Reading data from CMF/PHPCR - symfony

I'm trying to use CMF for backoffice content edition. For the purposes of local content edition, CMF works fine. But then, I want to send this data to another server using a custom data structure, one that is completely different from what PHPCR uses.
Does CMF provide any kind of API or service to query its repository? For instance, my entities are Pages which contain Sections which contain Articles that finally contain the properties "title" and "body". I want to send this structure as a JSON to another server without all the overhead present in PHPCR.
{
pageTitle: "Home",
sections: [
{
sectionTitle: "firstSection",
articles: [
{
title: "Hello",
body: "Welcome to this page"
}
]
}
]
}

The CMF provides quite a few components, so I am not sure exactly which you want to use and which you want to skip.
For example for the inline editing, you could point things to a different JSON-LD capable backend.
If you want to use Sonata for administration, then it gets a bit more complicated. In theory you can create a new Jackalope transport layer that simply talks to some REST service which will enable CMF to read/write from it just like with the other Jackalope transports. In fact I have done a proof of concept once to use the Prismic.io service in exactly this way, though I only implemented the read part.
Maybe the best way to answer your question is if you could state which parts of the CMF you do want to use, rather than just say you do not want to use any of the existing PHPCR implementations.

Related

In Domain Driven Design should you Add/Update Entities through the AggregateRoot?

If you have a Vendor with a list of Contacts, in DDD which is the better approach for adding a contact to a Vendor?
Here's some sample C# code using a CQRS command.
Given the following command, how should we implement adding a Contact to a Vendor
AddVendorContactCommand()
{
string vendorId;
string contactName;
}
Should we add a contact through the Vendor:
AddVendorContactHandler(AddVendorContactCommand command)
{
var vendor = await dbContext.Vendors.FindAsync(command.vendorId);
vendor.AddContact(command.contactName);
dbContext.Save();
//doesn't require a dbSet for VendorContacts???
}
Or should we reference the VendorContact and bypass the Vendor entirely.
AddVendorContactHandler(AddVendorContactCommand command)
{
//handler
var newVendorContact = new VendorContact(command.vendorId, command.contactName);
dbContext.VendorContacts.Add(newVendorContact);
dbContext.Save();
//requires a dbSet for VendorContacts;
}
I feel like the better approach is to go through the Vendor, but that requires our AddVendorContactCommand to read from the database first. In CQRS Commands, it generally suggests avoid reads. The second approach to use VendorContacts directly will have higher performance than if we go through Vendor.
Argument to go through the Vendor are the following:
What if the Vendor doesn't exist
What if the Vendor isn't allowed any more contacts.
What if the Vendor is deleted, disabled or otherwise readonly
What's the correct DDD approach?
First, as a developer, I'm obligated to say there is no single correct approach to anything.
Now that is out of the way, given the information you have provided, I'm going to assume that the Vendor entity you described can (and in my opinion should) be the Aggregate Root. With that in mind, I would definitely go with the first option you described.
I think you have a misconception about CQRS Commands. It is perfectly fine to get data from the database inside commands. The thing you have to avoid is fetching the data from the query side, which could be a totally different database.
You are also correct, you won't need a DbSet<> for VendorContact entity, and you should keep it that way on the Command side, as you want to protect the invariants inside your Vendor Aggregate Root.

How to do .Net Web Api versioning/routing for an app client?

So there are several parts to this question.
The 2 example endpoints (in simplest form):
user/{id}/profile
movie/{id}/info
I expect to create 2 controllers (UserController & MovieController).
How do I implement a view area before controller name?
Both of these are what I would consider a view. Therefore I would like to append a "view" in the url before the controller, as both controllers ONLY supply views. I later expect to also have a user controller in a different place that does NOT return views.
However, ALL my endpoints should start with /api/.
i.e. I want this:
api/view/user/{id}/profile
api/view/movie/{id}/info
But how do I register an area (/view/) while using "custom routing" (i.e.: httpConfiguration.MapHttpAttributeRoutes())? Any examples of this I couldn't find?
Where should I put versioning?
The client is an app, and will require versioning, so that we can make changes to the methods without breaking old versions of the app.
We are unsure where it would be best to place the versioning, and how the placement affects the development of new versions (if it does so at all?).
Possibilities:
1. api/v1/view/user/{id}/profile
2. api/view/v1/user/{id}/profile
3. api/view/user/{id}/profile/v1
version the whole API. This would upgrade the whole API to a new version, even if we only required a single method/endpoint to make an app-breaking change.
Are there any advantages to this that I am not seeing?
version the area. Same as above, just slightly fewer controllers affected.
version the method. Seems like the simplest, as only the single changed method is affected. But the url is very ugly.
Does anyone have an example of versioning in an MVC or Web Api structure that doesn't upgrade the whole API, but still keeps a somewhat nice structure in their URLs?
I ended up using https://github.com/Microsoft/aspnet-api-versioning as suggested by NightOwl888.
1.
Made my 2 controllers extend another controller with a const field that defined the routeprefix that they should share:
protected const string RoutePrefix = "api/view/v{version:apiVersion}";
...
[RoutePrefix(RoutePrefix + "/user")]
2.
The placement of the /v1/ doesn't matter with this Library. And allowed for either updating the controller or individuals methods, as seen fit per case basis.

Use FOSUserBundle in relation with yml-based Entities

I've started a Symfony2 project from scratch where I then installed FOSUserBundle.
Then, I have written (actually, generated with ORM Designer) some entities that need to have relations between them, and with the User entity.
I have Items belonging to Users, Collections belonging to Users that group Items, and so on.
Since I used FOSUserBundle I only have a basic User class (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md , step 3a) defined using annotations, no config/doctrine folder and no User.yml file in it.
I then created the MyBundle/Resources/config/doctrine folder and added the yml files mentioned above.
When I try to generate the entities with the command-line tool everything works fine: it will create the Entities from my yml files.
However, at this point, trying to load up in browsers the url where the login previously worked (when I only had the FOSUserBundle installed) will throw this error:
MappingException: No mapping file found named
'/var/www/concert/src/X/MyBundle/Resources/config/doctrine/User.orm.yml'
for class 'X\MyBundle\Entity\User'.
Following actions, such as generating the CRUD logic, will not work as long as I have an *.orm.yml file in the config/doctrine folder. If I remove those, CRUD generation will work, but generation of actual mysql tables won't.
Juggling with these gets me to a point where I can also get the tables, but then the actual app doesn't work if I try to use any of the url's where the newly generated CRUD is involved because since the entities are based on yml (which I remove to get things "working") it won't have any mapping knowledge.
Is this inherently wrong? To have yml-based entities in relationship with an User entity based on the FOSUserBundle and still be able to get the nice command-line generation tools?
The problem you describe stems from mixing configuration formats (yaml and I assume annotations). You can easily fix this by ditching the annotations in your models and replacing them with yaml-files like you would do in your own models.
Unfortunately the FOSUserBundle-docs only show you how to use annotations, so here is a quick transformation into yaml format when your X\MyBundle\Entity\User extends FOSUSerBundle's UserEntity:
X\MyBundle\Entity\User:
type: entity
table: fos_user
id:
id:
type: integer
strategy: { generator: "AUTO" }
The remaining stuff is taken care of by FOSUserBundle, as the BaseModel is a mapped-superclass and already describes the stuff in the User.orm.xml, but you could just as well replace the existing values or add additional values just like you would do with your own models.
If you don't use annotations throughout your app, you might also want to disable them in your app/config/config.yml to prevent side effects.

Dynamically creating field using Drupal

Okay lets say I have a basic demographic content type (Client) that I am saving as a node.
I need to make a key for an external database that we occasionally need to work with.
I want Drupal to take the fragments of three fields being collected in the Client content type and join them into a single field to be saved within the Client content type. Ideally this should be done when I create a new (Client) node.
The new field should contain the following
First 3 letters of firstname
First 3 letters of lastname
and last 4 digits of Social Security Number.
For example
firstname: John
lastname: Doe
SSN: 123-45-6789
A new field should be created, let’s call it fk_database. Using the example above the field >created would be -> johdoe6789
Can this be done via Rules module, or should I approach this in a different way? If I need to do this via a PHP script where exactly should that be added in the Drupal structure?
The easiest way would probably be to use the Computed Field module, it's pretty much built for exactly what you want to do:
Computed Field is a very powerful CCK field module that lets you add a custom "computed fields" to your content types. These computed fields are populated with values that you define via PHP code. You may draw on anything available to Drupal, including other fields, the current user, database tables, you name it.
If you do need to do it in code though, have a look into hook_entity_presave() which would probably be the best place to run your code from.
I personally would build a custom module to handle this and make use of the node API to handle the custom fields if you want to build them on the fly?
Modules could be created either in the modules directory on the 'root' or really they should be in sites > all > modules
You'll have to switch it on in the backend under site building > modules to enable it
You will be able to hook into the API and handle requests via the case statements e.g.
function hook_node_load($node, $types) {
//do something on node load
}
function hook_node_update($node) {
//do something on node update
}
function hook_node_insert($node) {
//do something on node insert
}

Where to put entity 'helper functions'?

I am having trouble understand a key concept of Symfony 2.
I am working on a website where users can create content which then can be sent to other people, using a secret url. Something like www.yoursite.com/{secret-identifier-string}.
I plan on doing this as follows:
Persist the user's content.
Create the identifier string containing the content id and the creation timestamp (or any other content which will never change again, as extra safety feature) with a two-way encryption method (like mcrypt_encrypt).
Create the link and display it to the user to give it away
Whenever a url is called, the identifier string will be decrypted. If the provided timestamp matches the corresponding value of the content id row, the page will be displayed.
My questions are:
Would you consider this a good procedure in general?
Outside Symfony2 I would create helper methods like getIdentifierString() and getContentPageLink(). Where do I put the corresponding code in Symfony2? Does it belong inside the entity class? If so I am having problems because I am using a service class for encryption. The service is only available in the controller.
Thanks a lot!
With all due respect to DI and service oriented design, namespacing and all the good stuff we benefit from,
I still refuse to type or read:
$this->mysyperfancyservice->dowhatevertheseviceissupposedtodowith($the_entity);
where a simple
do($the_entity);
is all I need on 150 instances across my project, where do is something everyone working on the project will know about.
That is what helper is meant for - readability and simplicity. As long as it doesn't depend on other services though.
My solution for that is in basic Composer feature:
"autoload": {
...
"files": [ "src/helper/functions.php" ]
}
I put a very limited number of extremely useful functions in src/helper/functions.php file, and add it to project like that.
In order for the function to become available project-wide, it is required to run:
composer dump-autoload
The general idea is that you create "helper classes" rather than "helper functions". Those classes may have dependencies on other classes in which case you'll define them as a service.
It sounds like your methods do have dependencies (on encryption) so you can make a new service that is responsible for generating links. In it's constructor it would take the encryptor and the methods would be passed the entity to generate a link/string for.
for example, your service:
<service id="app_core.linkifier" class="App\CoreBundle\Linkifier">
<argument type="service" id="the.id.for.encryptor"/>
</service>
and class:
class Linkifier
{
private $encryptor;
public function __construct(Encryptor $encryptor)
{
$this->encryptor = $encryptor;
}
public function generateContentPageLink(Entity $the_entity)
{
return $this->encryptor->encrypt($the_entity);
}
}

Resources