Sulu: error when trying to use custom data provider - sulu

I'm following docs from here: https://docs.sulu.io/en/2.2/cookbook/smart-content-data-provider.html
Trying to make custom data provider for my custom entity type "MatchEvent":
I did it how it's explained here. Since I have services.yaml file I defined those 2 like this:
app.match_event_repository:
class: App\Repository\MatchEventRepository
factory: ['#doctrine', 'getRepository']
arguments:
- Symfony\Bridge\Doctrine\ManagerRegistry
app.smart_content.data_provider.matchevent:
class: App\SmartContent\MatchEventDataProvider
arguments: ['#app.match_event_repository', '#sulu_core.array_serializer', '#request_stack' ]
tags: [{name: 'sulu.content.type', alias: 'smart_matchevent_selection'}]
So, if I understood well, after that I should have my custom content data provider named "smart_matchevent_selection" and I can use it like this:
<property name="match" type="smart_content">
<meta>
<title lang="en">Match</title>
<title lang="de">Match</title>
</meta>
<params>
<param name="provider" value="smart_matchevent_selection"/>
</params>
</property>
But when I try to edit page containing this field I get error:
Missing parameter token in Sulu\Bundle\PreviewBundle\Controller\PreviewController
Exception is triggered at project/vendor/sulu/sulu/src/Sulu/Bundle/PreviewBundle/Controller/PreviewController.php:
public function stopAction(Request $request): Response
{
$this->preview->stop($this->getRequestParameter($request, 'token', true));
return new JsonResponse();
}
What I'm doing wrong here?

If you carefully look at the service definition of the SmartContentDataProvider in the documentation, you will notice that the tag should be {name: 'sulu.smart_content.data_provider', alias: 'match_events'} instead of {name: 'sulu.content.type', alias: 'smart_matchevent_selection'} ...
Then you can use it like <param name="provider" value="match_events"/>

Related

Extending Modx modResource schema errors

I'm trying to extend the modx modresource object, but keep getting errors & I can't seem to figure out why. It is related to the schema (I think) but everything looks correct.
Schema:
<?xml version="1.0" encoding="UTF-8"?>
<model package="extresource" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" tablePrefix="modx_" version="1.0.0">
<object class="extResource" extends="modResource">
<composite alias="ResourceData" class="ResourceData" local="id" foreign="internalKey" cardinality="one" owner="local"/>
</object>
<object class="ResourceData" table="resource_data" extends="xPDOSimpleObject">
<field key="internalKey" dbtype="int" precision="11" phptype="integer" null="false" attributes="unsigned"/>
<field key="views" dbtype="int" precision="11" phptype="integer" null="true" />
<field key="starred" dbtype="int" precision="10" phptype="integer" null="false" />
<index alias="internalKey" name="internalKey" primary="false" unique="true" type="BTREE" >
<column key="internalKey" length="" collation="A" null="false" />
</index>
<aggregate alias="Resource" class="modResource" local="internalKey" foreign="id" cardinality="one" owner="foreign"/>
</object>
</model>
I'm testing it using:
$resource = $modx->getObject('modResource', 11112);
echo $resource->get('pagetitle'); //test I have the resource
$data = $resource->getOne('ResourceData');
The errors I get are:
Could not getOne: foreign key definition for alias ResourceData not
found. No foreign key definition for parentClass: modDocument using
relation alias: ResourceData
The table exists & has data, the package is registered in the modx extension packages. I've been over the schema many times & it looks right.
What is causing these errors?
You have to use the right object class in $modx->getObject. Otherwise you will get a modResource object, that does not know the extended object data and relationship.
$resource = $modx->getObject('extResource', 11112);
Does the resource you are loading have its class_key field set to extResource? That's needed for it to load the right resource object class.

Service Fabric specify fabric url

Is it possible to define which url a service uses instead of the standard fabric:/AppName/ServiceName?
I can't find if this is configurable or not on an application level.
Yes, you can change the name of the service in the ApplicationManifest.xml to something other than the name taken from the service's class name.
Short: just change the name attribute in ApplicationManifest.xml for that service to something else.
In code: If I have this service:
public interface IJustAnotherStatelessService : IService
{
Task<string> SayHelloAsync(string someValue);
}
internal sealed class JustAnotherStatelessService : StatelessService, IJustAnotherStatelessService
{
// Service implementation
}
Registered in Program.cs like this:
ServiceRuntime.RegisterServiceAsync("JustAnotherStatelessServiceType",
context => new JustAnotherStatelessService(context)).GetAwaiter().GetResult();
And in the ServiceManifest.xml for that service
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest ...>
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="JustAnotherStatelessServiceType" />
</ServiceTypes>
...
In the ApplicationManifest.xml you will get the suggested name:
<ApplicationManifest ...>
<DefaultServices>
<Service Name="JustAnotherStatelessService">
<StatelessService ServiceTypeName="JustAnotherStatelessServiceType" InstanceCount="[JustAnotherStatelessService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
This will give you an Uri to you service like
fabric:/app_name/JustAnotherStatelessService
Now, go ahead and change the name in the application manifest:
<ApplicationManifest ...>
<DefaultServices>
<Service Name="AwesomeService">
<StatelessService ServiceTypeName="JustAnotherStatelessServiceType" InstanceCount="[JustAnotherStatelessService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
And your service now answers to
fabric:/app_name/AwesomeService
You can use this uri builder (ServiceUriBuilder.cs) class from here: https://github.com/Azure-Samples/service-fabric-dotnet-web-reference-app/blob/master/ReferenceApp/Common/ServiceUriBuilder.cs
For stateless service you can easily get the proxy:
var serviceUri = new ServiceUriBuilder(ServiceName);
var proxyFactory = new ServiceProxyFactory();
var svc = proxyFactory.CreateServiceProxy<IServiceName>(serviceUri.ToUri());
For stateful service you have to specify the partition.
var serviceUri = new ServiceUriBuilder(StatefulServiceName);
var proxyFactory = new ServiceProxyFactory();
//this is just a sample of partition 1 if you are using number partitioning.
var partition = new ServicePartitionKey(1);
var svc = proxyFactory.CreateServiceProxy<IStatefulServiceName>(serviceUri.ToUri(), partition);

Unity 3: The type does not have an accessible constructor

I have a following interface and implementation
namespace ProjectName.Web
{
public interface IWebUtil
{
}
}
namespace ProjectName.Web
{
public class WebUtil : IWebUtil
{
}
}
in my config i have this registration. I am using Unity 3.
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="ProjectName.Web" />
...
<register name="WebUtil" type="ProjectName.Web.IWebUtil" mapTo="ProjectName.Web.WebUtil">
<lifetime type="transient" />
</register>
...
When I try to resolve this configuration I am getting this error:
Exception is: InvalidOperationException - The type IWebUtil does not have an accessible constructor.
-----------------------------------------------
At the time of the exception, the container was:
Resolving ProjectName.Web.IWebUtil,(none)
I have tried to add empty public constructor but no sucess.
Can anybody help with this? thanks.
The first step is to ensure that you are loading the Unity configuration since this is not done by default. To do this:
using Microsoft.Practices.Unity.Configuration;
container.LoadConfiguration();
I'm assuming you've done this. I'm also going to assume that you are trying to resolve IWebUtil using the following code:
container.Resolve<IWebUtil>();
This throws an InvalidOperationException because IWebUtil is configured as a named registration (with name "WebUtil"). So either resolve using the configured name:
container.Resolve<IWebUtil>("WebUtil");
Or change the registration to be a default (unnamed) registration:
<register name="" type="ProjectName.Web.IWebUtil" mapTo="ProjectName.Web.WebUtil">
<lifetime type="transient" />
</register>

Symfony Basic Translation Example

I am new to Symfony2. Trying to establish translation Service. I am following the steps given in the official documentation. But not successful.
Following are steps followed
In 'symfony/app/config/config.yml' translation service by defining locale "#translator:{ fallback: %locale% }"
In 'symfony/app/config/parameters.yml' defined locale parameter "locale:de"
In 'src/MyBundle/translateBundle/Resources/translations/messages.de.xlf' is created
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="1">
<source>Symfony2 is great</source>
<target>J'aime Symfony2</target>
</trans-unit>
</body>
</file>
</xliff>
Now I hope with this coding now I should get: 'J'aime Symfony2' on execution of following code.
<?php
namespace MyDays\translateBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller {
public function indexAction() {
$t = $this->get ( 'translator' )->trans ( 'Symfony2 is great' );
return new Response ( $t );
}
}
But still getting original text as 'Symfony2 is great'!
Is there anything I have to do apart from the steps given in documentation?
Have you removed # before translator... in config.yml?
Also you need to clear the cache after adding a new translation file.

Symfony DIC and Parent Services not working

I'm integrating Symfony DIC in a zend framework application, that's going fine except for parent services.
In my DIC config I have a parent service PC_Service which will be extended by all my services.
The problem is that the entity manager is not available (NULL) in the services that extend PC_Service. When I inject the entitymanager via service.stats the entitymanger is set correctly.
...
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.entitymanager" />
</call>
</service>
...
<service id="service.stats" class="Application_Service_Stats" parent="pc.service" />
...
PC_Service
abstract class PC_Service
{
protected $_em;
public function setEntityManager($entityManager)
{
$this->_em = $entityManager;
}
}
Application_Service_Stats
class Application_Service_Stats extends PC_Service
{
... $this->_em should be set here.
}
I hope someone can tell me what I'm doing wrong.
Don't know if it's a typo but it should be doctrine.orm.default_entity_manager or doctrine.orm.entity_manager (alias of the previuos):
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.orm.default_entity_manager" />
</call>
</service>
The solution is to compile the service container near the end of the ZF bootstrap. This process has a step called ResolveDefinitionTemplatesPass which patches in the calls from parent services.
This is typically done by the Symfony Kernel, but of course it isn't present in a ZF integration.
protected function _initServiceContainerCompilation()
{
// Wait for the SC to get built
$this->bootstrap('Services');
// Doctrine modifies the SC, so we need to wait for it also
$this->bootstrap('Doctrine');
// Compiling the SC allows "ResolveDefinitionTemplatesPass" to run,
// allowing services to inherit method calls from parents
$sc = $this->getResource('Services');
$sc->compile();
}