diff --git a/Controller/JsloaderController.php b/Controller/JsloaderController.php
index eed3377..38786e5 100644
--- a/Controller/JsloaderController.php
+++ b/Controller/JsloaderController.php
@@ -6,6 +6,7 @@
FOS\RestBundle\View\View;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* This controller includes the correct twig file to bootstrap the javascript
@@ -43,6 +44,26 @@ class JsloaderController
*/
private $plainTextTypes;
+ /**
+ * @var array
+ */
+ private $createRoutesForTypes;
+
+ /**
+ * @var array locales of the application
+ */
+ private $locales;
+
+ /**
+ * @var string content prefix in the repository path, like /cms/content
+ */
+ private $contentPrefix;
+
+ /**
+ * @var string routes prefix in the repository path, like /cms/routes
+ */
+ private $routesPrefix;
+
/**
* Create the Controller
@@ -52,32 +73,48 @@ class JsloaderController
* @param string $imageClass used to determine whether image upload should be activated
* @param Boolean $fixedToolbar whether the hallo toolbar is fixed or floating
* @param array $plainTextTypes RDFa types to edit in raw text only
- * @param string $requiredRole
+ * @param array $createRoutesForTypes types for which it is needed to create a route
+ * @param string $requiredRole the role name for the security check
* @param SecurityContextInterface $securityContext
+ * @param array $locales the locales of the application
+ * @param string $contentPrefix content prefix in the repository path
+ * @param string $routesPrefix routes prefix in the repository path
*/
public function __construct(
ViewHandlerInterface $viewHandler,
$stanbolUrl,
$imageClass,
$fixedToolbar = true,
- $plainTextTypes = array(),
+ array $plainTextTypes = array(),
+ array $createRoutesForTypes = array(),
$requiredRole = "IS_AUTHENTICATED_ANONYMOUSLY",
- SecurityContextInterface $securityContext = null
+ SecurityContextInterface $securityContext = null,
+ array $locales,
+ $contentPrefix,
+ $routesPrefix
) {
$this->viewHandler = $viewHandler;
$this->stanbolUrl = $stanbolUrl;
$this->imageClass = $imageClass;
$this->fixedToolbar = $fixedToolbar;
$this->plainTextTypes = $plainTextTypes;
-
+ $this->createRoutesForTypes = $createRoutesForTypes;
$this->requiredRole = $requiredRole;
$this->securityContext = $securityContext;
+ $this->locales = $locales;
+ $this->contentPrefix = $contentPrefix;
+ $this->routesPrefix = $routesPrefix;
}
/**
* Render js inclusion for create.js and dependencies and bootstrap code.
*
* The hallo editor is bundled with create.js and available automatically.
+<<<<<<< HEAD
+ * To use aloha, you need to download the zip, as explained in step 8 of
+ * the README.
+=======
+>>>>>>> master
*
* When using hallo, the controller can include the compiled js files from
* hallo's examples folder or use the assetic coffee filter.
@@ -101,11 +138,17 @@ public function includeJSFilesAction($editor = 'hallo')
$view->setTemplate(sprintf('SymfonyCmfCreateBundle::includejsfiles-%s.html.twig', $editor));
+
+
$view->setData(array(
'cmfCreateStanbolUrl' => $this->stanbolUrl,
'cmfCreateImageUploadEnabled' => (boolean) $this->imageClass,
'cmfCreateHalloFixedToolbar' => (boolean) $this->fixedToolbar,
- 'cmfCreateHalloPlainTextTypes' => json_encode($this->plainTextTypes)
+ 'cmfCreateHalloPlainTextTypes' => json_encode($this->plainTextTypes),
+ 'cmfCreateCreateRoutesTypes' => json_encode($this->createRoutesForTypes),
+ 'cmfCreateLocales' => json_encode($this->locales),
+ 'cmfCreateContentPrefix' => $this->contentPrefix,
+ 'cmfCreateRoutesPrefix' => $this->routesPrefix
)
);
diff --git a/Controller/RestController.php b/Controller/RestController.php
index bb52f76..2114ac8 100755
--- a/Controller/RestController.php
+++ b/Controller/RestController.php
@@ -115,16 +115,22 @@ public function postDocumentAction(Request $request)
$this->performSecurityChecks();
$rdfType = trim($request->request->get('@type'), '<>');
+
$type = $this->typeFactory->getTypeByRdf($rdfType);
- $result = $this->restHandler->run($request->request->all(), $type, null, RestService::HTTP_POST);
+ $result = null;
+ try {
+ $result = $this->restHandler->run($request->request->all(), $type, null, RestService::HTTP_POST);
+ } catch (\Exception $e) {
+ return Response::create("The document '$rdfType' could not be created: " . $e->getMessage(), 500);
+ }
if (!is_null($result)) {
$view = View::create($result)->setFormat('json');
return $this->viewHandler->handle($view, $request);
}
- return Response::create('The document could not be created', 500);
+ return Response::create("The document '$rdfType' could not be created", 500);
}
/**
diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index 02ef8e5..8772cc5 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -27,6 +27,10 @@ public function getConfigTreeBuilder()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
+ ->arrayNode('rdfmapper')
+ ->useAttributeAsKey('name')
+ ->prototype('scalar')->end()
+ ->end()
->scalarNode('role')->defaultValue('IS_AUTHENTICATED_ANONYMOUSLY')->end()
->arrayNode('image')
->canBeUnset()
@@ -43,6 +47,10 @@ public function getConfigTreeBuilder()
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
+ ->arrayNode('create_routes_types')
+ ->useAttributeAsKey('name')
+ ->prototype('scalar')->end()
+ ->end()
->arrayNode('rdf_config_dirs')
->useAttributeAsKey('dir')
->prototype('scalar')->end()
diff --git a/DependencyInjection/SymfonyCmfCreateExtension.php b/DependencyInjection/SymfonyCmfCreateExtension.php
index c1c3da1..88c21db 100644
--- a/DependencyInjection/SymfonyCmfCreateExtension.php
+++ b/DependencyInjection/SymfonyCmfCreateExtension.php
@@ -41,6 +41,8 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter($this->getAlias().'.map', $config['map']);
+ $container->setParameter($this->getAlias().'.rdfmapper', $config['rdfmapper']);
+
$container->setParameter($this->getAlias().'.stanbol_url', $config['stanbol_url']);
$container->setParameter($this->getAlias().'.role', $config['role']);
@@ -52,6 +54,8 @@ public function load(array $configs, ContainerBuilder $container)
}
$container->setParameter($this->getAlias().'.plain_text_types', $config['plain_text_types']);
+ $container->setParameter($this->getAlias().'.create_routes_types', $config['create_routes_types']);
+
if ($config['auto_mapping']) {
foreach ($container->getParameter('kernel.bundles') as $class) {
$bundle = new \ReflectionClass($class);
diff --git a/Mapper/RouteDoctrinePhpcrOdmMapper.php b/Mapper/RouteDoctrinePhpcrOdmMapper.php
new file mode 100644
index 0000000..5dca5d6
--- /dev/null
+++ b/Mapper/RouteDoctrinePhpcrOdmMapper.php
@@ -0,0 +1,33 @@
+getIdentifier() === 'locale') {
+ $object->setDefault('_locale', $value);
+ $object->setRequirement('_locale', $value);
+ return $object;
+ }
+ return parent::setPropertyValue($object, $property, $value);
+ }
+
+ public function getPropertyValue($object, PropertyInterface $property)
+ {
+ if ($object instanceof Route && $property->getIdentifier() === 'locale') {
+ return $object->getDefault('_locale');
+ }
+ return parent::getPropertyValue($object, $property);
+ }
+}
diff --git a/Metadata/ContainerRdfTypeFactory.php b/Metadata/ContainerRdfTypeFactory.php
new file mode 100644
index 0000000..d7ca433
--- /dev/null
+++ b/Metadata/ContainerRdfTypeFactory.php
@@ -0,0 +1,64 @@
+mapperServices = $mapperServices;
+ parent::__construct($defaultMapper, $driver);
+ }
+
+ /**
+ * Get the mapper for type $name in the $symfony container, or the defaultMapper if there is no specific one
+ *
+ * @param string $name the type name for which to get the mapper
+ *
+ * @return RdfMapperInterface
+ */
+ protected function getMapper($name)
+ {
+ if (isset($this->mapperServices[$name])) {
+ return $this->container->get($this->mapperServices[$name]);
+ }
+
+ return parent::getMapper($name);
+ }
+
+ /**
+ * @see ContainerAwareInterface::setContainer()
+ */
+ public function setContainer(ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
+}
diff --git a/Resources/config/phpcr_odm.xml b/Resources/config/phpcr_odm.xml
index ef12ed4..cf5bc58 100755
--- a/Resources/config/phpcr_odm.xml
+++ b/Resources/config/phpcr_odm.xml
@@ -6,6 +6,7 @@
Midgard\CreatePHP\Mapper\DoctrinePhpcrOdmMapper
+ Symfony\Cmf\Bundle\CreateBundle\Mapper\RouteDoctrinePhpcrOdmMapper
@@ -16,5 +17,11 @@
null
+
+ %symfony_cmf_create.map%
+
+ null
+
+
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index 5fecac1..fe06428 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -8,6 +8,7 @@
Symfony\Cmf\Bundle\CreateBundle\Controller\JsloaderController
Symfony\Cmf\Bundle\CreateBundle\Controller\RestController
Midgard\CreatePHP\Metadata\RdfTypeFactory
+ Symfony\Cmf\Bundle\CreateBundle\Metadata\ContainerRdfTypeFactory
Midgard\CreatePHP\RestService
@@ -18,21 +19,25 @@
%symfony_cmf_create.image.model_class%
%symfony_cmf_create.fixed_toolbar%
%symfony_cmf_create.plain_text_types%
+ %symfony_cmf_create.create_routes_types%
%symfony_cmf_create.role%
+ %locales%
+ %symfony_cmf_content.content_basepath%
+ %symfony_cmf_routing_extra.routing_repositoryroot%
-
+
%symfony_cmf_create.role%
-
+
@@ -40,10 +45,13 @@
%symfony_cmf_create.rdf_config_dirs%
-
+
- %symfony_cmf_create.map%
+ %symfony_cmf_create.rdfmapper%
+
+
+
diff --git a/Resources/public/js/create-routes-handler.js b/Resources/public/js/create-routes-handler.js
new file mode 100644
index 0000000..1ff24d5
--- /dev/null
+++ b/Resources/public/js/create-routes-handler.js
@@ -0,0 +1,88 @@
+jQuery(document).ready(function() {
+
+ (function(){
+
+ var createRouteForTypes = []; //types currently needing a route creation
+
+ //remove the enclosing <>
+ function trimAttribute(value) {
+ if (value instanceof Array) {
+ //Create.js sometimes adds the owl#Thing type without reasons
+ value = value[value.length - 1];
+ }
+ return value.substring(1, value.length - 1);
+ }
+
+ //an entity has been saved and the response of the backend received
+ $('body').bind('midgardstoragesavedentity', function (event, options) {
+
+ var createdType = trimAttribute(options.entity.attributes["@type"]);
+
+ if ($.inArray(createdType, createRouteForTypes) == -1) {
+ return;
+ }
+ //reset the types for which route creation is currently needed
+ createRouteForTypes.splice($.inArray(createdType, createRouteForTypes),1);
+
+ var vie = options.entity.vie;
+
+ /**
+ * Common request content
+ */
+ var trimmedSubject = options.entity.id.substr(1, options.entity.id.length - 2);
+ var lastSlashPos = trimmedSubject.lastIndexOf("/") + 1;
+ var contentName = trimmedSubject.substr(lastSlashPos, trimmedSubject.length - lastSlashPos);
+ var partOf = options.entity.attributes[""].models[0]["@subject"];
+ var trimmedPartOf = partOf.substr(1, partOf.length - 2); // "/cms/content/news"
+ var lastSlashPos = trimmedPartOf.lastIndexOf("/") + 1;
+ var parentName = trimmedPartOf.substr(lastSlashPos, trimmedPartOf.length - lastSlashPos);
+
+ /**
+ * Request types
+ */
+ var parentType = "<" + cmfCreateRouteRdfType + "/Parent" + ">";
+ var nameType = "<" + cmfCreateRouteRdfType + "/Name" + ">";
+ var routeContentType = "<" + cmfCreateRouteRdfType + "/RouteContent" + ">";
+ var localeType = "<" + cmfCreateRouteRdfType + "/Locale" + ">";
+ var partOfType = "";
+
+ for(var i in cmfCreateLocales) {
+ var parentPath = cmfCreateRoutesPrefix + "/" + cmfCreateLocales[i] + "/" + parentName;
+
+ var routeRequest = {};
+ routeRequest["@type"] = "<" + cmfCreateRouteRdfType + ">";
+ routeRequest[nameType] = contentName;
+ routeRequest[routeContentType] = trimmedSubject;
+ routeRequest[partOfType] = [parentPath];
+ routeRequest[localeType] = cmfCreateLocales[i];
+ routeRequest[parentType] = parentPath;
+
+ var routeEntity = new vie.Entity();
+ routeEntity.set(routeRequest);
+ vie.entities.add(routeEntity);
+ jQuery('body').midgardStorage('saveRemote', routeEntity, {
+ success: function (m, err) {
+ jQuery('body').midgardNotifications('create', {
+ body: 'Route ' + m.attributes[routeContentType] + ' created successfully'
+ });
+ },
+ error: function (m, err) {
+ jQuery('body').midgardNotifications('create', {
+ body: 'Error during creation of route ' + m.attributes[partOfType] + '/' + m.attributes[nameType] + '. ' + err.responseText,
+ timeout: 0
+ });
+ }
+ });
+ }
+ });
+
+ //an entity will be saved and sent to the backend
+ $('body').bind('midgardstoragesaveentity', function (event, options) {
+ var type = trimAttribute(options.entity.attributes['@type']);
+ if (options.entity.isNew() &&
+ $.inArray(type, cmfCreateCreateRoutesTypes) != -1) {
+ createRouteForTypes.push(type);
+ }
+ });
+ })()
+});
diff --git a/Resources/public/vendor/create b/Resources/public/vendor/create
index 271e011..0011a6f 160000
--- a/Resources/public/vendor/create
+++ b/Resources/public/vendor/create
@@ -1 +1 @@
-Subproject commit 271e0114a039ab256ffcceacdf7f361803995e05
+Subproject commit 0011a6faecbb9421d3bf19e7c85d147f8698da47
diff --git a/Resources/rdf-mappings/Symfony.Cmf.Bundle.RoutingExtraBundle.Document.Route.xml b/Resources/rdf-mappings/Symfony.Cmf.Bundle.RoutingExtraBundle.Document.Route.xml
new file mode 100644
index 0000000..26fb36e
--- /dev/null
+++ b/Resources/rdf-mappings/Symfony.Cmf.Bundle.RoutingExtraBundle.Document.Route.xml
@@ -0,0 +1,20 @@
+
+ dcterms:partOf
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Resources/views/includejsfiles-create.html.twig b/Resources/views/includejsfiles-create.html.twig
index 872670b..01fc0a0 100644
--- a/Resources/views/includejsfiles-create.html.twig
+++ b/Resources/views/includejsfiles-create.html.twig
@@ -20,6 +20,12 @@
var cmfCreateHalloParentElement = 'body';
{% endif %}
var cmfCreateHalloPlainTextTypes = {{ cmfCreateHalloPlainTextTypes|raw }};
+ var cmfCreateCreateRoutesTypes = {{ cmfCreateCreateRoutesTypes|raw }};
+ var cmfCreateLocales = {{ cmfCreateLocales|raw }};
+ var cmfCreateContentPrefix = '{{ cmfCreateContentPrefix }}';
+ var cmfCreateRoutesPrefix = '{{ cmfCreateRoutesPrefix }}';
+ var cmfCreateRouteRdfType = "http://cmf.symfony.com/CmfRoute";
+
{% javascripts output="js/create.js"
@@ -33,6 +39,7 @@
'@SymfonyCmfCreateBundle/Resources/public/vendor/create/deps/jquery.tagsinput.min.js'
'@SymfonyCmfCreateBundle/Resources/public/vendor/create/deps/annotate-min.js'
'@SymfonyCmfCreateBundle/Resources/public/vendor/create/examples/create-min.js'
+ '@SymfonyCmfCreateBundle/Resources/public/js/create-routes-handler.js'
%}
{% endjavascripts %}
@@ -61,4 +68,4 @@ and set up assetic to handle coffee script files
'@SymfonyCmfCreateBundle/Resources/public/js/init-vie-hallo.js'
'@SymfonyCmfCreateBundle/Resources/public/vendor/hallo/hallo.coffee'
'@SymfonyCmfCreateBundle/Resources/public/vendor/hallo/plugins/*.coffee'
-#}
\ No newline at end of file
+#}