Symfony 2 get Sonata media file path in Entity class - symfony

When implementing a __clone() method in media entity, I need to get the absolute path of a file to be able to make a copy of the file itself. I've been searching for a long time and I have not found any documentation to get this. Any ideas?
Here it is the __clone() method where I need the file path:
// Norwalk\StoreBundle\Entity\ProductHasMedia
public function __clone() {
if ($this->id) {
$this->media = clone $this->media;
$this->media->setProviderReference('clone_'.$this->media->getProviderReference());
$this->media->setName('clone_'.$this->media->getName());
$providerMeta = array('filename' => $this->media->getName());
$this->media->setProviderMetadata($providerMeta);
// Clone the physical image file too
$fs = new Filesystem();
$fs->copy( "original_image_path/".$this->media->getName(), "original_image_path/"."clone_".$this->media->getName());
}
}

I don't think it is possible without giving the Entity class to much responsibilities since you can't tell the absolute path name without having some services ('sonata.media.manager.media', 'sonata.media.provider.image' or 'sonata.media.twig.extension')..
The proper way to go is to build a clone function into an controller. The controller can have all the magic (services and entitymanagers) to do the cloning for you.
See this stackoverflow question for an example.

Related

Adding type to a document uploaded in Alfresco through behaviour

I am trying to associate a document type to xz:xylo, whenever a document is uploaded in a particular workspace of Alfresco, it should get attached to a type which I defined in xylomodel.xml.
I am trying to achieve this via Alfresco behaviour as procceding via Share has some limitation for my requirement.
Can anyone please correct me if the code attached is syntactically correct and I am approaching correctly.
enter code here
public class ApplyXyloAspect implements NodeServicePolicies.OnCreateNodePolicy {`
private NodeService nodeService;
private PolicyComponent policyComponent;
// Behaviours
private Behaviour onCreateNode;
}
/**
^When a document of type #XyloCmsType(name = "X:xz:Xylo") is created than aspects from xyloModel.xml
^needs to be applied
*/
public void init() {
// Create behaviours
if workspace=workspace://SpacesStore/973e1b8d-bf61-8196-3278-fbbf0b4375gg
org.alfresco.repo.node.NodeServicePolicies this.onCreateNode = new JavaBehaviour(this, "onCreateNode", NotificationFrequency.FIRST_EVENT);
// Bind behaviours to node policies
this.policyComponent.bindClassBehaviour(Qname.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
Qname.createQName(XYLO.NAMESPACE_XYLO_CONTENT_MODEL, XYLO.TYPE_xz_xyloModel),
this.onCreateNode
);
}
Depending on your requirements you might be better off achieving this through Folder Rules.
If folder rules are not adequate, or if I'm misunderstanding your use of the very specific NodeRef of workspace://SpacesStore/973e1b8d-bf61-8196-3278-fbbf0b4375gg then I would just check in the onCreateNode method if the created node's parent matches that NodeRef, rather than trying to check in the init method.
so in your init method you would just do something like this:
this.onCreateNode = new JavaBehaviour(this, "onCreateNode", Behaviour.NotificationFrequency.FIRST_EVENT);
this.policyComponent.bindClassBehaviour(NodeServicePolicies.OnCreateNodePolicy.QNAME, Qname.createQName(XYLO.NAMESPACE_XYLO_CONTENT_MODEL, XYLO.TYPE_xz_xyloModel), this.onCreateNode);
And then just check if the node is a child of the node you're trying to have be the parent, in this case you said it would be workspace://SpacesStore/973e1b8d-bf61-8196-3278-fbbf0b4375gg.
So the onCreateNode method would look something like this.
#Override
public void onCreateNode(ChildAssociationRef childAssociationRef){
NodeRef idealParentNodeRef = new NodeRef("workspace://SpacesStore/973e1b8d-bf61-8196-3278-fbbf0b4375gg");
NodeRef nodeRef = childAssociationRef.getChildRef();
NodeRef parentRef = childAssociationRef.getParentRef();
//First double check and make sure all the nodes exist.
if(nodeService.exists(nodeRef) && nodeService.exists(parentRef) && nodeService.exists(idealParentNodeRef)){
//then check if the parentRef and the idealParentNodeRef match
if(parentRef.equals(idealParentNodeRef)){
nodeService.addAspect(nodeRef, /*QName of the Aspect you want to add*/);
}
}
}
If you know for a fact the node/workspace you're uploading to will be very specific every time you could just do this, though I would probably also suggest throwing in some error handling, logging, etc. but this would get you started at least.
Note that, generally, you shouldn't necessarily expect the NodeRef to stay the same every time, granted, I'm just showing you what you could do based on the information from your post rather than what you should do (which would be finding some other way to reference the NodeRef/workspace you're trying to use, and going on from there, depending on whether that NodeRef/workspace is a Folder or Site, or something else).
Hope this helps.

How can I add .NET namespace information in DocFX

The title says it all ...
In Sandcastle Help File Builder we added the NamespaceDoc class to each namespace to create namespace documentation.
How do we to the same using DocFX?
Here's how I did it:
In the root folder of your documentation project, add a folder named namespaces.
Update your docfx.json file to include markup files added to the namespaces folder. You need to update the overwrite property in the build section. It will look something like this:
"overwrite": [
{
"files": [
"apidoc/**.md",
"namespaces/**.md"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
Create a markdown file in the namespaces folder for every namespace you want to add documentation to. It is probably best to name these files the same as the namespace.
The files should have a YAML header with a UID that matches the namespace's name. The summary: *content line tells docfx to overwrite the summary of the namespace with the contents of this file.
The rest of the page is standard markdown that will become the namespace's summary. For example:
---
uid: My.Groovy.Namespace
summary: *content
---
The My.Groovy.Namespace namespace contains a bunch of classes and interfaces.
There isn't a way to add it directly in source code. You can use overwrite files to add summary for namespace type.
I'm probably extremely late to this question, but i faced a similar problem and the solution i found invovles modifying docfx from source and adding helping classes, much like Sandcastle's solution.
Disclamer:
I do not claim that the solution i'm showcasing is programmatically
stable, safe or even correct. I do not claim that this solution will
work in any scenario or for any use. I only verify that, for me, it
worked perfectly fine, even though i recongize it's just a fast-put-up
workaround.
Steps :
I downloaded the source code of docfx from their github's releases page (2.59.2, as of today)
After extracting the solution, I opened the file docfx-2.59.2\src\Microsoft.DocAsCode.Metadata.ManagedReference\ExtractMetadataWorker.cs
The class implemented within this file contains a method named GetMetadataFromProjectLevelCache that, at some point, extracts the metadata
from the referenced project in a tree form.
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
// [...]
projectMetadata = controller.ExtractMetadata(key); // THIS line
// [...]
}
After this line, I appended the following line containing a method which I also had to implement.
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
// [...]
projectMetadata = controller.ExtractMetadata(key);
ExtractNamespaceDocumentation(projectMetadata); // THIS line
// [...]
}
The implementation was the following:
private void ExtractNamespaceDocumentation(MetadataItem node)
{
// Terminal nodes are not of our interest in any case
// Even if it's a namespace, it does not contain documentation
if (node.Items is not { Count: > 0 }) return;
// If it is namespace
if (node.Type == MemberType.Namespace)
{
// Get (if any), the child that is class and is named "_NamespaceDoc"
var doc = node.Items.FirstOrDefault(x =>
x.Type == MemberType.Class && x.Name.Split('.').Last() == "_NamespaceDoc");
// If we didn't found such class, the namespace does not contain documentation.
// Leave and don't go further.
if (doc is null) return;
// Else, assign the class' Summary and remarks to the Namespace and remove the class from the tree.
node.Summary = doc.Summary;
node.Remarks = doc.Remarks;
node.Items.Remove(doc);
// job finished for this namespace, we do not want to go further down the tree.
return;
}
// For non-namespace intermediate nodes (IE assembly nodes), visit the children.
foreach (var child in node.Items) ExtractNamespaceDocumentation(child);
}
Lastly, I compiled the solution and, by using the newly created docfx.exe located at docfx-2.59.2\src\docfx\bin\Debug\net472, i was able to detect all classes named _NamespaceDoc and use their <summary> tags to fill the namespaces they resided.
For the record, i decided to create a new .cs file at the root of my project to contain all _NamespaceDoc classes, so it would be easier for me to disable the whole file when i want to release the project. This file looked like this:
namespace RootNamespace
{
/// <summary>
/// Documentation for the Root Namespace
/// </summary>
public static class _NamespaceDoc { }
}
namespace RootNamespace.SubFolder
{
/// <summary>
/// Documentation for the Root Namespace's `SubFolder` Sub-Namespace.
/// </summary>
public static class _NamespaceDoc { }
}
// [...]
Hopefully, this may help other fellows seaking for such solution, or even the docfx devs and contributors to implement this feature more reliably.
Update:
For more info about this approach, I've started a discussion
on docfx's github repository

Laravel Controller does not reflect changes made

I have a controller named FrontEndController.php in my Laravel 5.3 project. When I make any changes in a method, it does not reflect these changes. So, for testing i checked by making changes in other method and faced the same issue. I also created a new method in the same controller and renamed the name of method in route to the newly created method but it throws an exception that method does not exist.
So, just for testing, I renamed the controller to FrontEndController_Jan-17-2017.php and I was shocked to see that it did not throw any exception like FrontEndController.php does not exists.
Now, my question is that from where is laravel getting the FrontEndController.php file if it does not exist in actual or is there any problem of cache etc. which i'm not aware about. I have also tried by clearing the cache using php artisan cache:clear command but still not found any solution.
Route (Not contained in any group or prefix etc.)
Route::get('register', array('as' => 'register','uses' => 'FrontEndController#getRegister'));
Controller
<?php
namespace App\Http\Controllers;
use Activation;
use App\Http\Requests;
use App\Http\Requests\UserRequest;
use App\User;
use App\Contact;
use App\PNumber;
use Cartalyst\Sentinel\Checkpoints\NotActivatedException;
use Cartalyst\Sentinel\Checkpoints\ThrottlingException;
use File;
use Hash;
use Illuminate\Http\Request;
use Lang;
use Mail;
use Redirect;
use Reminder;
use Validator;
use Sentinel;
use URL;
use View;
use Helper;
class FrontEndController extends JoshController
{
/**
* Account Register.
*
* #return View
*/
public function getRegister()
{
// Show the page
return view('register');
}
}

Best way for extending a entity in doctrine

I have a User Entity in a small Framework made by me. Now i want to use this User Entity in several projects.
But in some projects I want to add a few fields to the User Entity without modifying the file.
What I tried so far:
I created a new DefaultUser Entity in a DefaultUser Bundle and made the User Entity a mappedsuperclass. But now I can't make a association in other entities like
/*
* #ORM\ManyToOne(targetEntity="User", inversedBy="jobs")
* #ORM\JoinColumn(name="user", referencedColumnName="id")
*/
private $user;
Because Doctrine can't find the id column in the user entity. This only works if I specify the DefaultUser Entity. According to the doctrine documentation this only works on many to many associations if only one leaf exists.
Then I tried Single Table Inheritance. This works fine but I have to modify the DiscriminatorMap if I want to extend my user entity which is shared acros multiple projects...
So whats the best way to extend the UserEntity?
I have precisely the same problem - I have just switched from RedBean to Doctrine (for a project using the Zend Framework), and the structure of my classes did not take into account this issue. The core problem is that maps in Doctrine have a one to one relationship with classes, as far as I can work out. What we are looking for is a way to have one concrete class (the UserEntity) that uses a map from an abstract class (the DefaultUser). My solution, which may be something of a hack (I've only been using Doctrine for a couple of days), works for YAML at least:
Create a new mapping driver extending the YAML driver, and override the _loadMappingFile method with something like this:
class MyLibrary_Doctrine_Mapping_Driver_YamlExtended extends MyLibrary_Doctrine_Mapping_Driver_YamlExtended
{
protected $_basicEntityFolder;
protected function _loadMappingFile($file)
{
$entMaps = parent::_loadMappingFile($file);
//merge this with any extensions if defined
foreach($entMaps as $ent => $map)
{ //load the relevant map
if (!isset($map['extendEntity'])) {
continue;
}
$fileName = $this->_basicEntityFolder . DIRECTORY_SEPARATOR . str_replace('\\', '.', $map['extendEntity']) . $this->_fileExtension;
$extendedMaps = $this->_loadMappingFile($fileName);
if (!is_array($extendedMaps[$map['extendEntity']])) {
throw new MyProject_Doctrine_Exception("Entity to extend from could not be found.");
}
//merge so that the file lower in the class hierachy always overrides the higher
$map = array_merge($extendedMaps[$map['extendEntity']], $map);
//clear the extendEntity value
unset($map['extendEntity']);
$entMaps[$ent] = $map;
}
return $entMaps;
}
public function setExtendedEntitiesFolder($path)
{
$this->_basicEntityFolder = $path;
}
}
I then have two yaml files, in different folders, like this:
#MyApplication/Entities/Maps/Entities.User.dcm.yml
Entities\User:
extendEntity: LibraryEntities\User
That is the file in the application. Then in the library I have
#Library/Entities/Maps/ExtendedEntities/LibraryEntities.User.dcm.yml
LibraryEntities\User:
type: entity
table: user
fields:
username:
type: text
nullable: true
password:
type: text
nullable: true
defaultProfile:
type: text
nullable: true
column: default_profile
The reason it is in an ExtendedEntities folder is so I can define mappedSuperclasses in the library using a normal namespace, and Doctrine will load those automatically when a class extends them, but these extendedentities are outside of the path for Doctrine's usual class inheritance loading (if they were all in the normal folder structure then for eg "class ApplicationUser extends LibraryUser" Doctrine would try to load the config for LibraryUser because it would find it, and then cause the same error you have already encountered).
Then when I set up my $em I provide it with my driver:
$driverImpl = new MyLibrary_Doctrine_Mapping_Driver_YamlExtended(array(APPLICATION_PATH . '/entities/maps',
LIBRARY_PATH . '/Entities/Maps'));
$driverImpl->setExtendedEntitiesFolder(LIBRARY_PATH . '/Entities/Maps/ExtendedEntities');
Notice that this solution allows inheritance chains defined by 'extendEntity' (because the _loadMappingFile method is recursive). Also that any configuration file lower down the chain can overwrite any property already defined, so even if in your library yaml you had:
username:
type: text
Say you had a project in which usernames where integers you can simply override it in your application config with
username:
type: int
or whatever.
And therefore this solves the problem of defining Doctrine style inheritance on the base class. In every project you can define the DiscriminatorMap however you like.
In principle the same solution could be applied to annotations, though extending the annotation driver is a little more complicated, because it doesn't simply read metadata by reading one file in one go and converting it to an array, but makes numerous requests to the annotation reader, which means implementing this structure would be trickier.
I'd be very interested to know how other people have solved this problem.

Relative path to Entity in getRepository()

It's a bit tedious writing the whole path to the Entity when calling getRepository(). Especially in Symfony2 where it would be Acme\FooBundle\BarEntity. Is it possible to make it so you only have to specify the Entity name?
I'm adding a static method to my entities like this:
public static function getEntityName()
{
return get_called_class();
}
then
use Acme\FooBundle\BarEntity;
$repo = $em->getRepository(BarEntity::getEntityName());
You can write ->getRepository('FooBundle:BarEntity')

Resources