Shopware 6 Custom plugin that changes the schedule task interval value - shopware

I want to create a plugin that can set the scheduled task interval. Shopware has database field called run_interval in Schedule_task table. The admin will enter a value, this value will change the run_interval in the scheduled_task table. Is this possible? How can I do that?

I'm assuming you want to use a plugin configuration for the input field. You could then set up a subscriber to listen for changes of the config field and update the scheduled task entity.
Service definition:
<service id="Foo\MyPlugin\Subscriber\SystemConfigChangedSubscriber">
<argument type="service" id="scheduled_task.repository"/>
<tag name="kernel.event_subscriber"/>
</service>
Subscriber:
class SystemConfigChangedSubscriber implements EventSubscriberInterface
{
private EntityRepositoryInterface $repository;
public function __construct(EntityRepositoryInterface $repository)
{
$this->repository = $repository;
}
public static function getSubscribedEvents(): array
{
return [
SystemConfigChangedEvent::class => 'onSystemConfigChanged',
];
}
public function onSystemConfigChanged(SystemConfigChangedEvent $event): void
{
if ($event->getKey() !== 'MyPluginName.config.nameOfMyField') {
return;
}
$context = Context::createDefaultContext();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('name', 'name_of_the.task'));
$taskId = $this->repository->searchIds($criteria, $context)->firstId();
if (!$taskId) {
return;
}
$this->repository->update([
[
'id' => $taskId,
'runInterval' => $event->getValue(),
],
], $context);
}
}

Related

Shopware 6 - Custom CMS elements: How to get the data from two repositories into a custom CMS block?

We are working on a custom shopware 6 plugin. This plugin contains a custom CMS block with two CMS elements. The CMS elements need data from two different custom repositories which are not associated to each other.
We tried to set up two DataResolver (one for each CMS element) but they are overwriting each other. So we tried to put everything in one DataResolver. We checked how some other plugins do this but it is not very clear to us.
Can someone help us what we need to put into the CMSElementReslover.php file especially into these two methods:
public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
{
// Some other plugins return null here(?)
}
public function enrich(CmsSlotEntity $slot, ResolverContext $resolverContext, ElementDataCollection $result): void
{
// If we return null at the collect method, our $result variable is empty.
// We need the two custom repositories here...
}
We setup two additional classes for each element which extends our CmsElementResolver, e.g. like this:
class ExampleOneCmsElementResolver extends CmsElementResolver
{
public function getType(): string
{
}
public function getStruct(): Struct
{
}
The documentation is not very detailed: https://developer.shopware.com/docs/guides/plugins/plugins/content/cms/add-data-to-cms-elements
Thanks for any hint! 🙏🏼
Best!
#shopware #shopware6
We tried to add both repositories to the collection, e.g. like this:
public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
{
$config = $slot->getFieldConfig();
$criteria = new Criteria();
$criteriaCollection = new CriteriaCollection();
$criteriaCollection->add(
Entity1Definition::ENTITY_NAME,
Entity1Definition::class,
$criteria
);
$criteria = new Criteria();
$criteriaCollection->add(
Entity2Definition::ENTITY_NAME,
Entity2Definition::class,
$criteria
);
return $criteriaCollection->all() ? $criteriaCollection : null;
}
You are on the right track with adding your criteria to the collection.
Let's say you want to fetch a media and a product entity.
In the collect method you simply provide a unique key with both your criteria.
In the enrich method you retrieve the result of the respective search with the same key you used for the criteria.
Then it's simply a matter of setting your entities you retrieve from the search results to the slot by using an instance of Struct, e.g. ArrayStruct.
public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
{
$mediaIdConfig = $slot->getFieldConfig()->get('mediaId');
$productIdConfig = $slot->getFieldConfig()->get('productId');
if ($mediaIdConfig === null || $productIdConfig === null) {
return null;
}
$criteriaCollection = new CriteriaCollection();
$criteria = new Criteria([$mediaIdConfig->getStringValue()]);
$criteriaCollection->add('media_' . $slot->getUniqueIdentifier(), MediaDefinition::class, $criteria);
$criteria = new Criteria([$productIdConfig->getStringValue()]);
$criteriaCollection->add('product_' . $slot->getUniqueIdentifier(), ProductDefinition::class, $criteria);
return $criteriaCollection;
}
public function enrich(CmsSlotEntity $slot, ResolverContext $resolverContext, ElementDataCollection $result): void
{
$mediaSearchResult = $result->get('media_' . $slot->getUniqueIdentifier());
$productSearchResult = $result->get('product_' . $slot->getUniqueIdentifier());
if ($mediaSearchResult === null || $productSearchResult === null) {
return;
}
$slot->setData(new ArrayStruct([
'media' => $mediaSearchResult->first(),
'product' => $productSearchResult->first(),
]));
}

Which is the event fired after login but with an rebuilded cart

I have a shopware6 plugin which should store data in the session for certain cart items. Once a user has a dropped session and the user logs in again Shopware6 is rebuilding the cart.
I currently work with CustomerLoginEvent but the cart session not be restored here (yet); so what would be the correct event ?
You can listen to SalesChannelContextRestoredEvent, then get the cart from the restored context's token.
<service id="Foo\MyPlugin\ContextRestoredSubscriber">
<argument type="service" id="Shopware\Core\Checkout\Cart\SalesChannel\CartService"/>
<tag name="kernel.event_subscriber"/>
</service>
class ContextRestoredSubscriber implements EventSubscriberInterface
{
private CartService $cartService;
public function __construct(CartService $cartService)
{
$this->cartService = $cartService;
}
public static function getSubscribedEvents(): array
{
return [
SalesChannelContextRestoredEvent::class => 'onContextRestored',
];
}
public function onContextRestored(SalesChannelContextRestoredEvent $event): void
{
$context = $event->getRestoredSalesChannelContext();
$cart = $this->cartService->getCart($context->getToken(), $context);
// ...
}
}

Shopware 6: Extend existing core DAL entities with a reference

I'm trying to create a connection between 2 existing entities PropertyGroup and CustomFieldSet. Use-case is irrelevant.
So I created an EntityExtension:
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new ManyToOneAssociationField('customFieldSet', 'custom_field_set', CustomFieldSetDefinition::class))
);
}
public function getDefinitionClass(): string
{
return PropertyGroupDefinition::class;
}
And override the administration component to also include this association when loading the entity:
Component.override('sw-property-detail', {
methods: {
loadEntityData() {
this.isLoading = true;
const criteria = this.defaultCriteria;
criteria.addAssociation('customFieldSet', new Criteria(1, 500));
this.propertyRepository.get(this.groupId, Shopware.Context.api, criteria)
.then((currentGroup) => {
this.propertyGroup = currentGroup;
this.isLoading = false;
}).catch(() => {
this.isLoading = false;
});
}
}
});
(I tried to override defaultCriteria but that didn't work because of this.$super being unable to access computed properties).
But it keeps saying FRAMEWORK__ASSOCIATION_NOT_FOUND. I debugged the EntityDefinition and it seems that this extension is not even loaded.
I checked if my EntityExtension is loaded in the Symfony container and it is, but it seems that it doesn't reach the entity definition.
The EntityExtension seems to be missing the addition of a FkField inside the function extendFields:
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new FkField('custom_field_set', 'customFieldSetId', CustomFieldSetDefinition::class)),
);
$collection->add(
(new ManyToOneAssociationField('customFieldSet', 'custom_field_set', CustomFieldSetDefinition::class))
);
}
A new use statement has to be added for the FkField:
use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField;

How to extend shopware.api.customergroup

I am trying to extend Shopware v5.4.6's \Shopware\Components\Api\Resource\CustomerGroup by adding attributes to it yet it is not showing in the API response.
I have tried to repurpose extending the Customer API resource example but it did not work.
"SwagExtendCustomerGroupResource\Components\Api\Resource\CustomerGroup.php"
class CustomerGroup extends \Shopware\Components\Api\Resource\CustomerGroup
{
/**
* #inheritdoc
*/
public function getOne($id)
{
$result = parent::getOne($id);
$result ['attribute'] = $result->getAttribute();
return $result;
}
}
"SwagExtendCustomerGroupResource\Resources\services.xml"
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="swag_extend_customer_group_resource.customer_group_resource"
class="SwagExtendCustomerGroupResource\Components\Api\Resource\CustomerGroup"
decorates="shopware.api.customergroup"
public="false"
shared="false">
</service>
</services>
</container>
I was expecting to see "attribute" property yet it is not showing
As you can see in the original getOne method, the query builder does not select the attributes of the customer group.
So if you want to select the attributes, you need to overwrite this method completely:
public function getOne($id)
{
$this->checkPrivilege('read');
if (empty($id)) {
throw new ApiException\ParameterMissingException('id');
}
$builder = $this->getRepository()->createQueryBuilder('customerGroup')
->select('customerGroup', 'd', 'attr') // <-- add select
->leftJoin('customerGroup.discounts', 'd')
->leftJoin('customerGroup.attribute', 'attr') // <-- join attributes
->where('customerGroup.id = :id')
->setParameter(':id', $id);
$query = $builder->getQuery();
$query->setHydrationMode($this->getResultMode());
/** #var \Shopware\Models\Customer\Group $category */
$result = $query->getOneOrNullResult($this->getResultMode());
if (!$result) {
throw new ApiException\NotFoundException(sprintf('CustomerGroup by id %d not found', $id));
}
return $result;
}
Best regards from Schöppingen
Michael Telgmann

Getting error UserSession.OnActionExecuting(ActionExecutingContext): no suitable method found to override in mvc 5?

I have created one demo in mvc 5 and now I need to create one custom filter in my demo. I have used mvc 5.
I need to check every time what method is execute like is a ajax call or action method call in mvc.
Here I have write like this code in my class.
public class UserSession
: System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var session = filterContext.HttpContext.Session;
if (ApplicationSession.IsSessionAlive)
return;
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var ajaxRedirectTarget = new RouteValueDictionary { { "action", "FailAuthenticationAjax" }, { "controller", "Home" } };
filterContext.Result = new RedirectToRouteResult(ajaxRedirectTarget);
}
else
{
var redirectTarget = new RouteValueDictionary { { "action", "Login" }, { "controller", "Account" } };
filterContext.Result = new RedirectToRouteResult(redirectTarget);
}
}
}
but I got error like this UserSession.OnActionExecuting(ActionExecutingContext): no suitable method found to override
After I have put this class on my controller like this.
[UserSession]
public class DashboardController
{
}
any one know how to fixed this issue in mvc 5?

Resources