fixes
Some checks failed
Gitea Actions / Run-Tests-On-Arm64 (push) Failing after 16m4s
Gitea Actions / Run-Tests-On-Amd64 (push) Failing after 30m18s

This commit is contained in:
Thomas Peterson 2025-05-18 15:58:50 +02:00
parent 43264fce3b
commit 2913dca789
73 changed files with 2800 additions and 1460 deletions

View File

@ -56,7 +56,7 @@ services:
networks:
- network
smtp4dev:
image: registry.thomas-peterson.de/smtp4dev
image: registry.thomas-peterson.de/smtp4dev:manifest-amd64
restart: always
ports:
# Change the number before : to the port the web interface should be accessible on

View File

@ -133,7 +133,7 @@ RUN --mount=type=cache,target=/tmp/.composer \
# on production, we don't want test dependencies
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o --no-dev; \
else \
COMPOSER_HOME=/tmp/.composer composer install --no-scripts --no-plugins --no-progress -o; \
COMPOSER_HOME=/tmp/.composer composer update --ignore-platform-reqs --no-scripts --no-plugins --no-progress -o; \
fi
# copy the full codebase
@ -170,6 +170,6 @@ COPY --from=codebase --chown=$APP_USER_NAME:$APP_GROUP_NAME /codebase $APP_CODE_
RUN echo "root ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users" && \
echo "${APP_USER_NAME} ALL=(ALL) NOPASSWD: ALL " | tee -a "/etc/sudoers.d/users"
RUN pecl install xdebug
RUN pecl install https://xdebug.org/files/xdebug-3.4.2.tgz
ENV APP_ENV=dev

View File

@ -1,8 +1,12 @@
#!/bin/bash
# start-cron.sh
touch /var/log/cron.log
touch /var/log/cronD.log
touch /var/log/cronH.log
rm -R /data/www/new/var/cache/*
rm -R /data/www/new/var/log/*
chmod -R 0777 /data/www/new/var/cache
chmod -R 0777 /data/www/new/var/log
chmod 0777 /var/log/cron.log
chmod 0777 /var/log/cronD.log
chmod 0777 /var/log/cronH.log

View File

@ -5,5 +5,7 @@ BASH_ENV=/container.env
* * * * * root chmod -R 0777 /data/www/old/market/steplayouter >> /var/log/cron.log 2>&1
* * * * * root chmod -R 0777 /data/www/new/web/uploads/media >> /var/log/cron.log 2>&1
* * * * * root chmod -R 0777 /data/www/new/web/media >> /var/log/cron.log 2>&1
* * * * * www-data cd /data/www/new/web && /usr/local/bin/php /data/www/new/bin/console application:queue:do >> /var/log/cron.log 2>&1
* * * * * www-data cd /data/www/new/web && /usr/local/bin/php /data/www/new/bin/console application:queue:doEveryMinute >> /var/log/cron.log 2>&1
@daily www-data cd /data/www/new/web && /usr/local/bin/php /data/www/new/bin/console application:queue:doEveryDay >> /var/log/cronD.log 2>&1
@hourly www-data cd /data/www/new/web && /usr/local/bin/php /data/www/new/bin/console application:queue:doEveryHour >> /var/log/cronH.log 2>&1
#

View File

@ -4,7 +4,7 @@ error_log = /proc/self/fd/2
access.log = /proc/self/fd/1
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
catch_workers_output = yes
rlimit_core = unlimited
user = __APP_USER_NAME
group = __APP_GROUP_NAME
listen = 0.0.0.0:9000

View File

@ -26,16 +26,6 @@
}
}
},
"@symfony/ux-turbo": {
"turbo-core": {
"enabled": true,
"fetch": "eager"
},
"mercure-turbo-stream": {
"enabled": false,
"fetch": "eager"
}
},
"@symfony/ux-vue": {
"vue": {
"enabled": true,

View File

@ -1,65 +1,50 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['dialog', 'dynamicContent'];
static targets = ['dialog'];
observer = null;
connect() {
if (this.hasDynamicContentTarget) {
// when the content changes, call this.open()
this.observer = new MutationObserver(() => {
const shouldOpen = this.dynamicContentTarget.innerHTML.trim().length > 0;
if (shouldOpen && !this.dialogTarget.open) {
this.open();
} else if (!shouldOpen && this.dialogTarget.open) {
this.close();
}
});
this.observer.observe(this.dynamicContentTarget, {
childList: true,
characterData: true,
subtree: true
});
}
}
disconnect() {
if (this.observer) {
this.observer.disconnect();
}
if (this.dialogTarget.open) {
this.close();
}
}
open() {
open(e) {
this.element.getElementsByClassName('iframe')[0].innerHtml = "";
var htmlId = e.target.dataset.html_id;
var iframe = document.createElement('iframe');
iframe.classList.add("w-full");
iframe.classList.add("h-full");
iframe.src = e.target.dataset.href;
this.element.getElementsByClassName('iframe')[0].appendChild(iframe);
this.dialogTarget.showModal();
document.body.classList.add('overflow-hidden', 'blur-sm');
var $this = this;
window.addEventListener(htmlId, function(e) {
document.getElementById(htmlId).value = e.detail.id;
document.getElementById(htmlId + "-widget").classList.add('media-chooser--choosen');
document.getElementById(htmlId + "__preview__title").innerHtml = e.detail.title;
if (e.detail.thumbPath === "") {
} else {
document.getElementById(htmlId + "__preview__img").src = e.detail.thumbPath;
}
iframe.remove();
$this.close();
document.getElementById(htmlId).dispatchEvent(new Event('change', { bubbles: true }));
}, {once: true});
}
trash(e) {
var htmlId = e.target.dataset.html_id;
document.getElementById(htmlId).value = "";
document.getElementById(htmlId + "__preview__title").innerHtml = "";
document.getElementById(htmlId + "__preview__title").innerText = "";
document.getElementById(htmlId + "__preview__img").removeAttribute('src');
document.getElementById(htmlId + "__preview__img").removeAttribute('alt');
document.getElementById(htmlId + "__preview__img").removeAttribute('srcset');
document.getElementById(htmlId).dispatchEvent(new Event('change', { bubbles: true }));
}
close() {
this.dialogTarget.close();
document.body.classList.remove('overflow-hidden', 'blur-sm');
}
useMedia(e) {
let dataset = e.target.dataset;
document.getElementById(e.target.dataset.htmlId).value = e.target.dataset.id;
// Update preview
document.getElementById(e.target.dataset.htmlId + "-widget").classList.add('media-chooser--choosen');
document.getElementById(e.target.dataset.htmlId + "__preview__title").innerHtml = this.title;
if (e.target.dataset.thumbPath === "") {
} else {
document.getElementById(e.target.dataset.htmlId + "__preview__img").src = e.target.dataset.thumbPath;
}
// Close modal
this.close();
}
clickOutside(event) {
if (event.target === this.dialogTarget) {
this.dialogTarget.close();

View File

@ -71,7 +71,9 @@
@apply inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem];
}
.psc-button-secondary {
@apply inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-xs text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[1.8rem];
}
.form-label {
@apply block uppercase text-xs font-bold mb-2;

View File

@ -13,9 +13,10 @@
}
},
"require": {
"php": "8.1.*",
"php": "8.2.*",
"ext-ctype": "*",
"ext-iconv": "*",
"ext-mongodb": "^2",
"azuyalabs/yasumi": "^2.5",
"behat/transliterator": "^1.2@dev",
"bitandblack/colors": "^2.13",
@ -24,12 +25,11 @@
"cocur/slugify": "v3.1",
"composer/package-versions-deprecated": "^1.8",
"ddeboer/imap": "1.18.*",
"doctrine/annotations": "^1.0",
"doctrine/cache": "^1.11",
"doctrine/doctrine-bundle": "2.7.*",
"doctrine/mongodb-odm-bundle": "^4",
"doctrine/annotations": "^2",
"doctrine/cache": "^2",
"doctrine/doctrine-bundle": "^2",
"doctrine/mongodb-odm-bundle": "^5",
"doctrine/orm": "^2.7",
"dunglas/doctrine-json-odm": "^1.4",
"gabrielbull/ups-api": "dev-master",
"gregwar/captcha-bundle": "^2.2",
"guzzlehttp/guzzle": "^6",
@ -40,7 +40,7 @@
"knplabs/knp-menu-bundle": "^3",
"knplabs/knp-paginator-bundle": "5.9.*",
"lexik/form-filter-bundle": "^7",
"lexik/jwt-authentication-bundle": "2.16.*",
"lexik/jwt-authentication-bundle": "^3",
"liip/imagine-bundle": "2.9.*",
"mobiledetect/mobiledetectlib": "^2.8",
"mpdf/mpdf": "dev-qrcode",
@ -93,7 +93,6 @@
"symfony/ux-autocomplete": "^2.14",
"symfony/ux-chartjs": "^2.19",
"symfony/ux-live-component": "^2.12",
"symfony/ux-turbo": "^2.24",
"symfony/ux-twig-component": "^2.12",
"symfony/ux-vue": "^2.23",
"symfony/validator": "*",
@ -137,7 +136,7 @@
"sort-packages": true,
"optimize-autoloader": true,
"platform": {
"php": "8.1.12"
"php": "8.2.28"
},
"allow-plugins": {
"symfony/flex": true,

1270
src/new/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,5 @@ return [
Symfony\UX\Chartjs\ChartjsBundle::class => ['all' => true],
Symfonycasts\TailwindBundle\SymfonycastsTailwindBundle::class => ['all' => true],
Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true],
Dunglas\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle::class => ['all' => true],
Symfony\UX\Vue\VueBundle::class => ['all' => true],
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
];

View File

@ -5,5 +5,28 @@ declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('monolog', ['handlers' => ['main' => ['type' => 'stream', 'path' => '%kernel.logs_dir%/%kernel.environment%.log', 'level' => 'debug', 'channels' => ['!event']], 'console' => ['type' => 'console', 'process_psr_3_messages' => false, 'channels' => ['!event', '!doctrine', '!console']]]]);
$containerConfigurator->extension(
'monolog', [
'handlers' => [
'main' => [
'type' => 'stream',
'path' => '%kernel.logs_dir%/%kernel.environment%.log',
'level' => 'debug',
'channels' => [
'!event',
'!php'
]
],
'console' => [
'type' => 'console',
'process_psr_3_messages' => false,
'channels' => [
'!event',
'!doctrine',
'!console'
]
]
]
]
);
};

View File

@ -5,5 +5,10 @@ declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('lexik_jwt_authentication', ['secret_key' => '%env(resolve:JWT_SECRET_KEY)%', 'public_key' => '%env(resolve:JWT_PUBLIC_KEY)%', 'pass_phrase' => '%env(JWT_PASSPHRASE)%']);
$containerConfigurator->extension('lexik_jwt_authentication', [
'secret_key' => '%env(resolve:JWT_SECRET_KEY)%',
'public_key' => '%env(resolve:JWT_PUBLIC_KEY)%',
'user_id_claim' => 'uid',
'pass_phrase' => '%env(JWT_PASSPHRASE)%'
]);
};

View File

@ -15,11 +15,13 @@ use PSC\Shop\UserBundle\Security\ApiKey\ShopProvider;
use PSC\Shop\UserBundle\Security\User\UserProvider;
use PSC\Shop\UserBundle\Security\ZendAuthenticator;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension(
'security',
[
'session_fixation_strategy' => SessionAuthenticationStrategy::NONE,
'password_hashers' =>
[
Contact::class =>
@ -84,10 +86,14 @@ return static function (ContainerConfigurator $containerConfigurator): void {
['user_provider', 'shop_provider', 'instance_provider']
]
]
// 'database_token' => ['entity' => ['class' => Shop::class]],
// 'database_api_key' => ['entity' => ['class' => Instance::class]],
// 'database_token' => ['entity' => ['class' => Shop::class]],
// 'database_api_key' => ['entity' => ['class' => Instance::class]],
],
'firewalls' => [
'dev' => [
'security' => false,
'pattern' => '^/(_(profiler|wdt)|css|images|js)/',
],
'admin_secured_area' => [
'pattern' => '^/backend',
'provider' => 'user_provider',
@ -100,6 +106,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
'password_parameter' => 'password'
],
'logout' => [
'invalidate_session' => false,
'path' => 'psc_backend_logout',
'target' => 'psc_backend_login'
]
@ -125,7 +132,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
],
'custom_authenticators' => [
ApiKeyAuthenticator::class,
ZendAuthenticator::class,
ZendAuthenticator::class,
]
],
'storefront' => [

View File

@ -2,6 +2,7 @@
declare(strict_types=1);
use PSC\Shop\MediaBundle\Service\MediaManager;
use PSC\Shop\OrderBundle\Service\Order;
use PSC\System\SettingsBundle\Service\Instance;
use PSC\System\SettingsBundle\Service\Shop;
@ -19,7 +20,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
'instanceService' => service(Instance::class),
'shopService' => service(Shop::class),
'orderService' => service(Order::class),
'tokenService' => service(Token::class)
'tokenService' => service(Token::class),
'mediaService' => service(MediaManager::class)
]
]
);

View File

@ -20,7 +20,7 @@ class Shop
$tmp->id = $shopEntity->getUID();
$tmp->name = $shopEntity->getTitle();
$tmp->uuid = $shopEntity->getUuid();
$tmp->deleted = (bool)$shopEntity->isDeleted();
$tmp->disabled = (bool)$shopEntity->isDeleted();
$tmp->private = (bool)$shopEntity->isPrivate();
$tmp->basketField1 = (string)$shopEntity->getBasketfield1();
$tmp->basketField2 = (string)$shopEntity->getBasketfield2();
@ -33,7 +33,9 @@ class Shop
$domains = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Domain')->getAllByShopId($shopEntity);
$domainsTemp = [];
/** @var \PSC\Shop\EntityBundle\Entity\Domain $domain */
/**
* @var \PSC\Shop\EntityBundle\Entity\Domain $domain
*/
foreach ($domains as $domain) {
$domainsTemp[] = new Domain($domain->getUid(), $domain->getHost(), $domain->isLetsEncrypt());
}

View File

@ -22,11 +22,11 @@ class Shop
* @OA\Property(type="integer")
*/
public int $id = 0;
/**
/**
* @OA\Property(type="string", maxLength=255)
*/
public string $uuid = "";
/**
/**
* @OA\Property(type="string", maxLength=255)
*/
public string $name = "";
@ -58,15 +58,15 @@ class Shop
* @OA\Property(type="string", maxLength=255)
*/
public string $basketPosField2 = "";
/**
/**
* @OA\Property(type="array", @OA\Items(ref=@Model(type=\PSC\Component\ApiBundle\Model\Shop\Domain::class)))
*/
public array $domains = [];
/**
/**
* @OA\Property(type="boolean")
*/
public bool $deleted = false;
/**
public bool $disabled = false;
/**
* @OA\Property(type="boolean")
*/
public bool $private = false;

View File

@ -34,9 +34,13 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
class AccountType extends AbstractType
{
/** @var Field */
/**
* @var Field
*/
protected $fields;
/** @var General */
/**
* @var General
*/
protected $general;
protected $shop = null;
protected $formFactory;
@ -57,7 +61,8 @@ class AccountType extends AbstractType
$builder
->add('title', TextType::class, ['label' => 'Name'])
->add('payments', EntityType::class, array(
->add(
'payments', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Payment',
'choice_label' => 'title',
'choice_value' => 'uid',
@ -68,8 +73,10 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('u.shop = :shop')->andWhere('u.private = 1')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('shippings', EntityType::class, array(
)
)
->add(
'shippings', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Shipping',
'choice_label' => 'title',
'choice_value' => 'uid',
@ -80,8 +87,10 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('u.shop = :shop')->andWhere('u.private = 1')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('productGroups', EntityType::class, array(
)
)
->add(
'productGroups', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Productgroup',
'choice_label' => function (Productgroup $choice, $key, $value) {
@ -99,8 +108,10 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('u.shop = :shop')->andWhere('u.private = 1')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('parent', EntityType::class, array(
)
)
->add(
'parent', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Account',
'choice_label' => 'title',
'choice_value' => 'uid',
@ -112,8 +123,10 @@ class AccountType extends AbstractType
->join('u.shops', 's')
->where('s.uid = :shop')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('productsOrg', EntityType::class, array(
)
)
->add(
'productsOrg', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Product',
'choice_label' => 'nrTitle',
'multiple' => true,
@ -123,8 +136,10 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('u.shop = :shop')->andWhere('u.private = 1 AND u.originalProduct = 0')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('productsSub', EntityType::class, array(
)
)
->add(
'productsSub', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Product',
'choice_label' => 'nrTitle',
'required' => false,
@ -134,8 +149,10 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('u.shop = :shop')->andWhere('u.private = 1 AND u.originalProduct != 0')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
->add('cms', EntityType::class, array(
)
)
->add(
'cms', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Cms',
'choice_label' => 'title',
'choice_value' => 'uid',
@ -146,7 +163,8 @@ class AccountType extends AbstractType
return $er->createQueryBuilder('u')
->where('(u.shop = :shop OR u.uid in (' . implode(",", $tempCms) . '))')->andWhere('u.private = 1')->setParameter('shop', $this->shop->getSelectedShop()->getId());
}
))
)
)
->add('appendix', TextType::class, ['required' => false, 'label' => 'additive'])
->add('locked', CheckboxType::class, ['required' => false, 'label' => 'Locked'])
->add('street', TextType::class, ['required' => false, 'label' => 'street'])
@ -165,12 +183,14 @@ class AccountType extends AbstractType
->add('phone', TextType::class, ['required' => false, 'label' => 'number'])
->add('phoneAppendix', TextType::class, ['required' => false, 'label' => 'extension'])
->add('priceFactor', NumberType::class, array('required' => false, 'label' => 'factor', 'scale' => 2, 'html5' => true,
->add(
'priceFactor', NumberType::class, array('required' => false, 'label' => 'factor', 'scale' => 2, 'html5' => true,
'attr' => array(
'min' => -0.01,
'max' => 2.00,
'step' => 0.01,
)))
))
)
->add('mobileAreaCode', TextType::class, ['required' => false, 'label' => 'Countrycode'])
->add('mobilePrefix', TextType::class, ['required' => false, 'label' => 'prefix'])
@ -220,7 +240,9 @@ class AccountType extends AbstractType
->add('lastname2', TextType::class, ['required' => false, 'label' => 'lastname2'])
->add('calcValue1', TextType::class, ['required' => false, 'label' => 'value1'])
->add('calcValue2', TextType::class, ['required' => false, 'label' => 'value2']);
/** @var \PSC\System\PluginBundle\Form\Interfaces\Field $field */
/**
* @var \PSC\System\PluginBundle\Form\Interfaces\Field $field
*/
foreach ($this->fields->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::Account) as $field) {
$builder->add($field->buildForm($this->formFactory->createNamedBuilder($field->getGroup()), $options));
}
@ -235,10 +257,12 @@ class AccountType extends AbstractType
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
$resolver->setDefaults(
array(
'data_class' => 'PSC\Shop\EntityBundle\Entity\Account',
'cms' => [],
'translation_domain' => 'core_account_create_and_edit'
));
)
);
}
}

View File

@ -186,7 +186,7 @@ class ContactType extends AbstractType
))
->add('productsSub', EntityType::class, array(
'class' => 'PSC\Shop\EntityBundle\Entity\Product',
'choice_label' => 'title',
'choice_label' => 'nrTitle',
'choice_value' => 'uid',
'required' => false,
'multiple' => true,

View File

@ -30,6 +30,21 @@ class ContactRepository extends ServiceEntityRepository implements UserLoaderInt
{
parent::__construct($registry, Contact::class);
}
public function loadUserByUid($uuid)
{
$user = $this->createQueryBuilder('c')
->where('c.uid = :uid AND c.enable = 1')
->setParameter('uid', $uuid)
->getQuery()
->getOneOrNullResult();
if (null === $user) {
$message = sprintf('Unable to find an Contact identified by "%s".', $uuid);
throw new UserNotFoundException($message);
}
return $user;
}
public function loadUserByUsername($username)
{
@ -38,6 +53,10 @@ class ContactRepository extends ServiceEntityRepository implements UserLoaderInt
->setParameter('username', $username)
->getQuery()
->getOneOrNullResult();
if(null === $user) {
$user = $this->loadUserByUid($username);
}
if (null === $user) {
$message = sprintf('Unable to find an Contact identified by "%s".', $username);
throw new UserNotFoundException($message);

View File

@ -985,6 +985,12 @@ class Product
return $this->title;
}
public function getTitleSubTitle(): ?string
{
return $this->title . ' ' . $this->subTitle;
}
public function setTitle(?string $title): void
{
$this->title = $title;
@ -2871,7 +2877,7 @@ class Product
public function getNrTitle()
{
return $this->nrIntern . ' ' . $this->title;
return $this->nrIntern . ' ' . $this->title . ' ' . $this->subTitle;
}
/**

View File

@ -4,6 +4,7 @@ namespace PSC\Shop\EntityBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Attribute\Groups;
#[ORM\Table(name: 'shop')]
#[ORM\Entity(repositoryClass: 'PSC\Shop\EntityBundle\Repository\ShopRepository')]

View File

@ -8,6 +8,8 @@ use Doctrine\ORM\EntityManagerInterface;
use PSC\Shop\MediaBundle\Helper\MediaManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
@ -18,71 +20,19 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/
class TWMediaType extends AbstractType
{
/**
* @var MediaManager
*/
protected $mediaManager;
/**
* @var \Doctrine\ODM\MongoDB\DocumentManager
*/
protected $mongoManager;
/**
* @param MediaManager $mediaManager The media manager
* @param EntityManagerInterface $objectManager The media manager
* @param DocumentManager $mongoManager The media manager
*/
public function __construct(MediaManager $mediaManager, DocumentManager $mongoManager)
{
$this->mediaManager = $mediaManager;
$this->mongoManager = $mongoManager;
}
/**
* Builds the form.
*
* This method is called for each type in the hierarchy starting form the
* top most type. Type extensions can further modify the form.
*
* @param FormBuilderInterface $builder The form builder
* @param array $options The options
*
* @see FormTypeExtensionInterface::buildForm()
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addViewTransformer(
new IdToMediaTransformer($this->mongoManager, $options['current_value_container']),
true
);
$builder->setAttribute('chooser', $options['chooser']);
$builder->setAttribute('mediatype', $options['mediatype']);
}
/**
* @return string
*/
public function getParent()
{
return FormType::class;
}
/**
* Sets the default options for this type.
*
* @param OptionsResolver $resolver The resolver for the options.
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'compound' => false,
'chooser' => 'psc_shop_media_backend_folder_tw',
'mediatype' => null,
'current_value_container' => new CurrentValueContainer(),
)
);
return TextType::class;
}
/**
@ -95,9 +45,6 @@ class TWMediaType extends AbstractType
return 'tw_media';
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['chooser'] = $form->getConfig()->getAttribute('chooser');

View File

@ -6,7 +6,7 @@ class MediaItem
{
public ?string $name;
public ?string $description;
public ?string $description = null;
public ?string $media;

View File

@ -1,6 +1,6 @@
{% extends 'modalFrame.html.twig' %}
{% extends 'backend_layout.html.twig' %}
{% block body %}
{% block appContent %}
<div class="row">
<div class="col-md-3">
{{ form_start(folderForm, { 'attr': {'class': ''}}) }}
@ -134,14 +134,13 @@
<td class="text-end">
{% if modal %}
{% if isImage %}
<a href="javascript:void(0)" alt="{{ media.originalFilename }}" class="js-url-chooser-media-select btn btn-primary btn-sm" data-thumb-path="{{ imageurl }}" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}">Einfügen</a>
<button href="javascript:void(0)" alt="{{ media.originalFilename }}" class="js-url-chooser-media-select btn btn-primary btn-sm" type="button" data-action="modal#useMedia" data-thumb-path="{{ imageurl }}" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}" data-html-id="{{ htmlId }}">Einfügen</button>
{% else %}
<a href="javascript:void(0)" alt="{{ media.originalFilename }}" class="js-url-chooser-media-select btn btn-primary btn-sm" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}">Einfügen</a>
{% endif %}
{% endif %}
<a href="{{ path('psc_shop_media_backend_upload_swap', {folder: selectedFolder.id, media: media.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-sm btn-warning">Tauschen</a>
<a href="{{ path('psc_shop_media_backend_media_detail', {folder: selectedFolder.id, uuid: media.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-sm btn-info">Bearbeiten</a>
<button type="button" data-action="modal#useMedia" data-thumb-path="{{ imageurl }}" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}" data-html-id="{{ htmlId }}">Close</button>
</td>
</tr>
{% endfor %}
@ -155,3 +154,16 @@
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="module">
import $ from 'jquery'
$(document).ready(function() {
$("button[data-action='modal#useMedia']").click(function() {
const event = new CustomEvent("{{ htmlId }}", {detail: {thumbPath: $(this).attr('data-thumb-path'), path: $(this).attr('data-path'), title: $(this).attr('data-title'), id: $(this).attr('data-id')}});
window.parent.dispatchEvent(event);
});
});
</script>
{% endblock %}

View File

@ -2,13 +2,12 @@
{% apply spaceless %}
<div id="{{ id }}-widget" class="media-chooser {% if(value.ent is defined) %}media-chooser--choosen{% endif %}">
<!-- Hidden input -->
<input id="{{ id }}" type="hidden" name="{{ full_name }}" value="{% if(value.id is defined) %}{{ value.id }}{% endif %}">
<input id="{{ id }}" type="hidden" name="{{ full_name }}" value="{{value}}">
<!-- Preview -->
<div class="media-chooser__preview">
<figure class="thumbnail">
{% if(value.ent is defined) %}
{% set media = value.ent %}
{% if(value is defined and value != "") %}
{% set media = mediaService.getMedia(value) %}
{% set handler = mediamanager.getHandler(media) %}
{% set imageurl = handler.getImageUrl(media, app.request.basePath) %}
{% if imageurl is not empty and media.location == 'local' %}
@ -37,18 +36,33 @@
</figure>
</div>
<a
data-turbo-frame="modal"
data-action="modal#mediaSelect"
href="{{ path(chooser, {'uuid': 0, 'modal': 1, 'htmlId' : id}) }}"
class="flex items-center space-x-1 bg-psc-500 hover:bg-blue-700 text-white text-sm font-bold px-4 rounded"
>Auswählen</a>
<div data-controller="modal">
<button
data-action="modal#open"
data-html_id="{{id}}"
data-href="{{ path('psc_shop_media_backend_folder_tw', {'uuid': 0, 'modal': 1, 'htmlId' : id}) }}"
class="flex items-center space-x-1 bg-psc-500 hover:bg-blue-700 text-white text-sm font-bold px-4 rounded"
type="button"
>Auswählen</button>
<button type="button"
data-action="modal#trash"
data-html_id="{{id}}">
<i data-html_id="{{id}}" class="fa fa-trash"></i>
</button>
<button type="button" id="{{ id }}__preview__del-btn" class="js-media-chooser-del-preview-btn btn btn-danger media-chooser__preview__del-btn" data-linked-id="{{ id }}">
<i class="fa fa-trash"></i>
</button>
<dialog
class="open:flex bg-gray-800 rounded-lg shadow-xl inset-0 w-full md:w-fit md:max-w-[50%] md:min-w-[50%] h-full"
data-action="close->modal#close click->modal#clickOutside"
data-modal-target="dialog"
>
<div class="flex grow p-5 h-full iframe">
</div>
</dialog>
</div>
<!-- Select Button -->
</div>
</div>
{% endapply %}
{% endblock %}

View File

@ -0,0 +1,65 @@
{% block tw_media_widget %}
{% apply spaceless %}
<div id="{{ id }}-widget" class="media-chooser {% if(value.ent is defined) %}media-chooser--choosen{% endif %}">
<!-- Hidden input -->
<input id="{{ id }}" type="hidden" name="{{ full_name }}" value="{% if(value.id is defined) %}{{ value.id }}{% endif %}">
<!-- Preview -->
<div class="media-chooser__preview">
<figure class="thumbnail">
{% if(value.ent is defined) %}
{% set media = value.ent %}
{% set handler = mediamanager.getHandler(media) %}
{% set imageurl = handler.getImageUrl(media, app.request.basePath) %}
{% if imageurl is not empty and media.location == 'local' %}
{% if imageurl|lower|split('.')|last == 'svg' or 'image/svg' in media.contentType %}
{% set imageurlretina = imageurl %}
{% else %}
{% set imageurlretina = asset(imageurl | imagine_filter('media_list_thumbnail_retina')) %}
{% set imageurl = asset(imageurl | imagine_filter('media_list_thumbnail')) %}
{% endif %}
{% endif %}
{% if imageurl %}
<img src="{{ imageurl }}" srcset="{{ imageurl }} 1x, {{ imageurlretina is defined ? ', ' ~ imageurlretina ~ " 2x" }}" alt="{{ media.title }}" id="{{ id }}__preview__img" class="thumbnail-img media-chooser__preview__img">
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title">
{{ media.title }}
</figcaption>
{% else %}
<i class="fas fa-file-o media-thumbnail__icon"></i>
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title">
{{ media.title }}
</figcaption>
{% endif %}
{% else %}
<img id="{{ id }}__preview__img" class="thumbnail-img media-chooser__preview__img">
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title"></figcaption>
{% endif %}
</figure>
</div>
<div data-controller="modal">
<button
data-action="modal#open"
data-html_id="{{id}}"
data-href="{{ path(chooser, {'uuid': 0, 'modal': 1, 'htmlId' : id}) }}"
class="flex items-center space-x-1 bg-psc-500 hover:bg-blue-700 text-white text-sm font-bold px-4 rounded"
type="button"
>Auswählen</button>
<dialog
class="open:flex bg-gray-800 rounded-lg shadow-xl inset-0 w-full md:w-fit md:max-w-[50%] md:min-w-[50%] h-full"
data-action="close->modal#close click->modal#clickOutside"
data-modal-target="dialog"
>
<div class="flex grow p-5 h-full iframe">
</div>
</dialog>
</div>
<button type="button" id="{{ id }}__preview__del-btn" class="js-media-chooser-del-preview-btn btn btn-danger media-chooser__preview__del-btn" data-linked-id="{{ id }}">
<i class="fa fa-trash"></i>
</button>
<!-- Select Button -->
</div>
{% endapply %}
{% endblock %}

View File

@ -57,12 +57,11 @@ class EditController extends AbstractController
/**
* Create
*
*
* @param Request $request
* @param SessionInterface $session
* @param Field $field
* @param EntityManagerInterface $entityManager
* @param \PSC\System\SettingsBundle\Service\Shop $shopService
* @param Request $request
* @param SessionInterface $session
* @param Field $field
* @param EntityManagerInterface $entityManager
* @param \PSC\System\SettingsBundle\Service\Shop $shopService
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Doctrine\ORM\ORMException
*/
@ -72,7 +71,9 @@ class EditController extends AbstractController
{
$customFields = $field->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::News);
$customGroups = $field->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::News);
/** @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop */
/**
* @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop
*/
$selectedShop = $shopService->getSelectedShop();
$news = new News();
$news->setShop($selectedShop);
@ -97,13 +98,12 @@ class EditController extends AbstractController
/**
* edit
*
*
* @param Request $request
* @param Field $field
* @param SessionInterface $session
* @param EntityManagerInterface $entityManager
* @param \PSC\System\SettingsBundle\Service\Shop $shopService
* @param $uid
* @param Request $request
* @param Field $field
* @param SessionInterface $session
* @param EntityManagerInterface $entityManager
* @param \PSC\System\SettingsBundle\Service\Shop $shopService
* @param $uid
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Doctrine\ORM\ORMException
*/
@ -113,9 +113,13 @@ class EditController extends AbstractController
{
$customFields = $field->getFields(\PSC\System\PluginBundle\Form\Interfaces\Field::News);
$customGroups = $field->getGroups(\PSC\System\PluginBundle\Form\Interfaces\Field::News);
/** @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop */
/**
* @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop
*/
$selectedShop = $shopService->getSelectedShop();
/** @var News $news */
/**
* @var News $news
*/
$news = $entityManager
->getRepository('PSC\Shop\NewsBundle\Entity\News')->findOneBy(array('uid' => $uid, 'shop' => $selectedShop));
$form = $this->createForm(NewsType::class, $news);
@ -126,8 +130,11 @@ class EditController extends AbstractController
$entityManager->flush();
$session->getFlashBag()->add('success', 'News Entry \'' . $news->getTitle() . '\' has been updated!');
$this->logService->createLogEntry($selectedShop, $this->getUser(), LogEntry::INFO, PSCShopNewsBundle::class, $news->getTitle(), "News Entry saved");
return $this->redirectToRoute('psc_shop_news_backend_list');
// return $this->redirectToRoute('psc_shop_news_backend_list');
}
$customGroups = [];
$customFields = [];
return array(
'news' => $news,
'form' => $form->createView(),
@ -140,11 +147,10 @@ class EditController extends AbstractController
/**
* remove
*
*
* @param Request $request
* @param SessionInterface $session
* @param EntityManagerInterface $entityManager
* @param $uid
* @param Request $request
* @param SessionInterface $session
* @param EntityManagerInterface $entityManager
* @param $uid
* @return array|\Symfony\Component\HttpFoundation\RedirectResponse
*/
#[Route(path: '/edit/delete/{uid}', name: 'psc_shop_news_backend_delete')]
@ -152,7 +158,9 @@ class EditController extends AbstractController
public function deleteAction(Request $request, SessionInterface $session, EntityManagerInterface $entityManager, \PSC\System\SettingsBundle\Service\Shop $shopService, $uid)
{
$news = $entityManager->getRepository('PSC\Shop\NewsBundle\Entity\News')->findOneBy(['uid' => $uid]);
/** @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop */
/**
* @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop
*/
$selectedShop = $shopService->getSelectedShop();
$form = $this->createForm(DeleteType::class);
$form->handleRequest($request);

View File

@ -15,12 +15,18 @@ namespace PSC\Shop\NewsBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use PSC\Shop\MediaBundle\Model\MediaItem;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Serializer\Attribute\Ignore;
use Symfony\Component\Serializer\Attribute\MaxDepth;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
/**
* Cms
*
*
* @package PSC\Shop\News
* @subpackage Entitys
*/
@ -54,8 +60,8 @@ class News
*
* @var string
*/
#[ORM\Column(name: 'einleitung', type: 'string', length: 255)]
protected $introduction;
#[ORM\Column(name: 'einleitung', type: 'string', length: 255, nullable: true)]
protected ?string $introduction;
/**
* Language
*
@ -68,27 +74,28 @@ class News
*
* @var string
*/
#[ORM\Column(name: 'text', type: 'string')]
protected $text;
#[ORM\Column(name: 'text', type: 'string', nullable: true)]
protected ?string $text;
/**
* Shop zu welcher die News gehört
*
* @var int
*/
#[ORM\ManyToOne(targetEntity: 'PSC\Shop\EntityBundle\Entity\Shop')]
#[Ignore]
#[ORM\JoinColumn(name: 'shop_id', referencedColumnName: 'id')]
protected $shop;
#[ORM\Column(name: 'sort_date', type: 'date')]
#[ORM\Column(name: 'sort_date', type: 'date', nullable: true)]
protected $sortDate;
#[ORM\Column(name: 'from_date', type: 'datetime')]
#[ORM\Column(name: 'from_date', type: 'datetime', nullable: true)]
protected ?\DateTime $fromDate;
#[ORM\Column(name: 'to_date', type: 'datetime')]
#[ORM\Column(name: 'to_date', type: 'datetime', nullable: true)]
protected ?\DateTime $toDate;
#[ORM\Column(name: 'media', type: 'json_document', options: ['jsonb' => true])]
public $media = [];
#[ORM\Column(type: 'json')]
protected ?string $media = null;
/**
* enable
*
@ -99,8 +106,8 @@ class News
public function __construct()
{
$this->media = new ArrayCollection();
}
public function getUid()
{
return $this->uid;
@ -261,4 +268,29 @@ class News
{
$this->toDate = $toDate;
}
public function setMedia(array $media): void
{
$encoders = [new JsonEncoder()];
$normalizers = [new ObjectNormalizer(), new ArrayDenormalizer()];
$serializer = new Serializer($normalizers, $encoders);
$this->media = $serializer->serialize($media, 'json');
}
public function getMedia(): array
{
if($this->media === null) {
return [];
}
$encoders = [new JsonEncoder()];
$normalizers = [new ObjectNormalizer(), new ArrayDenormalizer()];
$serializer = new Serializer($normalizers, $encoders);
return $serializer->deserialize($this->media, MediaItem::class. '[]', 'json');
}
}

View File

@ -1,130 +1,30 @@
{% extends 'backend_base.html.twig' %}
{% extends 'backend_tailwind_base.html.twig' %}
{% form_theme form 'tailwind_formtheme.html.twig' %}
{% trans_default_domain 'core_news_edit' %}
{% block header %}
<div>
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 0 1-2.25 2.25M16.5 7.5V18a2.25 2.25 0 0 0 2.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 0 0 2.25 2.25h13.5M6 7.5h3v3H6v-3Z" />
</svg>
{{ 'News'|trans }} {{ 'create'|trans }}</h1>
</div>
<div class="flex flex-wrap items-center gap-4 justify-start shrink-0">
<a href="{{ path('psc_shop_news_backend_list') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-sm text-white shadow-lg bg-psc-500 hover:bg-psc-600 hover:ring-2 hover:ring-psc-500 hover:ring-offset-2 min-h-[2.25rem]">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
{{ 'back'|trans }}</a>
</div>
{% endblock %}
{% block body %}
<div class="w-full">
{{ component('NewsForm', {
form: form,
initialFormData: news,
customGroups: customGroups
}) }}
</div>
{% endblock %}
<div class="header">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<h3>
<i class="fa-fw fa fa-newspaper"></i>
News <span>>
erstellen </span>
</h3>
</div>
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 text-end">
<a href="{{ path("psc_shop_news_backend_list") }}" class="btn btn-default btn-sm"><i class="fa fa-lg fa-fw fa-arrow-left"></i> Zurück</a>
</div>
</div>
</div>
<div class="body">
{{ form_start(form, { 'attr': {'class': ''}}) }}
<div class="panel">
<div class="header">
<h4>{{ news.title }}</h4>
</div>
<div class="body">
<div class="row">
<div class="col-md-2">
<ul class="nav nav-pills flex-column" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" href="#all" role="tab">Allgemein</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#text" role="tab">Text</a>
</li>
{% for customGroup in customGroups %}
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#{{ customGroup.id }}" role="tab">{{ customGroup.title }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="col-md-10">
<div class="tab-content">
<div class="tab-pane active" id="all" role="tabpanel">
<div class="row">
<div class="col-md-4">
<div class="row mb-3">
<label class="col-md-3 form-control-label">{{ form_label(form.title) }}</label>
<div class="col-md-9">
{{ form_widget(form.title) }}
</div>
</div>
</div>
<div class="col-md-4">
<div class="row mb-3">
<label class="col-md-3 form-control-label">{{ form_label(form.url) }}</label>
<div class="col-md-9">
{{ form_widget(form.url) }}
</div>
</div>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-md-6">{{ form_widget(form.enable) }}</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="row mb-3">
<label class="col-md-3 form-control-label">{{ form_label(form.sortDate) }}</label>
<div class="col-md-9">
{{ form_widget(form.sortDate) }}
</div>
</div>
</div>
<div class="col-md-4">
<div class="row mb-3">
<label class="col-md-3 form-control-label">{{ form_label(form.language) }}</label>
<div class="col-md-9">
{{ form_widget(form.language) }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="row mb-3">
<label class="col-md-1 form-control-label">{{ form_label(form.introduction) }}</label>
<div class="col-md-11">
{{ form_widget(form.introduction) }}
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="text" role="tabpanel">
{{ form_widget(form.text, {attr: {'class': 'form-control summernote'}}) }}
</div>
{% for customGroup in customGroups %}
<div class="tab-pane" id="{{ customGroup.id }}" role="tabpanel">
{% for customField in customFields %}
{% if customField.group == customGroup.id and customField.getTemplate %}
{{ include(customField.getTemplate, { 'form': form }) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<div class="panel">
<div class="body">
<div class="row mb-3">
<div class="col-md-offset-1 col-md-11">
{{ form_widget(form.save, {attr: {class: 'btn btn-primary btn-sm'}}) }}
</div>
</div>
</div>
</div>
{{ form_end(form) }}
</div>
{{ summernote_mediabundle_init('default') }}
{% endblock %}

View File

@ -21,10 +21,10 @@
{% block body %}
<div class="w-full">
{{ component('NewsForm', {
form: form,
news: news,
customGroups: customGroups
}) }}
form: form,
initialFormData: news,
customGroups: customGroups
}) }}
</div>
<h4 class="text-psc text-xl font-medium flex flex-row gap-1 mb-2">
@ -32,36 +32,37 @@
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75 2.25 12l4.179 2.25m0-4.5 5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 0L21.75 12l-4.179 2.25m0 0 4.179 2.25L12 21.75 2.25 16.5l4.179-2.25m11.142 0-5.571 3-5.571-3" />
</svg>
{{ 'Changes'|trans }}</h4>
<div class="rounded-sm border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div class="w-full grid grid-cols-4 border-t border-stroke px-4 bg-slate-100 py-4.5 dark:border-strokedark sm:grid-cols-8 md:px-6 2xl:px-7.5">
<div class="hidden sm:flex col-span-1 px-6 py-3">
{{ 'Date'|trans }}
<div class="rounded-sm border bg-white px-6 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div class="w-full rounded-lg border border-stone-200">
<div class="grid grid-cols-4 border-b border-stone-200 bg-stone-100 text-sm font-medium text-stone-600 dark:bg-surface-dark">
<div class="hidden sm:flex col-span-1 px-6 py-3 font-bold">
{{ 'Date'|trans }}
</div>
<div class="col-span-1 px-6 py-3 font-bold">
{{ 'Username'|trans }}
</div>
<div class="col-span-2 px-6 py-3 font-bold">
{{ 'Changes'|trans }}
</div>
</div>
<div class="col-span-1 px-6 py-3">
{{ 'Username'|trans }}
{% for change in changes %}
<div class="grid grid-cols-4 group text-sm text-stone-800 dark:text-white">
<div class="hidden sm:flex col-span-1 px-6 py-3">
{{ change.created|date('H:i:s d.m.Y') }}
</div>
<div class="col-span-1 px-6 py-3">
{{ change.username }}
</div>
<div class="col-span-2 px-6 py-3">
{% for key, set in change.changeset %}
{% if set[1] is not iterable %}
<strong>{{ key }}</strong> <span class="badge bg-danger"><del>{{ set[0] }}</del></span><span class="badge bg-success">{% if set[1] is null %}0{% else %}{{ set[1] }}{% endif %}</span></br>
{% endif %}
{% endfor %}
</div>
</div>
<div class="col-span-2 px-6 py-3">
{{ 'Changes'|trans }}
</div>
</div>
{% for change in changes %}
<div class="w-full grid grid-cols-4 border-t border-stroke px-4 bg-slate-100 py-4.5 dark:border-strokedark sm:grid-cols-8 md:px-6 2xl:px-7.5">
<div class="hidden sm:flex col-span-1 px-6 py-3">
{{ change.created|date('H:i:s d.m.Y') }}
</div>
<div class="col-span-1 px-6 py-3">
{{ change.username }}
</div>
<div class="col-span-2 px-6 py-3">
{% for key, set in change.changeset %}
{% if set[1] is not iterable %}
<strong>{{ key }}</strong> <span class="badge bg-danger"><del>{{ set[0] }}</del></span><span class="badge bg-success">{% if set[1] is null %}0{% else %}{{ set[1] }}{% endif %}</span></br>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
{% endblock %}

View File

@ -2,7 +2,7 @@
{{ form_start(form, {attr: {class: ''}}) }}
<div class="tab-group flex-none md:flex w-full" data-dui-orientation="vertical">
<div role="tablist" class="relative mr-5 rounded-sm flex flex-col p-1 w-full md:w-2/12">
<div class="absolute top-0 left-0 right-0 mx-1 text-white w-auto bg-psc-500 rounded-sm shadow-sm transition-all duration-300 transform scale-x-0 translate-x-0 tab-indicator z-0"></div>
<div class="tab-indicator absolute left-0 w-1 bg-psc-500 transition-transform duration-300"></div>
<a href="#" class="tab-link flex items-center text-sm active px-4 py-2 relative" data-dui-tab-target="all">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M21 7.35304L21 16.647C21 16.8649 20.8819 17.0656 20.6914 17.1715L12.2914 21.8381C12.1102 21.9388 11.8898 21.9388 11.7086 21.8381L3.30861 17.1715C3.11814 17.0656 3 16.8649 3 16.647L2.99998 7.35304C2.99998 7.13514 3.11812 6.93437 3.3086 6.82855L11.7086 2.16188C11.8898 2.06121 12.1102 2.06121 12.2914 2.16188L20.6914 6.82855C20.8818 6.93437 21 7.13514 21 7.35304Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
@ -72,36 +72,37 @@
{{ form_widget(form.text) }}
</div>
<div id="media" class="tab-content w-full text-stone-500 text-sm hidden p-4">
<table class="table table-borderless form-no-mb">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Media</td>
<td></td>
</tr>
</thead>
<tbody>
{% for media_form in form.media %}
<div class="w-full overflow-hidden rounded-lg border border-stone-200">
<table class="w-full">
<thead class="border-b border-stone-200 bg-stone-100 text-sm font-medium text-stone-600 dark:bg-surface-dark"">
<tr>
<td>
{{ form_row(media_form.name) }}
</td>
<td>
{{ form_row(media_form.description) }}
</td>
<td>
{{ form_row(media_form.media) }}
</td>
<td>
{{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }}
</td>
<td class="px-2.5 py-2 text-start font-medium">Name</td>
<td class="px-2.5 py-2 text-start font-medium">Description</td>
<td class="px-2.5 py-2 text-start font-medium">Media</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_widget(form.media.vars.button_add, {label: '+ Add Media', attr: {class: 'btn btn-outline-primary'}}) }}
</thead>
<tbody class="group text-sm text-stone-800 dark:text-white">
{% for media_form in form.media %}
<tr class="border-b border-stone-200 last:border-0">
<td class="p-3">
{{ form_row(media_form.name) }}
</td>
<td class="p-3">
{{ form_row(media_form.description) }}
</td>
<td class="p-3">
{{ form_row(media_form.media) }}
</td>
<td class="p-3">
{{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{{ form_widget(form.media.vars.button_add, {label: '+ Add Media', attr: {class: 'psc-button-secondary mt-1'}}) }}
</div>
{% if customGroups is defined %}
{% for customGroup in customGroups %}

View File

@ -17,8 +17,8 @@ class NewsForm extends AbstractController
use DefaultActionTrait;
use LiveCollectionTrait;
#[LiveProp(fieldName: 'formData')]
public ?News $news;
#[LiveProp]
public ?News $initialFormData;
public ?Array $customGroups;
@ -26,7 +26,7 @@ class NewsForm extends AbstractController
{
return $this->createForm(
NewsType::class,
$this->news
$this->initialFormData
);
}
}

View File

@ -113,7 +113,7 @@ class Order
return false;
}
protected function updateOrder(\PSC\Shop\OrderBundle\Model\Base $order)
public function updateOrder(\PSC\Shop\OrderBundle\Model\Base $order)
{
if ($this->load_only_order) {
die("Do Not Update");
@ -286,10 +286,12 @@ class Order
public function getLastOrders(int $limit = 10): array
{
$query = $this->entityManager
->createQuery('
->createQuery(
'
SELECT c FROM PSCEntityBundle:Order c
JOIN c.shop s
WHERE s.uid = :id ORDER BY c.created DESC')
WHERE s.uid = :id ORDER BY c.created DESC'
)
->setParameter('id', $this->shopService->getSelectedShop()->getUid())
->setMaxResults($limit);
try {

View File

@ -0,0 +1,122 @@
<?php
namespace PSC\Shop\QueueBundle\Command;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use PSC\Shop\EntityBundle\Document\Job;
use PSC\Shop\EntityBundle\Document\JobLog;
use PSC\Shop\EntityBundle\Document\Queue;
use PSC\Shop\EntityBundle\Entity\Shop;
use PSC\Shop\QueueBundle\Event\InternalEvent;
use PSC\Shop\QueueBundle\Service\Event\Manager;
use PSC\Shop\QueueBundle\Service\Event\Registry;
use PSC\System\PluginBundle\Document\Plugin;
use PSC\System\PluginBundle\Event\ClearCache;
use PSC\System\PluginBundle\Event\DeInstallPlugin;
use PSC\System\PluginBundle\Event\EveryRun;
use PSC\System\PluginBundle\Event\InstallPlugin;
use PSC\System\SettingsBundle\Document\LogEntry;
use PSC\System\SettingsBundle\Service\Log;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\FlockStore;
#[AsCommand(name: 'application:queue:doEveryDay')]
class DoEveryDayCommand extends Command
{
/**
* @var Manager
*/
private Manager $eventManager;
/**
* @var Registry
*/
private Registry $eventRegistry;
private \PSC\Shop\QueueBundle\Service\Queue\Registry $queueRegistry;
/**
* @var DocumentManager
*/
private DocumentManager $mongoDb;
/**
* @var KernelInterface
*/
private KernelInterface $kernel;
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
/**
* @var Log
*/
private Log $logService;
private iterable $internalQueues;
public function __construct(#[TaggedIterator('psc.queues.internal')] iterable $internalQueues, EntityManagerInterface $entityManager, Manager $eventManager, Registry $eventRegistry, \PSC\Shop\QueueBundle\Service\Queue\Registry $queueRegistry, DocumentManager $documentManager, KernelInterface $kernel, Log $logService, private readonly \Symfony\Component\DependencyInjection\ContainerInterface $containerService)
{
$this->eventManager = $eventManager;
$this->eventRegistry = $eventRegistry;
$this->queueRegistry = $queueRegistry;
$this->mongoDb = $documentManager;
$this->kernel = $kernel;
$this->entityManager = $entityManager;
$this->logService = $logService;
$this->internalQueues = $internalQueues;
// you *must* call the parent constructor
parent::__construct();
}
protected function configure()
{
$this
->setDescription('Run the Jobs');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$store = new FlockStore();
$factory = new LockFactory($store);
$lock = $factory->createLock('doEveryDayQueue');
if ($lock->acquire()) {
foreach ($this->internalQueues as $queue) {
$queue->execute();
}
$queues = $this->mongoDb
->getRepository('PSC\Shop\EntityBundle\Document\Queue')
->findBy(
array('eventType' => 'system_plugin_every_day', 'active' => true),
[
'pos' => 'ASC'
]
);
/**
* @var Queue $queue
*/
foreach ($queues as $queue) {
$queueObj = $this->queueRegistry->get($queue->getQueueType());
try {
$success = $queueObj->execute(new EveryRun(), $queue);
} catch (\Exception $exception) {
$this->logService->createLogEntry(new Shop(), LogEntry::ERROR, "Cron", "", $exception->getMessage(), []);
}
}
$this->eventManager->clearManager();
}
date_default_timezone_set('Europe/Berlin');
$output->writeln("Successfully ".date('Y-m-d H:i:s'));
return 0;
}
}

View File

@ -0,0 +1,248 @@
<?php
namespace PSC\Shop\QueueBundle\Command;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use PSC\Shop\EntityBundle\Document\Job;
use PSC\Shop\EntityBundle\Document\JobLog;
use PSC\Shop\EntityBundle\Document\Queue;
use PSC\Shop\EntityBundle\Entity\Shop;
use PSC\Shop\QueueBundle\Event\InternalEvent;
use PSC\Shop\QueueBundle\Service\Event\Manager;
use PSC\Shop\QueueBundle\Service\Event\Registry;
use PSC\System\PluginBundle\Document\Plugin;
use PSC\System\PluginBundle\Event\ClearCache;
use PSC\System\PluginBundle\Event\DeInstallPlugin;
use PSC\System\PluginBundle\Event\EveryRun;
use PSC\System\PluginBundle\Event\InstallPlugin;
use PSC\System\SettingsBundle\Document\LogEntry;
use PSC\System\SettingsBundle\Service\Log;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\FlockStore;
#[AsCommand(name: 'application:queue:doEveryHour')]
class DoEveryHourCommand extends Command
{
/**
* @var Manager
*/
private Manager $eventManager;
/**
* @var Registry
*/
private Registry $eventRegistry;
private \PSC\Shop\QueueBundle\Service\Queue\Registry $queueRegistry;
/**
* @var DocumentManager
*/
private DocumentManager $mongoDb;
/**
* @var KernelInterface
*/
private KernelInterface $kernel;
/**
* @var EntityManagerInterface
*/
private EntityManagerInterface $entityManager;
/**
* @var Log
*/
private Log $logService;
private iterable $internalQueues;
public function __construct(#[TaggedIterator('psc.queues.internal')] iterable $internalQueues, EntityManagerInterface $entityManager, Manager $eventManager, Registry $eventRegistry, \PSC\Shop\QueueBundle\Service\Queue\Registry $queueRegistry, DocumentManager $documentManager, KernelInterface $kernel, Log $logService, private readonly \Symfony\Component\DependencyInjection\ContainerInterface $containerService)
{
$this->eventManager = $eventManager;
$this->eventRegistry = $eventRegistry;
$this->queueRegistry = $queueRegistry;
$this->mongoDb = $documentManager;
$this->kernel = $kernel;
$this->entityManager = $entityManager;
$this->logService = $logService;
$this->internalQueues = $internalQueues;
// you *must* call the parent constructor
parent::__construct();
}
protected function configure()
{
$this
->setDescription('Run the Jobs');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$store = new FlockStore();
$factory = new LockFactory($store);
$lock = $factory->createLock('doEveryHourQueue');
if ($lock->acquire()) {
foreach ($this->internalQueues as $queue) {
$queue->execute();
}
$queues = $this->mongoDb
->getRepository('PSC\Shop\EntityBundle\Document\Queue')
->findBy(
array('eventType' => 'system_plugin_every_hour', 'active' => true),
[
'pos' => 'ASC'
]
);
/**
* @var Queue $queue
*/
foreach ($queues as $queue) {
$queueObj = $this->queueRegistry->get($queue->getQueueType());
try {
$success = $queueObj->execute(new EveryRun(), $queue);
} catch (\Exception $exception) {
$this->logService->createLogEntry(new Shop(), LogEntry::ERROR, "Cron", "", $exception->getMessage(), []);
}
}
$this->eventManager->clearManager();
/**
* @var Job $job
*/
foreach ($this->eventManager->getAll() as $job) {
$canBeRemoved = true;
$event = $this->eventRegistry->get($job->getEvent());
if ($event instanceof ClearCache) {
$fs = new Filesystem();
//$fs->remove($this->kernel->getCacheDir());
} elseif ($event instanceof InstallPlugin) {
$event->setData($job->getData());
$event->setShop($job->getShop());
$install = $this->containerService->get($event->getInstallClass());
$install->execute();
$plugin = $this->mongoDb
->getRepository(Plugin::class)
->findOneBy(array('id' => (string)$event->getPlugin()));
$plugin->setShouldBeInstalled(false);
$this->mongoDb->persist($plugin);
} elseif ($event instanceof DeInstallPlugin) {
$event->setData($job->getData());
$event->setShop($job->getShop());
$deinstall = $this->containerService->get($event->getDeInstallClass());
$deinstall->execute();
$plugin = $this->mongoDb
->getRepository(Plugin::class)
->findOneBy(array('id' => (string)$event->getPlugin()));
$plugin->setInstalled(false);
$plugin->setShouldBeDeInstalled(false);
$this->mongoDb->persist($plugin);
} elseif ($event instanceof InternalEvent) {
$event->setData($job->getData());
$event->setShop($job->getShop());
} else {
$event->setData($job->getData());
$event->setShop($job->getShop());
$queues = $this->mongoDb
->getRepository(Queue::class)
->findBy(
array(
'shop' => $job->getShop(),
'active' => true,
'eventType' => $job->getEvent()
),
[
'pos' => 'ASC'
]
);
/**
* @var Queue $queue
*/
foreach ($queues as $queue) {
if (!$event->doProcess($queue)) {
continue;
}
$queueObj = $this->queueRegistry->get($queue->getQueueType());
/**
* @var JobLog $jobLog
*/
$jobLog = $this->mongoDb->getRepository(JobLog::class)->findOneBy(
[
'job' => $job->getId(),
'queue' => $queue->getId()
]
);
if ($jobLog) {
if ($jobLog->getError() == "") {
continue;
}
$jobLog->incCount();
if ($jobLog->getCount() > 2 && $jobLog->getError() != "") {
$canBeRemoved = false;
continue;
}
} else {
$jobLog = new JobLog();
$jobLog->setJob($job->getId());
$jobLog->setQueue($queue->getId());
}
$jobLog->setUpdated(new \DateTime());
try {
$success = $queueObj->execute($event, $queue);
if (!$success) {
$canBeRemoved = false;
$jobLog->setError($queueObj->getError());
} else {
$jobLog->setError("");
}
$this->mongoDb->persist($jobLog);
$this->mongoDb->flush();
} catch (\Exception $e) {
$response = $e->getResponse();
$message = $response->getContent(false);
$jobLog->setError($e->getMessage());
$this->mongoDb->persist($jobLog);
$this->mongoDb->flush();
$canBeRemoved = false;
}
}
}
if ($canBeRemoved) {
$this->eventManager->removeJob($job);
}
}
if (count($this->eventManager->getAll()) == 0) {
$this->mongoDb->createQueryBuilder(JobLog::class)->remove()->getQuery()->execute();
}
}
date_default_timezone_set('Europe/Berlin');
$output->writeln("Successfully ".date('Y-m-d H:i:s'));
return 0;
}
}

View File

@ -28,8 +28,8 @@ use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\FlockStore;
#[AsCommand(name: 'application:queue:do')]
class DoCommand extends Command
#[AsCommand(name: 'application:queue:doEveryMinute')]
class DoEveryMinuteCommand extends Command
{
/**
* @var Manager
@ -81,13 +81,10 @@ class DoCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output)
{
$store = new FlockStore();
$factory = new LockFactory($store);
$lock = $factory->createLock('doQueue');
$lock = $factory->createLock('doEveryMinuteQueue');
if ($lock->acquire()) {
foreach ($this->internalQueues as $queue) {

View File

@ -13,117 +13,122 @@ class Mail
*/
#[Field(type: 'string')]
protected $text;
/**
* @var string $textHtml
*/
/**
* @var string $textHtml
*/
#[Field(type: 'string')]
protected $textHtml;
/**
* @var string $from
*/
/**
* @var string $from
*/
#[Field(type: 'string')]
protected $from;
/**
* @var string $fromName
*/
/**
* @var string $fromName
*/
#[Field(type: 'string')]
protected $fromName;
/**
* @var string $to
*/
/**
* @var string $to
*/
#[Field(type: 'string')]
protected $to;
/**
* @var string $toName
*/
/**
* @var string $toName
*/
#[Field(type: 'string')]
protected $toName;
/**
* @var string $subject
*/
/**
* @var string $subject
*/
#[Field(type: 'string')]
protected $subject;
/**
* @var string $bcc
*/
/**
* @var string $bcc
*/
#[Field(type: 'string')]
protected $bcc;
/**
* @var boolean $sendInvoice
*/
/**
* @var boolean $sendInvoice
*/
#[Field(type: 'bool')]
protected $sendInvoice;
/**
* @var boolean $sendDelivery
*/
/**
* @var boolean $sendInvoice
*/
#[Field(type: 'bool')]
protected $sendXInvoice;
/**
* @var boolean $sendDelivery
*/
#[Field(type: 'bool')]
protected $sendDelivery;
/**
* @var boolean $sendLabel
*/
/**
* @var boolean $sendLabel
*/
#[Field(type: 'bool')]
protected $sendLabel;
/**
* @var boolean $sendOrder
*/
/**
* @var boolean $sendOrder
*/
#[Field(type: 'bool')]
protected $sendOrder;
/**
* @var boolean $sendOffer
*/
/**
* @var boolean $sendOffer
*/
#[Field(type: 'bool')]
protected $sendOffer;
/**
* @var boolean $sendJobticket
*/
/**
* @var boolean $sendJobticket
*/
#[Field(type: 'bool')]
protected $sendJobticket;
/**
* @var boolean $sendStorno
*/
/**
* @var boolean $sendStorno
*/
#[Field(type: 'bool')]
protected $sendStorno;
/**
* @var boolean $sendPosInvoice
*/
/**
* @var boolean $sendPosInvoice
*/
#[Field(type: 'bool')]
protected $sendPosInvoice;
/**
* @var boolean $sendPosDelivery
*/
/**
* @var boolean $sendPosDelivery
*/
#[Field(type: 'bool')]
protected $sendPosDelivery;
/**
* @var boolean $sendPosLabel
*/
/**
* @var boolean $sendPosLabel
*/
#[Field(type: 'bool')]
protected $sendPosLabel;
/**
* @var boolean $sendPosOrder
*/
/**
* @var boolean $sendPosOrder
*/
#[Field(type: 'bool')]
protected $sendPosOrder;
/**
* @var boolean $sendPosOffer
*/
/**
* @var boolean $sendPosOffer
*/
#[Field(type: 'bool')]
protected $sendPosOffer;
/**
* @var boolean $sendPosJobticket
*/
/**
* @var boolean $sendPosJobticket
*/
#[Field(type: 'bool')]
protected $sendPosJobticket;
/**
* @var boolean $sendPosStorno
*/
/**
* @var boolean $sendPosStorno
*/
#[Field(type: 'bool')]
protected $sendPosStorno;
/**
* @var array $files
*/
/**
* @var array $files
*/
#[Field(type: 'collection')]
protected $files;
/**
/**
* @return string
*/
public function getText()
@ -267,6 +272,23 @@ class Mail
$this->sendInvoice = $sendInvoice;
}
/**
* @return bool
*/
public function isSendXInvoice()
{
return $this->sendXInvoice;
}
/**
* @param bool $sendXInvoice
*/
public function setSendXInvoice($sendXInvoice)
{
$this->sendXInvoice = $sendXInvoice;
}
/**
* @return bool
*/
@ -490,4 +512,5 @@ class Mail
{
$this->sendPosJobticket = $sendPosJobticket;
}
}

View File

@ -93,6 +93,14 @@
</div>
</div>
</div>
<div class="col-md-1">
<div class="row mb-3">
{{ form_label(form.sendXInvoice) }}
<div class="col-md-12">
{{ form_widget(form.sendXInvoice) }}
</div>
</div>
</div>
<div class="col-md-1">
<div class="row mb-3">
{{ form_label(form.sendDelivery) }}
@ -337,4 +345,4 @@
$newLinkLi.before($newFormLi);
}
</script>
{% endverbatim %}
{% endverbatim %}

View File

@ -2,7 +2,7 @@
namespace PSC\Shop\QueueBundle\Type;
require_once(__DIR__ . '/../../../Shop/EntityBundle/Lagacy/TP_Basket_Item.php');
require_once __DIR__ . '/../../../Shop/EntityBundle/Lagacy/TP_Basket_Item.php';
use Doctrine\Bundle\MongoDBBundle\ManagerRegistry;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManager;
@ -56,7 +56,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
class Mail implements QueueInterface, ConfigurableElementInterface
{
/** @var Form */
/**
* @var Form
*/
protected $_formFactory = null;
protected $_entityManager = null;
protected $_doctrine_mongodb = null;
@ -66,8 +68,8 @@ class Mail implements QueueInterface, ConfigurableElementInterface
protected $_template = null;
protected $_error = null;
/**
* @var Log
*/
* @var Log
*/
protected Log $_logService;
public function __construct(TemplateVars $templateVars, Printing $printing, FormFactoryInterface $formFactory, EntityManagerInterface $entityManager, DocumentManager $doctrine_mongodb, MailerInterface $mailer, \Twig\Environment $template, Log $logService)
{
@ -125,6 +127,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$builder->add("toName", TextType::class, array('label' => 'An Name', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("subject", TextType::class, array('label' => 'Betreff*', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("bcc", TextType::class, array('label' => 'BCC (info@..,prod@...)', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendXInvoice", CheckboxType::class, array('label' => 'XRechnung anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendInvoice", CheckboxType::class, array('label' => 'Rechnung anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendDelivery", CheckboxType::class, array('label' => 'Lieferschein anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendOrder", CheckboxType::class, array('label' => 'Auftrag anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
@ -139,13 +142,15 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$builder->add("sendPosJobticket", CheckboxType::class, array('label' => 'Jobticket anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendPosLabel", CheckboxType::class, array('label' => 'Label anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add("sendPosStorno", CheckboxType::class, array('label' => 'Storno anfügen?', 'required' => false, 'attr' => array('class' => 'form-element')));
$builder->add('files', CollectionType::class, array(
$builder->add(
'files', CollectionType::class, array(
'entry_type' => FileType::class,
'entry_options' => array('label' => false),
'allow_add' => true,
'allow_delete' => true,
'label' => false
));
)
);
}
}
@ -164,6 +169,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$mail->setSubject($form->get('subject')->getData());
$mail->setBcc($form->get('bcc')->getData());
$mail->setSendInvoice($form->get('sendInvoice')->getData());
$mail->setSendXInvoice($form->get('sendXInvoice')->getData());
$mail->setSendDelivery($form->get('sendDelivery')->getData());
$mail->setSendOrder($form->get('sendOrder')->getData());
$mail->setSendOffer($form->get('sendOffer')->getData());
@ -196,6 +202,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$form->get('subject')->setData($queueObj->getQueueDocument()->getSubject());
$form->get('bcc')->setData($queueObj->getQueueDocument()->getBcc());
$form->get('sendInvoice')->setData($queueObj->getQueueDocument()->isSendInvoice());
$form->get('sendXInvoice')->setData($queueObj->getQueueDocument()->isSendXInvoice());
$form->get('sendDelivery')->setData($queueObj->getQueueDocument()->isSendDelivery());
$form->get('sendOrder')->setData($queueObj->getQueueDocument()->isSendOrder());
$form->get('sendOffer')->setData($queueObj->getQueueDocument()->isSendOffer());
@ -219,8 +226,8 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
/**
* @param EventInterface $event
* @param Queue $queue
* @param EventInterface $event
* @param Queue $queue
* @return bool
* @throws \Doctrine\ORM\OptimisticLockException
* @throws \MongoException
@ -229,12 +236,18 @@ class Mail implements QueueInterface, ConfigurableElementInterface
public function execute(EventInterface $event, Queue $queue)
{
/** @var \PSC\Shop\QueueBundle\Document\Queue\Mail $mailDoc */
/**
* @var \PSC\Shop\QueueBundle\Document\Queue\Mail $mailDoc
*/
$mailDoc = $queue->getQueueDocument();
$eventDoc = $queue->getEventDocument();
/** @var TemplateVars $templateVars */
/**
* @var TemplateVars $templateVars
*/
$templateVars = $this->_templateVars;
/** @var Printing $printing */
/**
* @var Printing $printing
*/
$printing = $this->_printing;
if ($event->isOverwriteQueueHandling()) {
try {
@ -265,10 +278,14 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($event instanceof Lock) {
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
$shopRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shop');
/** @var Shop $shop */
/**
* @var Shop $shop
*/
$shop = $shopRepo->findOneBy(array('uid' => $event->getShop()));
$params = array(
'contact' => $contact,
@ -295,17 +312,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($html) {
$message->html($html->render($params));
}
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Lock Mail send", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Lock Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($params),
'to' => $to->render($params),
'subject' => $subject->render($params)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Lock Mail error", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Lock Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -314,14 +335,20 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof UnLock || $event instanceof \PSC\Shop\QueueBundle\Event\Contact\Create || $event instanceof \PSC\Shop\QueueBundle\Event\Contact\Login) {
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
/** @var \PSC\Shop\EntityBundle\Document\Contact $contactObj */
/**
* @var \PSC\Shop\EntityBundle\Document\Contact $contactObj
*/
$contactObj = $this->_doctrine_mongodb
->getRepository('PSC\Shop\EntityBundle\Document\Contact')
->findOneBy(array('uid' => (string) $contact->getId()));
$shopRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shop');
/** @var Shop $shop */
/**
* @var Shop $shop
*/
$shop = $shopRepo->findOneBy(array('uid' => $event->getShop()));
$params = array(
'contact' => $contact,
@ -349,17 +376,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($html) {
$message->html($html->render($params));
}
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Login Mail send", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Login Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($params),
'to' => $to->render($params),
'subject' => $subject->render($params)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Login Mail error", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Login Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -368,10 +399,14 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof Start) {
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
$shopRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shop');
/** @var Shop $shop */
/**
* @var Shop $shop
*/
$shop = $shopRepo->findOneBy(array('uid' => $event->getShop()));
$contact->setPasswordResetUuid(Uuid::uuid4());
$contact->setPasswordResetDate(time());
@ -402,18 +437,22 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($html) {
$message->html($html->render($params));
}
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($params),
'to' => $to->render($params),
'subject' => $subject->render($params)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -422,10 +461,14 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof Finish) {
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
$shopRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shop');
/** @var Shop $shop */
/**
* @var Shop $shop
*/
$shop = $shopRepo->findOneBy(array('uid' => $event->getShop()));
$password = $this->generatePassword(10);
$contact->setPassword(password_hash($password, PASSWORD_DEFAULT));
@ -458,17 +501,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$message->html($html->render($params));
}
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
'message' => "Nicht verfügbar da Passwort enhalten",
'from' => $from->render($params),
'to' => $to->render($params),
'subject' => $subject->render($params)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -477,11 +524,15 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof Notify) {
$positionRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos');
/** @var Orderpos $position */
/**
* @var Orderpos $position
*/
$position = $positionRepo->findOneBy(array('uuid' => $event->getPosition()));
$templateVars->loadOrder($position->getOrder()->getUuid());
$params = $templateVars->getPosTwigVars($event->getPosition());
/** @var Position $objDoc */
/**
* @var Position $objDoc
*/
$objDoc = $this->_doctrine_mongodb
->getRepository(Position::class)
->findOneBy(['uid' => (string)$position->getId()]);
@ -525,7 +576,9 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof Change) {
$positionRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos');
/** @var Orderpos $position */
/**
* @var Orderpos $position
*/
$position = $positionRepo->findOneBy(array('uuid' => $event->getPosition()));
$templateVars->loadOrder($position->getOrder()->getUuid());
try {
@ -653,17 +706,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$message->attach($fileContent->render($templateVars->getTwigVars()), $fileName->render($templateVars->getTwigVars()));
}
}
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($templateVars->getPosTwigVars($position->getUuid())),
'to' => $to->render($templateVars->getPosTwigVars($position->getUuid())),
'subject' => $subject->render($templateVars->getPosTwigVars($position->getUuid()))
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -696,9 +753,14 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($mailDoc->isSendInvoice()) {
$content = $printing->generateOrder($templateVars->getOrder(), Printing::INVOICE);
$contentXRechnung = $printing->generateXRechnung($templateVars->getOrder());
if ($content) {
$message->attach($content, $printing->getFileName(), 'application/pdf');
}
}
if ($mailDoc->isSendXInvoice()) {
$contentXRechnung = $printing->generateXRechnung($templateVars->getOrder());
if ($contentXRechnung) {
$message->attach($contentXRechnung, "xrechnung.xml", 'application/pdf');
}
}
@ -753,16 +815,20 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$message->attach($fileContent->render($templateVars->getTwigVars()), $fileName->render($templateVars->getTwigVars()));
}
}
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($templateVars->getTwigVars()),
'to' => trim($to->render($templateVars->getTwigVars()))
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "error", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -770,7 +836,9 @@ class Mail implements QueueInterface, ConfigurableElementInterface
return true;
}
if ($event instanceof \Plugin\System\PSC\Upload\Event\Create) {
/** @var Upload $upload */
/**
* @var Upload $upload
*/
$upload = $this->_doctrine_mongodb
->getRepository(Upload::class)
->findOneBy(['id' => new ObjectId($event->getUpload())]);
@ -798,16 +866,20 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($html) {
$message->html($html->render($params));
}
$this->_logService->createLogEntry(new Shop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "\Plugin\System\PSC\Upload\Event\Create Mail send", [
$this->_logService->createLogEntry(
new Shop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "\Plugin\System\PSC\Upload\Event\Create Mail send", [
'message' => $message->getTextBody(),
'from' => $message->getFrom(),
'to' => $message->getTo()
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry(new Shop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "\Plugin\System\PSC\Upload\Event\Create Mail error", [
$this->_logService->createLogEntry(
new Shop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "\Plugin\System\PSC\Upload\Event\Create Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -816,10 +888,14 @@ class Mail implements QueueInterface, ConfigurableElementInterface
}
if ($event instanceof StockMin || $event instanceof BuyMax) {
$productRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Product');
/** @var Product $product */
/**
* @var Product $product
*/
$product = $productRepo->findOneBy(array('uuid' => $event->getProduct()));
$shopRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shop');
/** @var Shop $shop */
/**
* @var Shop $shop
*/
$shop = $shopRepo->findOneBy(array('uid' => $event->getShop()));
$params = array(
'product' => $product,
@ -846,17 +922,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
if ($html) {
$message->html($html->render($params));
}
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "StockMin BuyMax Mail send", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "StockMin BuyMax Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($params),
'to' => $to->render($params),
'subject' => $subject->render($params)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "StockMin BuyMax Mail error", [
$this->_logService->createLogEntry(
$shop, new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "StockMin BuyMax Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -867,7 +947,9 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$templateVars->loadOrder($event->getOrder());
$vars = $templateVars->getPosTwigVars($event->getPosition());
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
$vars['approvalContact'] = $contact;
try {
@ -947,17 +1029,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$message->attach($fileContent->render($vars), $fileName->render($vars));
}
}
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Request Mail send", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Request Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($vars),
'to' => $to->render($vars),
'subject' => $subject->render($vars)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Request Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}
@ -968,7 +1054,9 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$templateVars->loadOrder($event->getOrder());
$vars = $templateVars->getPosTwigVars($event->getPosition());
$contactRepo = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact');
/** @var Contact $contact */
/**
* @var Contact $contact
*/
$contact = $contactRepo->findOneBy(array('uuid' => $event->getContact()));
$vars['approvalContact'] = $contact;
$vars['message'] = $event->getMessage();
@ -1049,17 +1137,21 @@ class Mail implements QueueInterface, ConfigurableElementInterface
$message->attach($fileContent->render($vars), $fileName->render($vars));
}
}
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Accept Declined Mail send", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::INFO, PSCShopQueueBundle::class, $queue->getName(), "Accept Declined Mail send", [
'message' => $message->getTextBody(),
'from' => $from->render($vars),
'to' => $to->render($vars),
'subject' => $subject->render($vars)
]);
]
);
$this->_mailer->send($message);
} catch (\Exception $e) {
$this->_logService->createLogEntry($templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Accept Declined Mail error", [
$this->_logService->createLogEntry(
$templateVars->getOrder()->getShop(), new Contact(), LogEntry::ERROR, PSCShopQueueBundle::class, $queue->getName(), "Accept Declined Mail error", [
'error' => $e->getMessage()
]);
]
);
$this->_error = $e->getMessage();
return false;
}

View File

@ -4,6 +4,7 @@ namespace PSC\Shop\UserBundle\Security\ApiKey;
use Doctrine\ODM\MongoDB\DocumentManager;
use PSC\Shop\EntityBundle\Document\Instance;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
@ -40,7 +41,7 @@ class InstanceProvider implements UserProviderInterface
if (null === $instance) {
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException(sprintf('Instance "%s" not found.', $identifier));
throw new UserNotFoundException(sprintf('Instance "%s" not found.', $identifier));
}
return $instance;

View File

@ -4,9 +4,9 @@ namespace PSC\Shop\UserBundle\Security\ApiKey;
use PSC\Shop\EntityBundle\Entity\Shop;
use PSC\Shop\EntityBundle\Repository\ShopRepository;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class ShopProvider implements UserProviderInterface
@ -42,7 +42,7 @@ class ShopProvider implements UserProviderInterface
if (null === $user) {
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException(sprintf('Shop "%s" not found.', $identifier));
throw new UserNotFoundException(sprintf('User "%s" not found.', $identifier));
}
return $user;

View File

@ -4,9 +4,9 @@ namespace PSC\Shop\UserBundle\Security\User;
use PSC\Shop\ContactBundle\Repository\ContactRepository;
use PSC\Shop\EntityBundle\Entity\Contact;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class UserProvider implements UserProviderInterface
@ -42,12 +42,9 @@ class UserProvider implements UserProviderInterface
public function loadUserByIdentifier(string $identifier): UserInterface
{
$user = $this->repository->loadUserByUsername($identifier);
if (null === $user) {
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException(sprintf('User "%s" not found.', $identifier));
throw new UserNotFoundException(sprintf('User "%s" not found.', $identifier));
}
return $user;

View File

@ -59,9 +59,11 @@ class ZendAuthenticator extends AbstractAuthenticator
if ($contact) {
return new SelfValidatingPassport(
new UserBadge($contactUuid, function () use ($contact) {
return $contact;
})
new UserBadge(
$contactUuid, function () use ($contact) {
return $contact;
}
)
);
}

View File

@ -20,9 +20,11 @@ class PluginCompiler implements CompilerPassInterface
try {
$collection = (new \MongoDB\Client('mongodb://mongodb/'))->psc->Plugin;
$plugins = $collection->find(array('installed' => true));
/** @var Plugin $plugin */
/**
* @var Plugin $plugin
*/
foreach ($plugins as $plugin) {
$container->get('doctrine_mongodb.odm.metadata.chain')->addDriver(new AnnotationDriver(new AnnotationReader(), $container->getParameter('kernel.project_dir') . '/var/plugins/' . $plugin['path'] . '/Document'), $plugin['path']);
$container->get('doctrine_mongodb.odm.default_metadata_driver')->addDriver(new AnnotationDriver(new AnnotationReader(), $container->getParameter('kernel.project_dir') . '/var/plugins/' . $plugin['path'] . '/Document'), $plugin['path']);
}
} catch (\Exception $e) {
var_dump($e->getMessage());

View File

@ -0,0 +1,26 @@
<?php
namespace PSC\System\PluginBundle\Event;
use PSC\Shop\QueueBundle\Event\Event;
class EveryDay extends Event
{
public function getType(): string
{
return 'system_plugin_every_day';
}
public function getDescription(): string
{
return 'einmal am Tag';
}
public function getData(): void
{
}
public function setData($data): void
{
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace PSC\System\PluginBundle\Event;
use PSC\Shop\QueueBundle\Event\Event;
class EveryHour extends Event
{
public function getType(): string
{
return 'system_plugin_every_hour';
}
public function getDescription(): string
{
return 'jede Stunde';
}
public function getData(): void
{
}
public function setData($data): void
{
}
}

View File

@ -13,7 +13,7 @@ class EveryRun extends Event
public function getDescription()
{
return 'Bei jeder Ausführung';
return 'jede Minute';
}
public function getData()

View File

@ -41,6 +41,17 @@ services:
tags:
- { name: events }
psc.system.plugin.event.every.day:
class: PSC\System\PluginBundle\Event\EveryDay
tags:
- { name: events }
psc.system.plugin.event.every.hour:
class: PSC\System\PluginBundle\Event\EveryHour
tags:
- { name: events }
psc.system.plugin.manager:
class: PSC\System\PluginBundle\Service\Manager
public: true
@ -51,4 +62,4 @@ services:
public: false
arguments: ['%kernel.project_dir%']
tags:
- { name: routing.loader }
- { name: routing.loader }

View File

@ -97,15 +97,6 @@
"doctrine/sql-formatter": {
"version": "1.2.x-dev"
},
"dunglas/doctrine-json-odm": {
"version": "1.4",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "0.1",
"ref": "c2ab78f625df0c89af5908d50a28602ff8c4919f"
}
},
"egulias/email-validator": {
"version": "2.1.18"
},
@ -248,9 +239,6 @@
"myclabs/deep-copy": {
"version": "1.9.5"
},
"namshi/jose": {
"version": "7.2.3"
},
"nelmio/alice": {
"version": "3.12",
"recipe": {
@ -937,15 +925,6 @@
"config/routes/ux_live_component.yaml"
]
},
"symfony/ux-turbo": {
"version": "2.24",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.19",
"ref": "9dd2778a116b6e5e01e5e1582d03d5a9e82630de"
}
},
"symfony/ux-twig-component": {
"version": "v2.12.0"
},

View File

@ -20,22 +20,6 @@
</head>
<body class="min-h-screen bg-slate-100 text-gray-900 overflow-y-auto dark:text-gray-100 dark:bg-gray-900 antialiased">
<div
data-controller="modal"
data-action="turbo:before-cache@window->modal#close"
>
<dialog
class="open:flex bg-gray-800 rounded-lg shadow-xl inset-0 w-full md:w-fit md:max-w-[50%] md:min-w-[50%] animate-fade-in backdrop:bg-slate-600 backdrop:opacity-80"
data-modal-target="dialog"
data-action="close->modal#close click->modal#clickOutside"
>
<div class="flex grow p-5">
<div class="grow overflow-auto p-1">
<turbo-frame id="modal" data-modal-target="dynamicContent"></turbo-frame>
</div>
</div>
</dialog>
</div>
<div class="flex h-full w-full overflow-x-clip">
<div x-data x-show="$store.sideBar.isOpen" x-transition.opacity.500ms="" @click="$store.sideBar.close()" class="fixed inset-0 z-20 w-full h-full bg-gray-900/50 lg:hidden"></div>
<aside x-data :class="$store.sideBar.isOpen ? 'translate-x-0 max-w-[20em] shadow-2xl lg:max-w-[var(--sidebar-width)]' : '-translate-x-full lg:translate-x-0 lg:max-w-[var(--collapsed-sidebar-width)] lg:shadow-2xl rtl:lg:-translate-x-0 rtl:translate-x-full'" class="fixed inset-y-0 left-0 z-20 flex h-screen flex-col overflow-hidden w-[var(--sidebar-width)] bg-white transition-all rtl:left-auto rtl:right-0 lg:z-0 lg:border-r rtl:lg:border-l rtl:lg:border-r-0 dark:bg-gray-800 dark:border-gray-700 -translate-x-full lg:translate-x-0 lg:shadow-2xl rtl:lg:-translate-x-0 rtl:translate-x-full">

View File

@ -1,3 +1,28 @@
<turbo-frame id="modal">
{% block body %}{% endblock %}
</turbo-frame>
<!DOCTYPE html>
<html lang="de-DE">
<head>
<meta charset="utf-8">
<title>PSC Admin</title>
<meta name="description" content="">
<meta name="author" content="">
<base href="{{ app.request.getBaseURL() }}/"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script>
var jwt_token = '{{tokenService.generateToken()}}';
</script>
{% block stylesheets %}
{% endblock %}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="apple-touch-icon" sizes="57x57" href="/apps/icons/apple-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="/apps/icons/apple-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="/apps/icons/apple-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="/apps/icons/apple-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="/apps/icons/apple-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="/apps/icons/apple-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="/apps/icons/apps/icons/apple-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="/apps/icons/apple-icon-152x152.png"><link rel="apple-touch-icon" sizes="180x180" href="/apps/icons/apple-icon-180x180.png"><link rel="icon" type="image/png" sizes="192x192" href="/apps/icons/android-icon-192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="/apps/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="96x96" href="/apps/icons/favicon-96x96.png"><link rel="icon" type="image/png" sizes="16x16" href="/apps/icons/favicon-16x16.png"><link rel="manifest" href="/apps/icons/manifest.json"><meta name="msapplication-TileColor" content="#ffffff"><meta name="msapplication-TileImage" content="/apps/icons/ms-icon-144x144.png"><meta name="theme-color" content="#ffffff">
</head>
<body class="min-h-screen bg-slate-100 text-gray-900 overflow-y-auto dark:text-gray-100 dark:bg-gray-900 antialiased">
{% block body %}{% endblock %}
{% block javascripts %}
{% endblock %}
{% block importmap %}{{ importmap('backend/tailwind') }}{% endblock %}
</body>
</html>

View File

@ -3,7 +3,8 @@ namespace Plugin\Custom\PSC\Printess\Transformer;
use PSC\Shop\ContactBundle\Model\Contact;
class ContactArray {
class ContactArray
{
public function transformContactToArray(Contact $contact): array
{
@ -73,6 +74,9 @@ class ContactArray {
], [
'name' => 'contact0abteilung',
'value' => $contact->getLayouterData()->getAbteilung()
], [
'name' => 'contact0district',
'value' => $contact->getLayouterData()->getDistrict()
], [
'name' => 'contact0function',
'value' => $contact->getLayouterData()->getFunction()
@ -162,4 +166,4 @@ class ContactArray {
'value' => $contact->getCustom24()
]];
}
}
}

View File

@ -20,7 +20,7 @@ class OrderController extends AbstractController
GetState $getStateService,
Shop $shopService
) {
if($order->getUuid() != "") {
if($order && $order->getUuid() != "") {
$orderModel = $orderService->getOrderByUuid($order->getUuid());
$positions = [];

View File

@ -126,7 +126,6 @@ class SaxoprintController extends AbstractController
$putConfig->setConfig($reqConfig);
$config = $putConfig->call();
}
$getPrices->setShop($shop->getMongoShopByUid($product->getShop()->getUid()));
$getPrices->setProductId((int)$request->get('saxoprintProductId'));

View File

@ -6,6 +6,8 @@ use PSC\Library\Calc\Article;
class GetPrices extends Base
{
public array $json = [];
public function getPrices(Article $article): array
{
@ -23,6 +25,12 @@ class GetPrices extends Base
$domain = $this->stagingUrl;
}
$this->json = [
"attributes" => $attributes,
"quantity" => $article->getOptionById('auflage')->getRawValue(),
"productId" => $article->getOptionById('productId')->getValue(),
];
$response = $this->client->request(
'POST',
@ -34,12 +42,7 @@ class GetPrices extends Base
"json" => [
"items" => [
[
"product" => [
"attributes" => $attributes,
"quantity" => $article->getOptionById('auflage')->getRawValue(),
"productId" => $article->getOptionById('productId')->getValue(),
]
]
"product" => $this->json ]
]
],
]

View File

@ -17,7 +17,7 @@ class OrderController extends AbstractController
GetState $getStateService,
Shop $shopService
) {
if($order->getUuid() != "") {
if($order && $order->getUuid() != "") {
$orderModel = $orderService->getOrderByUuid($order->getUuid());
$positions = [];

View File

@ -0,0 +1,48 @@
<?php
namespace Plugin\Custom\PSC\WMD_API\Document\Queue;
use Doctrine\ODM\MongoDB\Mapping\Annotations\EmbeddedDocument;
use Doctrine\ODM\MongoDB\Mapping\Annotations\Field;
#[EmbeddedDocument]
class Check
{
#[Field(type: 'string')]
protected $from;
#[Field(type: 'string')]
protected $bcc;
#[Field(type: 'string')]
protected $to;
public function getFrom(): string
{
return $this->from;
}
public function getTo(): string
{
return $this->to;
}
public function getBcc(): string
{
return (string)$this->bcc;
}
public function setFrom(string $from): void
{
$this->from = $from;
}
public function setTo(string $to): void
{
$this->to = $to;
}
public function setBcc(string $bcc): void
{
$this->bcc = $bcc;
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace Plugin\Custom\PSC\WMD_API\Queue;
use Doctrine\ODM\MongoDB\DocumentManager;
use PSC\Shop\QueueBundle\Type\ConfigurableElementInterface;
use PSC\Library\Calc\Engine;
use PSC\Shop\EntityBundle\Document\Queue;
use PSC\Shop\EntityBundle\Repository\ProductRepository;
use PSC\Shop\QueueBundle\Event\EventInterface;
use PSC\Shop\QueueBundle\Type\QueueInterface;
use PSC\System\SettingsBundle\Service\Shop;
use Plugin\Custom\PSC\WMD_API\Api\GetPrices;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
#[AutoconfigureTag("queues")]
class Check implements QueueInterface, ConfigurableElementInterface
{
public function __construct(private ProductRepository $productRepository,
private Shop $shopService,
private DocumentManager $documentManager,
private GetPrices $pricesApi,
private MailerInterface $mailerService
) {
}
public function getType(): string
{
return 'custom_psc_wmd_check';
}
public function getDescription(): string
{
return 'Exportiert ein Auftrag nach Wir Machen Druck';
}
public function getGroup(): string
{
return 'Allgemeines';
}
public function getName(): string
{
return 'Reseller Products (WMD) Check';
}
public function injectDocument(Form $form, EventInterface $event, Queue $doc)
{
$check = new \Plugin\Custom\PSC\WMD_API\Document\Queue\Check();
$check->setTo($form->get('to')->getData());
$check->setFrom($form->get('from')->getData());
$check->setBcc($form->get('bcc')->getData());
$doc->setQueueDocument($check);
}
public function setFormData(Form $form, EventInterface $event, Queue $doc)
{
if($doc->getQueueDocument() === null) {
return;
}
$form->get('from')->setData($doc->getQueueDocument()->getFrom());
$form->get('bcc')->setData($doc->getQueueDocument()->getBcc());
$form->get('to')->setData($doc->getQueueDocument()->getTo());
}
public function execute(EventInterface $event, Queue $doc)
{
try {
$shop = $this->shopService->getShopByUid($doc->getShop());
$mongoShop = $this->shopService->getMongoShopByUid($shop->getUID());
set_time_limit(0);
$products = $this->productRepository->findBy(['type' => 101, 'enable' => true, 'shop' => $doc->getShop()]);
$engine = new Engine();
$this->pricesApi->setShop($mongoShop);
$doc = $doc->getQueueDocument();
foreach($products as $product) {
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUid()]);
$engine->loadString($productDoc->getPluginSettingModule('wmd', 'config'));
$engine->calc();
try {
$pricesArray = $this->pricesApi->getPrices($engine->getArticle());
} catch (\Throwable $th) {
$message = (new Email())
->subject('WMD Api Product Fehler')
->from($doc->getFrom())
->to($doc->getTo())
->html(sprintf('%s: %s (%s)<br/>%s<br/>%s', 'Fehler im Product: ', $product->getTitle(), $product->getUid(), $th->getMessage(), json_encode($this->pricesApi->json)));
$bccArray = explode(",", $doc->getBcc());
foreach ($bccArray as $bc) {
if (trim($bc) != "") {
$message->addBcc(trim($bc));
}
}
$this->mailerService->send($message);
continue;
}
}
} catch (\Throwable $th) {
var_dump($th->getMessage());
return false;
}
}
public function getError()
{
}
public function setForm(Form $form)
{
}
public function getForm(FormBuilderInterface $builder, $form_options, EventInterface $event)
{
$builder->add("from", TextType::class, array('label' => 'From', 'attr' => array('class' => 'form-element')));
$builder->add("to", TextType::class, array('label' => 'to', 'attr' => array('class' => 'form-element')));
$builder->add("bcc", TextType::class, array('label' => 'bcc', 'attr' => array('class' => 'form-element')));
}
public function getTemplate()
{
return '@PluginCustomPSCWMD_API/queue/check.html.twig';
}
}

View File

@ -0,0 +1,27 @@
<div class="panel">
<div class="header">
<h4>Check</h4>
</div>
<div class="body">
<div class="row">
<div class="col-md-4">
<div class="form-group row">
<label class="col-md-5 form-control-label">{{ form_label(form.from) }}</label>
<div class="col-md-7">{{ form_widget(form.from, {attr: {'class': 'form-control' }}) }}</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group row">
<label class="col-md-5 form-control-label">{{ form_label(form.to) }}</label>
<div class="col-md-7">{{ form_widget(form.to, {attr: {'class': 'form-control' }}) }}</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group row">
<label class="col-md-5 form-control-label">{{ form_label(form.bcc) }}</label>
<div class="col-md-7">{{ form_widget(form.bcc, {attr: {'class': 'form-control' }}) }}</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -15,7 +15,9 @@ class Startseite implements Field
private $_entityManager;
/** @var \PSC\System\SettingsBundle\Service\Shop */
/**
* @var \PSC\System\SettingsBundle\Service\Shop
*/
private $_shopService;
private $options;
@ -41,14 +43,16 @@ class Startseite implements Field
{
$this->options = $options;
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$products = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Product')->findBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "enable" => 1));
$tmp = [];
foreach ($products as $product) {
$tmp[$product->getTitle() . " (" . $product->getUid() . ")"] = $product->getUid();
$tmp[$product->getNrTitle()] = $product->getUid();
}
$productGroups = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Productgroup')->findBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "enable" => 1));
@ -58,15 +62,18 @@ class Startseite implements Field
$tmpGroups[$productGroup->getTitle() . " (" . $productGroup->getUid() . ")"] = $productGroup->getUid();
}
$builder->add('mode', ChoiceType::class, [
$builder->add(
'mode', ChoiceType::class, [
'required' => false,
'label' => 'Startpage',
'choices' => [
'Willkommensseite' => "index",
'Slider + Produktliste o. Produktgruppen ohne Seitennavi' => "sliderproductsnosidenav",
]
])
->add('slider_interval', ChoiceType::class, [
]
)
->add(
'slider_interval', ChoiceType::class, [
'required' => false,
'label' => 'Sliderspeed',
'choices' => [
@ -74,23 +81,30 @@ class Startseite implements Field
'normal' => "4000",
'fast' => "2000",
]
])
->add('mc_start_products', ChoiceType::class, array(
]
)
->add(
'mc_start_products', ChoiceType::class, array(
'choices' => $tmp,
'multiple' => true,
'required' => false,
'label' => 'Product',
))
->add('mc_start_productgroups', ChoiceType::class, array(
)
)
->add(
'mc_start_productgroups', ChoiceType::class, array(
'choices' => $tmpGroups,
'multiple' => true,
'required' => false,
'label' => 'Productgroups',
))
->add('index_slogan', TextareaType::class, array(
)
)
->add(
'index_slogan', TextareaType::class, array(
'label' => 'Slogen',
'required' => false
));
)
);
return $builder;
}
@ -103,7 +117,9 @@ class Startseite implements Field
public function formPostSetData(FormEvent $event)
{
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$layoutSettings = json_decode($shopEntity->getLayoutSettings(), true);
@ -114,7 +130,9 @@ class Startseite implements Field
}
if (strtolower($shopEntity->getDefaultFunc()) == "index") {
/** @var Shopsetting $setting */
/**
* @var Shopsetting $setting
*/
$setting = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shopsetting')->findOneBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "key" => "index_index_layout"));
if ($setting) {
$event->getForm()->get('bootstrap3Startseite')->get('mode')->setData($setting->getValue());
@ -134,12 +152,16 @@ class Startseite implements Field
public function formPostSubmit(FormEvent $event)
{
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$layoutSettings = json_decode($shopEntity->getLayoutSettings(), true);
$layoutSettings[$shopEntity->getLayout()]['slider_interval'] = $event->getForm()->get('bootstrap3Startseite')->get('slider_interval')->getData();
/** @var Shopsetting $setting */
/**
* @var Shopsetting $setting
*/
$setting = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shopsetting')->findOneBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "key" => "index_index_layout"));
if ($setting) {
$setting->setValue($event->getForm()->get('bootstrap3Startseite')->get('mode')->getData());

View File

@ -15,7 +15,9 @@ class Startseite implements Field
private $_entityManager;
/** @var \PSC\System\SettingsBundle\Service\Shop */
/**
* @var \PSC\System\SettingsBundle\Service\Shop
*/
private $_shopService;
private $options;
@ -41,14 +43,16 @@ class Startseite implements Field
{
$this->options = $options;
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$products = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Product')->findBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "enable" => 1));
$tmp = [];
foreach ($products as $product) {
$tmp[$product->getTitle() . " (" . $product->getUid() . ")"] = $product->getUid();
$tmp[$product->getNrTitle()] = $product->getUid();
}
$productGroups = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Productgroup')->findBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "enable" => 1));
@ -58,15 +62,18 @@ class Startseite implements Field
$tmpGroups[$productGroup->getTitle() . " (" . $productGroup->getUid() . ")"] = $productGroup->getUid();
}
$builder->add('mode', ChoiceType::class, [
$builder->add(
'mode', ChoiceType::class, [
'required' => false,
'label' => 'Startseite',
'choices' => [
'Willkommensseite' => "index",
'Slider + Produktliste o. Produktgruppen ohne Seitennavi' => "sliderproductsnosidenav",
]
])
->add('slider_interval', ChoiceType::class, [
]
)
->add(
'slider_interval', ChoiceType::class, [
'required' => false,
'label' => 'Slidergeschwindigkeit',
'choices' => [
@ -74,23 +81,30 @@ class Startseite implements Field
'Normal' => "4000",
'Schnell' => "2000",
]
])
->add('mc_start_products', ChoiceType::class, array(
]
)
->add(
'mc_start_products', ChoiceType::class, array(
'choices' => $tmp,
'multiple' => true,
'required' => false,
'label' => 'Produkte',
))
->add('mc_start_productgroups', ChoiceType::class, array(
)
)
->add(
'mc_start_productgroups', ChoiceType::class, array(
'choices' => $tmpGroups,
'multiple' => true,
'required' => false,
'label' => 'Produktgruppen',
))
->add('index_slogan', TextareaType::class, array(
)
)
->add(
'index_slogan', TextareaType::class, array(
'label' => 'Slogen',
'required' => false
));
)
);
return $builder;
}
@ -103,7 +117,9 @@ class Startseite implements Field
public function formPostSetData(FormEvent $event)
{
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$layoutSettings = json_decode($shopEntity->getLayoutSettings(), true);
@ -112,7 +128,9 @@ class Startseite implements Field
$event->getForm()->get('bootstrap4Startseite')->get('slider_interval')->setData($layoutSettings[$shopEntity->getLayout()]['slider_interval']);
if (strtolower($shopEntity->getDefaultFunc()) == "index") {
/** @var Shopsetting $setting */
/**
* @var Shopsetting $setting
*/
$setting = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shopsetting')->findOneBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "key" => "index_index_layout"));
if ($setting) {
$event->getForm()->get('bootstrap4Startseite')->get('mode')->setData($setting->getValue());
@ -128,12 +146,16 @@ class Startseite implements Field
public function formPostSubmit(FormEvent $event)
{
/** @var Shop $shopEntity */
/**
* @var Shop $shopEntity
*/
$shopEntity = $this->options['shopEntity'];
$layoutSettings = json_decode($shopEntity->getLayoutSettings(), true);
$layoutSettings[$shopEntity->getLayout()]['slider_interval'] = $event->getForm()->get('bootstrap4Startseite')->get('slider_interval')->getData();
/** @var Shopsetting $setting */
/**
* @var Shopsetting $setting
*/
$setting = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Shopsetting')->findOneBy(array("shop" => $this->_shopService->getSelectedShop()->getUid(), "key" => "index_index_layout"));
if ($setting) {
$setting->setValue($event->getForm()->get('bootstrap4Startseite')->get('mode')->getData());

View File

@ -104,7 +104,9 @@ class GetPrice extends AbstractController
$output = new \Plugin\System\PSC\XmlCalc\Dto\Output\PriceOutput();
$output->product = $data->product;
/** @var Product $product */
/**
* @var Product $product
*/
$product = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Product')->findOneBy(['uuid' => $data->product]);
@ -158,7 +160,9 @@ class GetPrice extends AbstractController
$output->xmlProductTypes[] = $article->getName();
}
/** @var Base $option */
/**
* @var Base $option
*/
foreach ($engine->getArticle()->getOptions() as $option) {
$tmp = new Element();
$tmp->name = $option->getName();
@ -180,7 +184,9 @@ class GetPrice extends AbstractController
$tmp->displayGroup = $option->getDisplayGroup();
if ($option->type == 'select' || $option->type == 'checkbox' || $option->type == 'radio') {
/** @var Opt $option */
/**
* @var Opt $option
*/
if ($option instanceof ColorDBSelect) {
$tmp->colorSystem = $option->getColorSystem();
if (!isset($output->colorDb[$option->getColorSystem()])) {
@ -243,6 +249,8 @@ class GetPrice extends AbstractController
foreach ($group->getVariants() as $variant) {
$variantObj = new Variant();
$variantObj->name = $variant->getName();
$variantObj->text = $variant->getText();
$variantObj->data = $variant->getData();
foreach ($variant->getValues() as $value) {
$valueObj = new Value();
$valueObj->key = $value->getKey();

View File

@ -15,6 +15,21 @@ class Variant
*/
public string $name;
/**
* @var string
*
* @OA\Property(type="string")
*/
public string $text;
/**
* @var string
*
* @OA\Property(type="string")
*/
public string $data;
/**
* @var Variant[] options
*

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,8 @@ abstract class BaseNews extends Doctrine_Record
'length' => '25',
));
$this->hasColumn('sort_date', 'date', 25);
$this->hasColumn('from_date', 'datetime', 25);
$this->hasColumn('to_date', 'datetime', 25);
$this->hasColumn('updated', 'timestamp', 25, array(
'type' => 'timestamp',
'length' => '25',
@ -84,4 +86,4 @@ abstract class BaseNews extends Doctrine_Record
$sluggable0 = new Doctrine_Template_Sluggable (array('unique' => true, 'fields' => array(0 => 'title'), 'name' => 'url', 'canUpdate' => true));
$this->actAs($sluggable0);
}
}
}

View File

@ -25,13 +25,13 @@ $filesOptions = $this->article['basketarticle']->getFiles();
<strong><?php echo $this->layouter()->getTitle($this->article['basketarticle']->getLayouterId()); ?></strong><br />
<?php endif; ?>
<?php if(($this->article['options'])): ?>
<ul id="options_<?= $basketArticle['uuid'] ?>">
<ul id="options_<?= $this->article['uuid'] ?>">
<li>Lade Optionen</li>
</ul>
<script>
$(function () {
loadDetails($("#options_<?= $basketArticle['uuid'] ?>"), '<?= json_encode(['test' => false, 'product' => $basketArticle['uuid'], 'values' => $this->article['basketarticle']->getOptions()]) ?>');
loadDetails($("#options_<?= $this->article['uuid'] ?>"), '<?= json_encode(['test' => false, 'product' => $basketArticle['uuid'], 'values' => $this->article['basketarticle']->getOptions()]) ?>');
})

View File

@ -396,9 +396,9 @@ if($linkend == "") { ?>
if(count($cms) > 0) /* wenn wir CMS einträge haben... */
{
/* Text ausgeben */
if(!$cms->getFirst()->notinmenu)
if(!$cms[0]->notinmenu)
{
echo $cms->getFirst()->getText();
echo $cms[0]->getText();
}
echo '<hr>';

View File

@ -2670,6 +2670,10 @@ class ArticleController extends TP_Controller_Action
$this->_redirect('/basket/simple');
return;
}
if (file_exists($this->_templatePath . '/basket/custom.phtml')) {
$this->_redirect('/basket/custom');
return;
}
$this->_redirect('/basket/index');

View File

@ -209,7 +209,10 @@ class BasketController extends TP_Controller_Action
$this->redirectSpeak("/basket/simple");
}
public function customAction()
{
}
public function simpleAction()
{
@ -2239,7 +2242,6 @@ class BasketController extends TP_Controller_Action
$stockErrorCount = $article->stock_count;
$this->view->stockError = true;
}
array_push(
$temp, array(
'uuid' => $uuid,
@ -3241,14 +3243,7 @@ class BasketController extends TP_Controller_Action
$this->view->delivery_address = Doctrine_Query::create()->select()->from('ContactAddress s')->where('s.contact_id = ? AND display = 1 AND s.uuid = ?', array($this->user->id, $basket->getDelivery()))->fetchOne();
if ($basket->getSender() == 0 || $this->view->sender_address == null) {
$this->view->sender_address = Doctrine_Query::create()->select()->from('ContactAddress s')->where('s.contact_id = ? AND display = 1 AND s.type = ?', array($this->user->id, 3))->fetchOne();
if ($this->view->sender_address == null) {
$this->view->sender_address = $this->shop->getOrderSenderSavedAsObject();
} else {
$basket->setSender($this->view->sender_address->uuid);
$this->view->sender = $basket->getSender();
}
$this->view->sender_address = $this->shop->getOrderSenderSavedAsObject();
}
$this->view->sender_address_shop = $this->shop->getOrderSenderSavedAsObject();
if ($this->_getParam('basketfield1')) {

View File

@ -45,12 +45,11 @@ class NewsController extends TP_Controller_Action
$news = Doctrine_Query::create()
->from('News c')
->where('c.shop_id = ? AND c.active = 1 AND (c.language = ?
->where('c.shop_id = ? AND c.active = 1 AND (c.from_date IS NULL OR c.from_date < ?) AND (c.to_date IS NULL or c.to_date > ?) AND (c.language = ?
OR c.language = \'all\')',
array($this->shop->id, Zend_Registry::get('locale')))
->orderBy('c.sort_date DESC')
->execute();
array($this->shop->id, date('Y-m-d H:i:s'), date('Y-m-d H:i:s'), Zend_Registry::get('locale')))
->orderBy('c.sort_date DESC');
$news = $news->execute();
$this->view->news = $news;
$this->_helper->layout->setLayout('default');
@ -60,7 +59,7 @@ class NewsController extends TP_Controller_Action
$news = Doctrine_Query::create()
->from('News c')
->where('c.shop_id = ? AND c.active = 1 AND c.url = ?',
->where('c.shop_id = ? AND c.active = 1 AND (c.from_date IS NULL OR c.from_date < ?) AND (c.to_date IS NULL or c.to_date > ?) AND c.url = ?',
array($this->shop->id, $this->_getParam('url')))
->fetchOne();
@ -68,4 +67,4 @@ class NewsController extends TP_Controller_Action
$this->_helper->layout->setLayout('default');
}
}
}

View File

@ -89,13 +89,16 @@ class TP_Controller_Action extends Zend_Controller_Action
$this->view->shop = Doctrine_Query::create()->from('Shop s')->where('s.id = ?')->fetchOne(array(
$conf['id']));
if ($this->view->shop->template_switch && Zend_Auth::getInstance()->hasIdentity()) {
if (Zend_Auth::getInstance()->hasIdentity()) {
$user = Zend_Auth::getInstance()->getIdentity();
$accountPath = $this->getAccountTemplatePath($user['account_id']);
if ($accountPath != "") {
$conf['layout'] = $accountPath;
Zend_Registry::set('layout_path', APPLICATION_PATH . '/design/clients/' . $this->view->shop->uid . '/' . $accountPath . '');
if(file_exists(APPLICATION_PATH . '/design/clients/' . $this->view->shop->uid . '/' . $accountPath)) {
Zend_Registry::set('layout_path', APPLICATION_PATH . '/design/clients/' . $this->view->shop->uid . '/' . $accountPath . '');
}else{
Zend_Registry::set('layout_path', APPLICATION_PATH . '/design/vorlagen/' . $accountPath . '');
}
}
}

View File

@ -19,7 +19,6 @@ require_once('/data/www/new/vendor/mongodb/mongodb/src/Database.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/Collection.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/UpdateResult.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/InsertOneResult.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/Operation/Executable.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/Operation/Explainable.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/Operation/FindOne.php');
require_once('/data/www/new/vendor/mongodb/mongodb/src/Operation/Find.php');