Commit 6f62ba07 authored by Sebastian Castro's avatar Sebastian Castro

Merge Import and importDynamic Admin, so both use mapping tables

parent 49263da7
......@@ -84,6 +84,7 @@
pre {
font-size: 11px;
line-height: 13px;
text-align: left;
}
</style>
......
<?php
namespace Biopen\GeoDirectoryBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
class ImportAdmin extends ImportAbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with("Importer des données en dur, depuis un fichier CSV ou une API Json")
->add('sourceName', 'text', array(
'required' => true,
'label' => 'Nom de la source des données'))
->add('file', 'file', array('label' => 'Fichier à importer', 'required' => false))
->add('url', 'text', array('label' => 'Ou Url vers une API Json', 'required' => false))
->add('geocodeIfNecessary', null, array('required' => false, 'label' => 'Géocoder les élements sans latitude ni longitude à partir de leur adresse'))
// ->add('parentCategoryToCreateOptions', 'sonata_type_model', array(
// 'class'=> 'Biopen\GeoDirectoryBundle\Document\Category',
// 'required' => false,
// 'btn_add' => false,
// 'label' => 'Groupe dans lequel créer les catégories manquantes',
// 'mapped' => true), array('admin_code' => 'admin.category'))
->add('createMissingOptions', null, array('required' => false, 'label' => 'Créer les catégories manquantes à partir des catégories renseignées dans chaque élément'))
->add('optionsToAddToEachElement', 'sonata_type_model', array(
'class'=> 'Biopen\GeoDirectoryBundle\Document\Option',
'required' => false,
'choices_as_values' => true,
'multiple' => true,
'btn_add' => false,
'label' => 'Catégories à ajouter à chaque élément importé'), array('admin_code' => 'admin.option'))
->end()
->with('Aide', ["description" => $this->getInstructions('05a0895f-7b11-4a96-a98b-43fef68840a1')])
->end()
;
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('execute', $this->getRouterIdParameter().'/execute');
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('id')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('fileName')
->add('_action', 'actions', array(
'actions' => array(
'edit' => array(),
)
))
;
}
}
\ No newline at end of file
<?php
namespace Biopen\GeoDirectoryBundle\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Biopen\GeoDirectoryBundle\Document\ElementStatus;
class ImportDynamicAdmin extends ImportAbstractAdmin
{
public function getTemplate($name)
{
switch ($name) {
case 'edit': return '@BiopenAdmin/edit/edit_import_dynamic.html.twig';
break;
default : return parent::getTemplate($name);
break;
}
}
protected function configureFormFields(FormMapper $formMapper)
{
$dm = $this->getConfigurationPool()->getContainer()->get('doctrine_mongodb');
$repo = $dm->getRepository('BiopenGeoDirectoryBundle:Element');
$formProperties = json_encode($repo->findFormProperties());
$elementProperties = json_encode($repo->findDataCustomProperties());
$optionsList = $dm->getRepository('BiopenGeoDirectoryBundle:Option')->createQueryBuilder()
->select('name')->hydrate(false)->getQuery()->execute()->toArray();
$optionsList = json_encode($optionsList);
$formMapper
->tab('Général')
->with("Import Dynamique, pour afficher des données gérées par quelqu'un d'autre", ['class' => 'col-md-6'])
->add('sourceName', 'text', array('required' => true, 'label' => 'Nom de la source '))
->add('url', 'text', array('label' => "Url de l'api Json", 'required' => true))
->add('refreshFrequencyInDays', null, array('required' => false, 'label' => "Fréquence de mise à jours des données en jours (laisser vide pour ne jamais mettre à jour automatiquement"))
->add('idsToIgnore', 'text', array('required' => false, 'attr' => ['class' => 'gogo-display-array'], 'label' => "Liste des IDs qui seront ignorées lors de l'import", 'label_attr' => ['title' => "Pour ignorer un élément, supprimer le (définitivement) et il ne sera plus jamais importé. Si vous supprimez un élément dynamiquement importé juste en changeant son status (soft delete), l'élément sera quand meme importé mais conservera son status supprimé. Vous pourrez donc à tout moment restaurer cet élement pour le voir apparaitre de nouveau"]))
->end()
->with("Autres options", ['box_class' => 'box box-default', 'class' => 'col-md-6'])
->add('geocodeIfNecessary', null, array('required' => false, 'label' => 'Géocoder les élements sans latitude ni longitude à partir de leur adresse'))
->add('createMissingOptions', null, array('required' => false, 'label' => 'Créer les catégories manquantes', 'label_attr' => ['title' => "Si un élément importé a une catégorie qui n'existe pas encore sur votre carte, elle sera automatiquement crée"]))
->add('optionsToAddToEachElement', 'sonata_type_model', array(
'class'=> 'Biopen\GeoDirectoryBundle\Document\Option',
'required' => false,
'choices_as_values' => true,
'multiple' => true,
'btn_add' => false,
'label' => 'Catégories à ajouter à chaque élément importé'), array('admin_code' => 'admin.option'))
->add('needToHaveOptionsOtherThanTheOnesAddedToEachElements', null, array('required' => false, 'label' => 'Les éléments importés doivent contenir au moins une catégorie en dehors de celles ajoutées manuellement ci-dessus', 'label_attr' => ['title' => "Sans prendre en compte les catégories ajoutés via le champs \"Catégories à ajouter à chaque élément importé\", si les éléments importés n'ont pas de catégories, ils seront marqués comme \"Modération aucune catégorie renseignée\""]))
->add('fieldToCheckElementHaveBeenUpdated', null, array('required' => false, 'label' => "Nom de l'attribut à comparer pour la mise à jour", 'label_attr' => ['title' => "Lorsqu'on met à jour une source, certains des éléments à importer existent déjà dans notre base de donnée. Vous pouvez renseigner ici un champs qui permettra de comparer si l'élément à été mis à jour au sein de la source depuis le dernier import. Exple de champ: updatedAt, date_maj etc... (laisser vide pour mettre à jour les éléments à chaque fois)"]))
->end();
if ($this->getSubject()->getId())
{
$formMapper->with('Historique', array('class' => 'col-sm-12'))
->add('logs', 'hidden', array('attr' => ['class' => 'gogo-display-logs'], 'mapped' => false))
->end();
}
$formMapper->end();
$formMapper->tab('Modifier les données en exécutant du code')
->with('Entrez du code qui sera exécuté à la reception des données, avant leur traitement par GoGoCarto', ["description" => "La variable <b>\$data</b> représente le tableau PHP créé à partir des données Csv ou Json. Quelques examples de transformations simple:
<pre>&lt;?php</br>\$data = \$data['elements']</pre>
<pre>&lt;?php</br>foreach(\$data as \$key => \$row) {
\$data[\$key]['source'] = \"MySource\";
}</pre>
<pre>&lt;?php</br>foreach(\$data as \$key => \$row) {
\$data[\$key]['latitude'] = \$row['geo']['latitude']);
\$data[\$key]['longitude'] = \$row['geo']['longitude']);
}</pre>
<pre>&lt;?php</br>foreach(\$data as \$key => \$row) {
\$data[\$key]['categories'] = array_map(function(\$cat) { return \$cat[0]; }, \$row['categories']);
}</pre>"])
->add('customCode', 'text', array('label' => 'Code PHP qui sera exécuté', 'attr' => ['class' => 'gogo-code-editor', 'format' => 'php', 'height' => '500'], 'required' => false))
->end()
->end();
if ($this->getSubject()->getId())
{
$formMapper
->tab('Table de correspondance des champs')
->with('Transformer les données à importer')
->add('ontologyMapping', 'hidden', array('attr' => ['class' => 'gogo-mapping-ontology', 'data-form-props' => $formProperties, 'data-props' => $elementProperties]))
->end()
->end();
if (count($this->getSubject()->getOntologyMapping()) > 0)
{
$formMapper->tab('Table de correspondance des catégories')
->with('Faites correspondre les catégories')
->add('taxonomyMapping', 'hidden', array('attr' => ['class' => 'gogo-mapping-taxonomy', 'data-options' => $optionsList]))
->end()
->end();
}
}
$formMapper
->tab('Aide')
->with("Aide", ['box_class' => 'box box-default', "description" => $this->getInstructions('13154fa0-13c2-41f1-a4ad-e04c35c86e89')])
->end()
->end();
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('refresh', $this->getRouterIdParameter().'/refresh');
$collection->add('collect', $this->getRouterIdParameter().'/collect');
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('sourceName')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$dm = $this->getConfigurationPool()->getContainer()->get('doctrine_mongodb');
$deletedElementsCount = $dm->getRepository('BiopenGeoDirectoryBundle:Element')->findDeletedElementsByImportIdCount();
$listMapper
->addIdentifier('sourceName', null, array('label' => 'Nom de la source'))
// Total count
->add('logs', null, array('label' => "Nombre d'éléments", 'template' => '@BiopenAdmin/partials/import/list_total_count.html.twig'))
// non visibles count
->add('idsToIgnore', null, array('label' => "Infos", 'template' => '@BiopenAdmin/partials/import/list_non_visibles_count.html.twig', 'choices' => $deletedElementsCount))
->add('refreshFrequencyInDays', null, array('label' => 'Mise à jour', 'template' => '@BiopenAdmin/partials/import/list_refresh_frequency.html.twig'))
->add('lastRefresh', null, array('label' => 'Derniere mise à jour', 'template' => '@BiopenAdmin/partials/import/list_last_refresh.html.twig'))
->add('_action', 'actions', array(
'actions' => array(
'edit' => array(),
'delete' => array(),
'refresh' => array('template' => '@BiopenAdmin/partials/list__action_refresh.html.twig'),
)
))
;
}
}
\ No newline at end of file
<?php
namespace Biopen\GeoDirectoryBundle\Controller\Admin;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Biopen\GeoDirectoryBundle\Document\ElementStatus;
use Biopen\GeoDirectoryBundle\Document\ImportState;
class ImportAdminController extends Controller
{
public function listAction()
{
return $this->redirect($this->admin->generateUrl('create'));
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->remove('edit');
}
private function executeImport($import)
{
$object = $import;
$em = $this->get('doctrine_mongodb')->getManager();
$em->flush();
$object->setCurrState(ImportState::Started);
$object->setCurrMessage("En attente...");
$em->persist($object);
$em->flush();
$this->get('biopen.async')->callCommand('app:elements:importSource', [$object->getId()]);
// $result = $this->get('biopen.element_import')->startImport($object);
$redirectionUrl = $this->admin->generateUrl('create');
$stateUrl = $this->generateUrl('biopen_import_state', ['id' => $object->getId()]);
return $this->render('@BiopenAdmin/pages/import/import-progress.html.twig', [
'import' => $object,
'redirectUrl' => $redirectionUrl,
'stateUrl' => $stateUrl
]);
}
// This method is just an overwrite of the SonataAdminCRUDController for calling the executeImport once the document is created
public function createAction()
{
$request = $this->getRequest();
$this->admin->checkAccess('create');
$object = $this->admin->getNewInstance();
$this->admin->setSubject($object);
$form = $this->admin->getForm();
$form->setData($object);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid) {
try {
$object = $this->admin->create($object);
return $this->executeImport($object);
} catch (ModelManagerException $e) {
$this->handleModelManagerException($e);
$isFormValid = false;
}
}
if (!$isFormValid) { // show an error message if the form failed validation
$text = $this->trans('flash_create_error', array('%name%' => $this->escapeHtml($this->admin->toString($object))), 'SonataAdminBundle');
$this->addFlash('sonata_flash_error', $text);
}
}
$view = $form->createView();
// set the theme for the current Admin Form
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render('@BiopenAdmin/edit/edit_import.html.twig', array(
'action' => 'create',
'form' => $view,
'object' => $object,
), null);
}
}
\ No newline at end of file
<?php
namespace Biopen\GeoDirectoryBundle\Controller\Admin;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Biopen\GeoDirectoryBundle\Document\ImportState;
class ImportDynamicAdminController extends Controller
{
public function collectAction()
{
$object = $this->admin->getSubject();
$result = $this->get('biopen.element_import')->collectData($object);
$this->addFlash('sonata_flash_success', "Les données ont été chargées avec succès.</br>Voici le résultat obtenu pour le premier élément à importer :<pre>" . print_r($result, true) . '</pre>');
$url = $this->admin->generateUrl('edit', ['id' => $object->getId()]);
return $this->redirect($url);
}
public function refreshAction()
{
$object = $this->admin->getSubject();
$object->setCurrState(ImportState::Started);
$object->setCurrMessage("En attente...");
$em = $this->get('doctrine_mongodb')->getManager();
$em->persist($object);
$em->flush();
// $this->get('biopen.async')->callCommand('app:elements:importSource', [$object->getId()]);
$result = $this->get('biopen.element_import')->importJson($object);
$redirectionUrl = $this->admin->generateUrl('edit', ['id' => $object->getId()]);
$stateUrl = $this->generateUrl('biopen_import_state', ['id' => $object->getId()]);
return $this->render('@BiopenAdmin/pages/import/import-progress.html.twig', [
'import' => $object,
'redirectUrl' => $redirectionUrl,
'redirectListUrl' => $redirectionUrl = $this->admin->generateUrl('list'),
'stateUrl' => $stateUrl
]);
}
/**
* Overite Sonata CRud Controller
*/
public function editAction($id = null)
{
$request = $this->getRequest();
$id = $request->get($this->admin->getIdParameter());
$object = $this->admin->getObject($id);
if (!$object) throw $this->createNotFoundException(sprintf('unable to find the object with id : %s', $id));
$this->admin->checkAccess('edit', $object);
$this->admin->setSubject($object);
$form = $this->admin->getForm();
$form->setData($object);
$form->handleRequest($request);
if ($form->isSubmitted()) {
//TODO: remove this check for 4.0
if (method_exists($this->admin, 'preValidate')) {
$this->admin->preValidate($object);
}
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid) {
try {
// ----- CUSTOM -------
$object->setOntologyMapping($request->get('ontology'));
$object->setTaxonomyMapping($request->get('taxonomy'));
// ---- END CUSTOM ------
$object = $this->admin->update($object);
$this->addFlash(
'sonata_flash_success',
$this->trans(
'flash_edit_success',
array('%name%' => $this->escapeHtml($this->admin->toString($object))),
'SonataAdminBundle'
)
);
if ($request->get('collect')) {
$url = $this->admin->generateUrl('collect', ['id' => $object->getId()]);
} else if ($request->get('import')) {
$url = $this->admin->generateUrl('refresh', ['id' => $object->getId()]);
} else {
$url = $this->admin->generateUrl('edit', ['id' => $object->getId()]);
}
return $this->redirect($url);
} catch (ModelManagerException $e) {
$this->handleModelManagerException($e);
$isFormValid = false;
} catch (LockException $e) {
$this->addFlash('sonata_flash_error', $this->trans('flash_lock_error', array(
'%name%' => $this->escapeHtml($this->admin->toString($object)),
'%link_start%' => '<a href="'.$this->admin->generateObjectUrl('edit', $object).'">',
'%link_end%' => '</a>',
), 'SonataAdminBundle'));
}
}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest()) {
$this->addFlash(
'sonata_flash_error',
$this->trans(
'flash_edit_error',
array('%name%' => $this->escapeHtml($this->admin->toString($object))),
'SonataAdminBundle'
)
);
}
}
}
$view = $form->createView();
// set the theme for the current Admin Form
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render($this->admin->getTemplate('edit'), array(
'action' => 'edit',
'form' => $view,
'object' => $object,
), null);
}
/**
* Overwrite Sonata CRud Controller
*/
public function createAction()
{
$request = $this->getRequest();
// the key used to lookup the template
$templateKey = 'edit';
$this->admin->checkAccess('create');
$class = new \ReflectionClass($this->admin->hasActiveSubClass() ? $this->admin->getActiveSubClass() : $this->admin->getClass());
$object = $this->admin->getNewInstance();
$this->admin->setSubject($object);
$form = $this->admin->getForm();
$form->setData($object);
$form->handleRequest($request);
if ($form->isSubmitted()) {
//TODO: remove this check for 4.0
if (method_exists($this->admin, 'preValidate')) {
$this->admin->preValidate($object);
}
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid && (!$this->isInPreviewMode($request) || $this->isPreviewApproved($request))) {
try {
$object = $this->admin->create($object);
$result = $this->get('biopen.element_import')->collectData($object);
$this->addFlash('sonata_flash_success', "Les données ont été chargées avec succès. Vous pouvez maintenant compléter les tables de correspondances, puis importer les données.");
$url = $this->admin->generateUrl('edit', ['id' => $object->getId()]) . "#tab_3";
return $this->redirect($url);
} catch (ModelManagerException $e) {
$this->handleModelManagerException($e);
$isFormValid = false;
}
}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest()) {
$this->addFlash(
'sonata_flash_error',
$this->trans(
'flash_create_error',
array('%name%' => $this->escapeHtml($this->admin->toString($object))),
'SonataAdminBundle'
)
);
}
} elseif ($this->isPreviewRequested()) {
// pick the preview template if the form was valid and preview was requested
$templateKey = 'preview';
$this->admin->getShow();
}
}
$view = $form->createView();
// set the theme for the current Admin Form
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render($this->admin->getTemplate($templateKey), array(
'action' => 'create',
'form' => $view,
'object' => $object,
), null);
}
}
\ No newline at end of file
......@@ -128,6 +128,13 @@ class Import extends AbstractFile
*/
private $customCode = "<?php";
/**
* @var date $lastRefresh
*
* @MongoDB\Field(type="date")
*/
private $lastRefresh = null;
public function __construct() {
$this->logs = new \Doctrine\Common\Collections\ArrayCollection();;
......@@ -516,4 +523,26 @@ class Import extends AbstractFile
{
return $this->customCode;
}
/**
* Set lastRefresh
*
* @param date $lastRefresh
* @return $this
*/
public function setLastRefresh($lastRefresh)
{
$this->lastRefresh = $lastRefresh;
return $this;
}
/**
* Get lastRefresh
*
* @return date $lastRefresh
*/
public function getLastRefresh()
{
return $this->lastRefresh;
}
}
......@@ -13,20 +13,14 @@ use \Datetime;
class ImportDynamic extends Import
{
/**
* @var string
* @var string
* @MongoDB\Field(type="int")
*/
private $refreshFrequencyInDays;
/**
* @var date $lastRefresh
*
* @MongoDB\Field(type="date")
*/
private $lastRefresh = null;
/**
* @var date $lastRefresh
* @var date $nextRefresh
*
* @MongoDB\Field(type="date")
*/
......@@ -35,17 +29,17 @@ class ImportDynamic extends Import
public function isDynamicImport() { return true; }
public function updateNextRefreshDate()
public function updateNextRefreshDate()
{
if ($this->getRefreshFrequencyInDays() == 0) $this->setNextRefresh(null);
else
{
else
{
$interval = new \DateInterval('P' . $this->getRefreshFrequencyInDays() .'D');
$date = new DateTime();
$date->setTimestamp(time());
$this->setNextRefresh($date->add($interval));
}
}
}
/**
* Set refreshFrequencyInDays
......@@ -70,28 +64,6 @@ class ImportDynamic extends Import
return $this->refreshFrequencyInDays;
}
/**
* Set lastRefresh
*
* @param date $lastRefresh
* @return $this
*/
public function setLastRefresh($lastRefresh)
{
$this->lastRefresh = $lastRefresh;
return $this;
}
/**
* Get lastRefresh
*
* @return date $lastRefresh
*/
public function getLastRefresh()
{
return $this->lastRefresh;
}
/**
* Set nextRefresh
*
......
......@@ -11,6 +11,7 @@ use Biopen\GeoDirectoryBundle\Document\Element;
use Application\Sonata\UserBundle\Document\Group;
use Biopen\GeoDirectoryBundle\Document\Option;
use Biopen\GeoDirectoryBundle\Document\ImportDynamic;
use Biopen\GeoDirectoryBundle\Document\Import;
use Biopen\GeoDirectoryBundle\Document\Webhook;
use Doctrine\ODM\MongoDB\DocumentManager;
......@@ -42,7 +43,7 @@ class DatabaseIntegrityWatcher
}
}
}
else if ($document instanceof ImportDynamic)
else if ($document instanceof Import || $document instanceof ImportDynamic)
{
$import = $document;
$qb = $dm->getRepository('BiopenGeoDirectoryBundle:Element')->createQueryBuilder();
......
......@@ -3,17 +3,17 @@ services:
class: Biopen\GeoDirectoryBundle\Admin\Element\ElementAdmin
arguments: [~, Biopen\GeoDirectoryBundle\Document\Element, 'BiopenGeoDirectoryBundle:Admin/ElementAdmin']
tags:
- { name: sonata.admin, manager_type: doctrine_mongodb, group: "data", label: Éléments }
- { name: sonata.admin, manager_type: doctrine_mongodb, group: "data", label: Éléments }
admin.import:
class: Biopen\GeoDirectoryBundle\Admin\ImportAdmin
arguments: [~, Biopen\GeoDirectoryBundle\Document\Import, 'BiopenGeoDirectoryBundle:Admin/ImportAdmin']
tags:
- { name: sonata.admin, manager_type: doctrine_mongodb, group: "data", label: Import }
- { name: sonata.admin, manager_type: doctrine_mongodb, group: "data", label: Import }
admin.source_external:
class: Biopen\GeoDirectoryBundle\Admin\ImportDynamicAdmin
arguments: [~, Biopen\GeoDirectoryBundle\Document\ImportDynamic, 'BiopenGeoDirectoryBundle:Admin/ImportDynamicAdmin' ]
class: Biopen\GeoDirectoryBundle\Admin\ImportAdmin
arguments: [~, Biopen\GeoDirectoryBundle\Document\ImportDynamic, 'BiopenGeoDirectoryBundle:Admin/ImportAdmin' ]