src/Ox/HoardBundle/Controller/ReferenceController.php line 325

Open in your IDE?
  1. <?php
  2. namespace App\Ox\HoardBundle\Controller;
  3. use Symfony\Component\HttpFoundation\Request;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\HttpFoundation\JsonResponse;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  8. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
  9. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  10. use Symfony\Component\HttpFoundation\File\File;
  11. use Symfony\Component\Filesystem\Filesystem;
  12. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  13. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  14. use Symfony\Component\Form\Extension\Core\Type\ButtonType;
  15. use Knp\Component\Pager\PaginatorInterface;
  16. use App\Ox\HoardBundle\Entity\Reference;
  17. use App\Ox\HoardBundle\Form\ReferenceType;
  18. /**
  19.  * Reference controller.
  20.  *
  21.  * @Route("/reference")
  22.  */
  23. class ReferenceController extends AbstractController
  24. {
  25.     /**
  26.      * Suggest
  27.      * @Route("/suggest", name="suggest_reference", methods={"GET"})
  28.      */
  29.     public function suggestReference(Request $request)
  30.     {
  31.         $em $this->getDoctrine()->getManager();
  32.         //get query params
  33.         $query $request->get('q');
  34.         $typeID $request->get('type');
  35.         $queryBuilder $em->createQueryBuilder();
  36.         $queryBuilder->select('r.title, r.id, r.authors, r.year, r.abbreviation, r.sortValue')
  37.             ->from('OxHoardBundle:Reference''r')
  38.             ->orderBy('r.sortValue''DESC')
  39.             ->addOrderBy('r.authors''ASC')
  40.             ->addOrderBy('r.abbreviation''ASC')
  41.             ->addOrderBy('r.title''ASC')
  42.             ;
  43.         //match query against year, title or authors
  44.         if($query) {
  45.             $queryBuilder $queryBuilder->where('r.title LIKE :query')
  46.                                         ->orWhere('r.abbreviation LIKE :query')
  47.                                         ->orWhere('r.authors LIKE :query')
  48.                                         ->orWhere('r.year LIKE :query')
  49.                                         ->setParameter('query''%'.$query.'%')
  50.                                         ;
  51.         }
  52.         //check type
  53.         if($typeID) {
  54.             $type $em->getRepository('OxHoardBundle:ReferenceType')->find($typeID);
  55.             $queryBuilder $queryBuilder->andWhere('r.referenceType = :refType')
  56.                 ->setParameter('refType'$type);
  57.         }
  58.         $query $queryBuilder->getQuery();
  59.         $queryResult $query->getArrayResult();
  60.         $response = array();
  61.         foreach($queryResult as $result) {
  62.             //compile the text version of the reference
  63.             $text '';
  64.             if($result['abbreviation']) { $text .= $result['abbreviation']; }
  65.             else {
  66.                 if( $result['authors'] ) { $text.=$result['authors'].' - '; }
  67.                 if( $result['year'] ) { $text.=$result['year'].' - '; }
  68.                 if( $result['title'] ) {
  69.                     $text.=$result['title'];
  70.                 } else {
  71.                     $text.='Untitled';
  72.                 }
  73.             }
  74.             $result['text'] = $text;
  75.             $response[] = $result;
  76.         }
  77.         return new JsonResponse($response);
  78.     }
  79.     /**
  80.      * Lists all Reference entities.
  81.      *
  82.      * @Route("/", name="reference", methods={"GET"})
  83.      * @Template()
  84.      */
  85.     public function indexAction(Request $requestPaginatorInterface $paginator)
  86.     {
  87.         $limit 20;
  88.         $em $this->getDoctrine()->getManager();
  89.         $em->getFilters()->enable('softdeleteable');
  90.         
  91.         $queryBuilder $em->createQueryBuilder();
  92.         $queryBuilder->select('r, type')
  93.             ->from('OxHoardBundle:Reference''r')
  94.             ->leftJoin('r.referenceType''type');
  95.         $activeTab $request->query->get('active-tab');
  96.         if ($activeTab == '#tabs-2') {
  97.             // advanced search
  98.             $title $request->query->get('title');
  99.             if ($title) {
  100.                 $queryBuilder->andWhere('r.title LIKE :chosenTitle')
  101.                 ->setParameter('chosenTitle''%'.$title.'%');
  102.             }
  103.             $titleEdition $request->query->get('title-edition');
  104.             if ($titleEdition) {
  105.                 $queryBuilder->andWhere('r.titleEdition LIKE :chosenTitleEdition')
  106.                 ->setParameter('chosenTitleEdition''%'.$titleEdition.'%');
  107.             }
  108.             $abbreviation $request->query->get('abbreviation');
  109.             if ($abbreviation) {
  110.                 $queryBuilder->andWhere('r.abbreviation LIKE :chosenAbbreviation')
  111.                 ->setParameter('chosenAbbreviation''%'.$abbreviation.'%');
  112.             }
  113.             
  114.             $yearFrom $request->query->get('year-from');
  115.             if ($yearFrom) {
  116.                 $queryBuilder->andWhere('r.year >= :chosenYearFrom')
  117.                 ->setParameter('chosenYearFrom'$yearFrom);
  118.             }
  119.             
  120.             $yearTo $request->query->get('year-to');
  121.             if ($yearTo) {
  122.                 $queryBuilder->andWhere('r.year <= :chosenYearTo')
  123.                 ->setParameter('chosenYearTo'$yearTo);
  124.             }
  125.             
  126.             $referenceType null;
  127.             $referenceTypeId $request->query->get('reference-type');
  128.             if($referenceTypeId) {
  129.                 $referenceType $em->getRepository('OxHoardBundle:ReferenceType')->find($referenceTypeId);
  130.                 if ($referenceType) {
  131.                     $queryBuilder->andWhere('r.referenceType = :chosenReferenceType')
  132.                         ->setParameter('chosenReferenceType'$referenceType);
  133.                 }
  134.             }
  135.             
  136.             $author $request->query->get('author');
  137.             if ($author) {
  138.                 $queryBuilder->andWhere('r.authors LIKE :chosenAuthor')
  139.                 ->setParameter('chosenAuthor''%'.$author.'%');
  140.             }
  141.             
  142.             $internalNote $request->query->get('internal-note');
  143.             if ($internalNote) {
  144.                 $queryBuilder->andWhere('r.internalNote LIKE :chosenInternalNote')
  145.                 ->setParameter('chosenInternalNote''%'.$internalNote.'%');
  146.             }
  147.             $volume $request->query->get('volume');
  148.             if ($volume) {
  149.                 $queryBuilder->andWhere('r.volume = :chosenVolume')
  150.                 ->setParameter('chosenVolume'$volume);
  151.             }
  152.         } else { //simple search
  153.             if(isset($_GET['search']))
  154.             {
  155.                 $searchValue $_GET['search'];
  156.                 $queryBuilder->where('r.title LIKE :search')
  157.                     ->orWhere('r.authors LIKE :search'
  158.                     ->orWhere('r.abbreviation LIKE :search')
  159.                     ->orWhere('r.titleEdition LIKE :search')
  160.                     ->setParameter('search','%'.$searchValue.'%');
  161.             }
  162.         }
  163.         $query $queryBuilder->getQuery()
  164.             ->setFirstResult(0)
  165.             ->setMaxResults($limit);
  166.         $pagination $paginator->paginate(
  167.             $query,
  168.             $request->query->getInt('page'1),/* page number */
  169.             $limit
  170.         );
  171.         $isAuthenticated false;
  172.         if($this->getUser()) {
  173.             $isAuthenticated true;
  174.         }
  175.         $sortFields = array();
  176.         if ($isAuthenticated) {
  177.             $sortFields[] = array('label' => 'ID''key' => 'r.id''defaultDirection' => 'asc');
  178.         }
  179.         $sortFields array_merge($sortFields, array(
  180.             array('label' => 'Author''key' => 'r.authors''defaultDirection' => 'asc'),
  181.             array('label' => 'Year''key' => 'r.year''defaultDirection' => 'desc'),
  182.             array('label' => 'Title''key' => 'r.title''defaultDirection' => 'asc'),
  183.             array('label' => 'Title (journal, series)''key' => 'r.titleEdition''defaultDirection' => 'asc'),
  184.         ));
  185.         if ($isAuthenticated) {
  186.             $sortFields[] = array('label' => 'Sort Value''key' => 'r.sortValue''defaultDirection' => 'desc');
  187.         }
  188.         
  189.         $isAdmin $this->userIsAdmin();
  190.         $referenceTypes $em->createQuery('SELECT rt FROM OxHoardBundle:ReferenceType rt ORDER BY rt.referenceType')->getResult();
  191.         return $this->render('@OxHoardBundle/reference/list.html.twig', array(
  192.             'pagination' => $pagination,
  193.             'sort_fields' => $sortFields,
  194.             'is_authenticated' => $isAuthenticated,
  195.             'is_admin' => $isAdmin,
  196.             'reference_types' => $referenceTypes,
  197.             // 'filtered_type' => $filteredType,
  198.             // 'abbreviations' => $onlyAbbreviated,
  199.             // 'own_column_only' => $ownColumnOnly,
  200.             'search_term' => isset($searchValue)?$searchValue:null,
  201.             'title' => isset($title) ? $title null,
  202.             'title_edition' => isset($titleEdition) ? $titleEdition null,
  203.             'abbreviation' => isset($abbreviation) ? $abbreviation null,
  204.             'volume' => isset($volume) ? $volume null,
  205.             'year_from' => isset($yearFrom) ? $yearFrom null,
  206.             'year_to' => isset($yearTo) ? $yearTo null,
  207.             'reference_type' => isset($referenceTypeId) ? $referenceTypeId null,
  208.             'author' => isset($author) ? $author null,
  209.             'internalNote' => isset($internalNote) ? $internalNote null,
  210.             'active_tab' => isset($activeTab) ? $activeTab"#tabs-1",
  211.         ));
  212.     }
  213.     /**
  214.      * Creates a new Reference entity.
  215.      *
  216.      * @Route("/", name="reference_create", methods={"POST"})
  217.      * @Template("@OxHoardBundle/reference/new.html.twig")
  218.      */
  219.     public function createAction(Request $request)
  220.     {
  221.         //only logged in users can create
  222.         if(!$this->getUser()) {
  223.             throw new AccessDeniedException("Only logged in contributors may create a reference entry");
  224.         }
  225.         $reference = new Reference();
  226.         $form $this->createCreateForm($reference);
  227.         $form->handleRequest($request);
  228.         if ($form->isValid()) {
  229.             $em $this->getDoctrine()->getManager();
  230.             $em->persist($reference);
  231.             $em->flush();
  232.             return $this->redirect($this->generateUrl('reference_show', array('id' => $reference->getId())));
  233.         }
  234.         return array(
  235.             'reference' => $reference,
  236.             'form'   => $form->createView(),
  237.         );
  238.     }
  239.     /**
  240.      * Creates a form to create a Reference entity.
  241.      *
  242.      * @param Reference $reference The entity
  243.      *
  244.      * @return \Symfony\Component\Form\Form The form
  245.      */
  246.     private function createCreateForm(Reference $reference)
  247.     {
  248.         $form $this->createForm(ReferenceType::class, $reference, array(
  249.             'action' => $this->generateUrl('reference_create'),
  250.             'method' => 'POST',
  251.         ));
  252.         $form->add('submit'SubmitType::class, array('label' => 'Create'));
  253.         return $form;
  254.     }
  255.     /**
  256.      * Displays a form to create a new Reference entity.
  257.      *
  258.      * @Route("/new", name="reference_new", methods={"GET"})
  259.      * @Template()
  260.      */
  261.     public function newAction()
  262.     {
  263.         //only logged in users can create
  264.         if(!$this->getUser()) {
  265.             throw new AccessDeniedException("Only logged in contributors may create a reference entry");
  266.         }
  267.         $reference = new Reference();
  268.         $form   $this->createCreateForm($reference);
  269.         return $this->render('@OxHoardBundle/reference/new.html.twig', array(
  270.             'reference' => $reference,
  271.             'edit_form'   => $form->createView(),
  272.             'is_admin' => $this->userIsAdmin(),
  273.         ));
  274.     }
  275.     /**
  276.      * Finds and displays a Reference entity.
  277.      *
  278.      * @Route("/{id}", name="reference_show", methods={"GET"})
  279.      * @Template()
  280.      */
  281.     public function showAction(Request $request$id)
  282.     {
  283.         $em $this->getDoctrine()->getManager();
  284.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  285.         // if the hoard is not fount check if it soft-deleted
  286.         if (!$reference) {
  287.             $em->getFilters()->disable('softdeleteable');
  288.             $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  289.             $em->getFilters()->enable('softdeleteable');
  290.             // if it is not soft-deleted return "not found"
  291.             if (!$reference) {
  292.                 throw $this->createNotFoundException('Unable to find Reference entity.');
  293.             } else {
  294.                 // else check if it is really soft-deleted and redirect ti the redirectId
  295.                 $redirect_id $reference->getRedirectToReference();
  296.                 if ($reference->getDeletedAt() && $redirect_id) {
  297.                     return $this->redirect($this->generateUrl('reference_show', array('id' => $redirect_id)));
  298.                 } else {
  299.                     throw $this->createNotFoundException('Unable to find Reference entity.');
  300.                 }
  301.             }
  302.         }
  303.         // $isAuthenticated = false;
  304.         // if($this->getUser()) {
  305.         //     $isAuthenticated = true;
  306.         // }
  307.         $isAuthenticated false;
  308.         if($this->getUser()) {
  309.             $isAuthenticated true;
  310.         }
  311.         $hoards = [];
  312.         foreach($reference->getHoardReferences() as $hoardReference) {
  313.             $hoardId $hoardReference->getHoard()->getId();
  314.             $em->getFilters()->disable('softdeleteable');
  315.             $hoard $em->getRepository('OxHoardBundle:Hoard')->find($hoardId);
  316.             if (!$hoard->getDeletedAt()) {
  317.                 if ($isAuthenticated || ($hoard->getValidatedByUser())) {
  318.                     $hoards[] = $hoard;
  319.                 }
  320.             }
  321.             $em->getFilters()->enable('softdeleteable');
  322.         }
  323.     
  324.         usort($hoards, array($this"cmp"));
  325.         
  326.         $deleteForm $this->createDeleteForm($id);
  327.         $referer $request->get('referer');
  328.         if(!$referer) {
  329.             $referer $request->headers->get('referer');
  330.         }
  331.         if (!strpos($referer"/reference/")) {
  332.             $referer null;
  333.         }
  334.         if (strpos($referer"/edit")) {
  335.             $referer null;
  336.         }
  337.         return array(
  338.             'reference' => $reference,
  339.             'hoards' => $hoards,
  340.             'delete_form' => $deleteForm->createView(),
  341.             'is_authorised_to_edit' => $this->checkAccess($reference'edit'false),
  342.             'is_authenticated' => $isAuthenticated,
  343.             'referer' => $referer,
  344.         );
  345.     }
  346.     function cmp($a$b)
  347.     {
  348.         $aCountry $a->getCountries()[0].'';
  349.         $bCountry $b->getCountries()[0].'';
  350.         $aName $a.'';
  351.         $bName $b.'';
  352.         $aStr $aCountry $aName;
  353.         $bStr $bCountry $bName;
  354.         return strcasecmp($aStr,$bStr);
  355.     }
  356.     /**
  357.      * Displays a form to edit an existing Reference entity.
  358.      *
  359.      * @Route("/{id}/edit", name="reference_edit", methods={"GET"})
  360.      * @Template()
  361.      */
  362.      public function editAction(Request $request$id)
  363.     {
  364.         $em $this->getDoctrine()->getManager();
  365.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  366.         if (!$reference) {
  367.             throw $this->createNotFoundException('Unable to find Reference entity.');
  368.         }
  369.     
  370.         $this->checkAccess($reference'edit');
  371.         $editForm $this->createEditForm($reference$request);
  372.         $deleteForm $this->createDeleteForm($id);
  373.         $hoards $request->getSession()->get('hoards');
  374.         $coins $request->getSession()->get('coins');
  375.         $objects $request->getSession()->get('objects');
  376.         $request->getSession()->clear('hoards');
  377.         $request->getSession()->clear('coins');
  378.         $request->getSession()->clear('objects');
  379.         return array(
  380.             'hoards' => $hoards,
  381.             'coins'       => $coins,
  382.             'objects'       => $objects,
  383.             'reference'      => $reference,
  384.             'edit_form'   => $editForm->createView(),
  385.             'delete_form' => $deleteForm->createView(),
  386.             'is_admin' => $this->userIsAdmin(),
  387.         );
  388.     }
  389.     /**
  390.     * Creates a form to edit a Reference entity.
  391.     *
  392.     * @param Reference $reference The entity
  393.     *
  394.     * @return \Symfony\Component\Form\Form The form
  395.     */
  396.     private function createEditForm(Reference $reference$request)
  397.     {
  398.         $referer $request->get('referer');
  399.         if(!$referer)
  400.         {
  401.             $referer $request->headers->get('referer');
  402.         }
  403.                
  404.         $action $this->generateUrl('reference_update', array('id' => $reference->getId()));
  405.         if($referer) {
  406.             $action .= '?referer='.$referer;
  407.         }
  408.         $form $this->createForm(ReferenceType::class, $reference, array(
  409.             'action' => $action,
  410.             'method' => 'PUT',
  411.         ));
  412.         if($this->userIsAdmin())
  413.         {
  414.             $form->add('hasOwnColumn');
  415.         }
  416.         $form->add('submit'SubmitType::class, array('label' => 'Update'));
  417.         return $form;
  418.     }
  419.     /**
  420.      * Edits an existing Reference entity.
  421.      *
  422.      * @Route("/{id}", name="reference_update", methods={"PUT"})
  423.      * @Template("@OxHoardBundle/reference/edit.html.twig")
  424.      */
  425.     public function updateAction(Request $request$id)
  426.     {
  427.        // echo $request->get('referer');exit;
  428.         $em $this->getDoctrine()->getManager();
  429.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  430.         if (!$reference) {
  431.             throw $this->createNotFoundException('Unable to find Reference entity.');
  432.         }
  433.         $this->checkAccess($reference'edit');
  434.         $deleteForm $this->createDeleteForm($id);
  435.         $editForm $this->createEditForm($reference$request);
  436.         $editForm->handleRequest($request);
  437.         $hoards = [];
  438.         $coins = [];
  439.         $objects = [];
  440.         if ($editForm->isValid()) {
  441.             $em->flush();
  442.   
  443.             $referer $request->get('referer');
  444.             if(!$referer) {
  445.                 $referer $request->headers->get('referer');
  446.             }
  447.             
  448.             $page $request->get('page');
  449.             if(isset($page)) {
  450.                 $referer .= '&page=' $page;
  451.             }
  452.             return $this->redirect($referer);
  453.             
  454.         }
  455.         return array(
  456.             'hoards'      => $hoards,
  457.             'coins'       => $coins,
  458.             'objects'     => $objects,
  459.             'reference'      => $reference,
  460.             'edit_form'   => $editForm->createView(),
  461.             'delete_form' => $deleteForm->createView(),
  462.         );
  463.     }
  464.     /**
  465.      * Deletes a Reference entity.
  466.      *
  467.      * @Route("/{id}", name="reference_delete", methods={"DELETE"})
  468.      */
  469.     public function deleteAction(Request $request$id)
  470.     {
  471.         $form $this->createDeleteForm($id);
  472.         $form->handleRequest($request);
  473.         if ($form->isValid()) {
  474.             try {
  475.                 $em $this->getDoctrine()->getManager();
  476.                 $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  477.                 if (!$reference) {
  478.                     throw $this->createNotFoundException('Unable to find Reference entity.');
  479.                 }
  480.                 if (!$this->getUser() || !($this->getUser()->hasRole('ROLE_ADMIN') || $this->getUser()->hasRole('ROLE_SUPER_ADMIN'))) {
  481.                     $request->getSession()->getFlashBag()
  482.                         ->add('error''Unable to delete Reference. Only admins can delete references.');
  483.                     return $this->redirect($this->generateUrl('reference_edit', array('id' => $reference->getId())));
  484.                 }
  485.                 // check whether it is in use
  486.                 $queryBuilder $em->createQueryBuilder();
  487.                 $queryBuilder->select('hrdref, h')
  488.                             ->from('OxHoardBundle:HoardReference''hrdref')
  489.                             ->leftJoin('hrdref.hoard''h')
  490.                             ->leftJoin('hrdref.reference''r')
  491.                             ->where('r.id = :query')
  492.                             ->setParameter('query'$id);
  493.                 $query $queryBuilder->getQuery();
  494.                 $hoards $query->getResult();
  495.                 $queryBuilder $em->createQueryBuilder();
  496.                 $queryBuilder->select('coiref, h')
  497.                             ->from('OxHoardBundle:CoinReference''coiref')
  498.                             ->leftJoin('coiref.coin''h')
  499.                             ->leftJoin('coiref.reference''r')
  500.                             ->where('r.id = :query')
  501.                             ->setParameter('query'$id);
  502.                 $query $queryBuilder->getQuery();
  503.                 $coins $query->getResult();
  504.                 $queryBuilder $em->createQueryBuilder();
  505.                 $queryBuilder->select('objref, o')
  506.                             ->from('OxHoardBundle:ObjectReference''objref')
  507.                             ->leftJoin('objref.object''o')
  508.                             ->leftJoin('objref.reference''r')
  509.                             ->where('r.id = :query')
  510.                             ->setParameter('query'$id);
  511.                 $query $queryBuilder->getQuery();
  512.                 $objects $query->getResult();
  513.                 if(count($hoards) > || count($coins) > || count($objects) > 0) {
  514.                   $request->getSession()->set('hoards'$hoards);
  515.                   $request->getSession()->set('coins'$coins);
  516.                   $request->getSession()->set('objects'$objects);
  517.                   return $this->redirect($this->generateUrl('reference_edit', array('id' => $reference->getId())));
  518.                 } else {
  519.                   $em->remove($reference);
  520.                   $em->flush();
  521.                   return $this->redirect($this->generateUrl('reference'));
  522.                 }
  523.             } catch (\Exception $e) {
  524.                 //an exception is thrown if the entity is used by any non-deleted coins. Tell the user that this is probably the case.
  525.                 $request->getSession()
  526.                     ->getFlashBag()
  527.                     ->add('error''Unable to delete Reference. It may currently be in use on a coin, object or hoard.');
  528.                 return $this->redirect($this->generateUrl('reference_edit', array('id' => $reference->getId())));
  529.             }
  530.         }
  531.         return $this->redirect($this->generateUrl('reference'));
  532.     }
  533.     /**
  534.      * Creates a form to delete a Reference entity by id.
  535.      *
  536.      * @param mixed $id The entity id
  537.      *
  538.      * @return \Symfony\Component\Form\Form The form
  539.      */
  540.     private function createDeleteForm($id)
  541.     {
  542.         return $this->createFormBuilder()
  543.             ->setAction($this->generateUrl('reference_delete', array('id' => $id)))
  544.             ->setMethod('DELETE')
  545.             ->add('submit'ButtonType::class, array(
  546.                 'label' => 'Delete this reference',
  547.                 'attr' => array(
  548.                     'class' => 'delete-button btn btn-danger'
  549.                 )
  550.             ))
  551.             ->getForm()
  552.         ;
  553.     }
  554.     
  555.     
  556.     /**
  557.      * Upload a new pdf file for the reference
  558.      *
  559.      * @Route("/{id}/ajax_add_file", methods={"POST"})
  560.      */
  561.     public function setFile(Request $request$id)
  562.     {
  563.         $em $this->getDoctrine()->getManager();
  564.         
  565.         $file $request->files->get('file');
  566.         
  567.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  568.         if(!$reference)
  569.         {
  570.             throw $this->createNotFoundException('Unable to find Reference entity.');
  571.         }
  572.         if(!$file->getMimeType() == 'application/pdf')
  573.         {
  574.             return new JsonResponse(array('success'=> 0'error'=> 'Invalid file type. Only pdf files may be uploaded'));
  575.         }
  576.         $isValid true;
  577.         
  578.         //build new fileName
  579.         $now = new \DateTime();
  580.         $nowString $now->format('Ymd-His');
  581.         $fileName $id.'-'.$nowString.'.'.$file->guessExtension();
  582.         
  583.         $file $file->move($this->getPermanentReferenceRootDir(), $fileName);
  584.         
  585.         $reference->setFilePath($fileName);
  586.         $em->flush();
  587.         
  588.         return new JsonResponse( array('success' => 1'filepath' => $reference->getFilePath()));
  589.     }
  590.     
  591.     /**
  592.      * Retrieve pdf file
  593.      * @Route("/{id}/file", name="reference_file", requirements={"id": "\d+"}, methods={"GET"})
  594.      */
  595.     public function getFile($id)
  596.     {
  597.         $em $this->getDoctrine()->getManager();
  598.         
  599.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  600.         if(!$reference)
  601.         {
  602.             throw $this->createNotFoundException('Unable to find Reference entity.');
  603.         }
  604.         
  605.         if(!$reference->getIsFilePublic() && !$this->getUser())
  606.         {
  607.             throw $this->createNotFoundException('Unable to find Reference file.');
  608.         }
  609.         $pdf = new File($this->getPermanentReferenceRootDir().$reference->getFilePath());
  610.         
  611.         $file $pdf->openFile();
  612.         
  613.         $contents file_get_contents($file->getRealPath());
  614.         $response = new Response($contents);
  615.         $response->headers->set('Content-Type'$pdf->getMimeType());
  616.         $response->headers->set('Content-Length'$file->getSize());
  617.         $response->headers->set('ETag'md5($contents));
  618.         $response->headers->set('Last-Modified'$reference->getModifiedDate()->format('D, d M Y H:i:s T'));
  619.         
  620.         return $response;
  621.     }
  622.     /**
  623.      * Delete pdf file
  624.      * @Route("/{id}/ajax_delete_file", methods={"POST"})
  625.      */
  626.     public function deleteFile(Request $request$id)
  627.     {
  628.         $em $this->getDoctrine()->getManager();
  629.         $reference $em->getRepository('OxHoardBundle:Reference')->find($id);
  630.         if(!$reference)
  631.         {
  632.             throw $this->createNotFoundException('Unable to find Reference entity.');
  633.         }
  634.         $this->checkAccess($reference'edit');
  635.         $pdf = new File($this->getPermanentReferenceRootDir().$reference->getFilePath());
  636.         $filesystem = new Filesystem();
  637.         $filesystem->remove($pdf);
  638.         
  639.         $reference->setFilePath(null);
  640.         $em->flush();
  641.          
  642.         return new JsonResponse( array('success' => 1));
  643.     }
  644.     private function cleanZenonField($input) {
  645.         //use a regex to strip any extraneous punctuation chars from the end
  646.         // e.g. "London :" --> "London"
  647.         // e.g. "Ionian magistrates. Caracalla or Elagabalus? -." -> "Ionian magistrates. Caracalla or Elagabalus?"
  648.         $cleanRegex '/(.*)(\s+[^\w\d\s]*\s*)$/';
  649.         $matches null;
  650.         if( preg_match($cleanRegex$input$matches)) {
  651.             return $matches[1];
  652.         } else {
  653.             //match failed (it really shouldn't though)
  654.             return $input;
  655.         }
  656.     }
  657.     //return an array of strings from matches for the given tag (e.g. '300') and code (e.g. 'a')
  658.     private function extractZenonParam($xpath$tag$code$clean true) {
  659.         $query '//marc:datafield[@tag="'.$tag.'"]';
  660.         if($code) {
  661.             $query .= '/marc:subfield[@code="'.$code.'"]';
  662.         }
  663.         $els $xpath->query($query);
  664.         
  665.         $resp = [];
  666.         foreach($els as $el) {
  667.             $content $el->textContent;
  668.             if($clean) {
  669.                 $resp[] = $this->cleanZenonField($content);
  670.             } else {
  671.                 $resp[] = $content;
  672.             }
  673.         }
  674.         return $resp;
  675.     }
  676.     /**
  677.      *  Look up zenon reference
  678.      *  @Route("/zenon_lookup/{id}", name="zenon_lookup", methods={"GET"})
  679.      */
  680.     public function zenonLookupAction($id) {
  681.         
  682.         $output $this->getZenonInfo($id);
  683.         return new JsonResponse($output);
  684.     }
  685.     
  686.     // given an array of strings ["A", "B", "C", "D"], join them as "A, B, C and D"
  687.     private function joinZenonEntries($entries) {
  688.         $out "";
  689.         $len count($entries);
  690.         foreach($entries as $i => $entry) {
  691.             if($i === 0) {
  692.                 //first
  693.                 $out .= $entry;
  694.             } else if($i $len -1) {
  695.                 //middle
  696.                 $out .= ", ".$entry;
  697.             } else {
  698.                 //last
  699.                 $out .= " and ".$entry;
  700.             }
  701.         }
  702.         return $out;
  703.     }
  704.     
  705.     private function getZenonInfo($id) {
  706.         // $url = "http://opac.dainst.org/OAI?verb=GetRecord&identifier=oai:dai-all:DAI01-".$id."&metadataPrefix=marc21";
  707.         $url "https://zenon.dainst.org/Record/".$id."/Export?style=MARCXML";
  708.         $defaults = array(
  709.             CURLOPT_URL => $url,
  710.             CURLOPT_HEADER => 0,
  711.             CURLOPT_RETURNTRANSFER => TRUE,
  712.             CURLOPT_TIMEOUT => 4
  713.         );
  714.         
  715.         $ch curl_init();
  716.         curl_setopt_array($ch$defaults);
  717.         if( ! $result curl_exec($ch))
  718.         { 
  719.             return new JsonResponse("Error querying zenon");
  720.         } 
  721.         curl_close($ch);
  722.         
  723.         $xmlDoc = new \DOMDocument();
  724.         $xmlDoc->loadXml($result);
  725.         $xpath = new \DomXPath($xmlDoc);
  726.         $xpath->registerNamespace('marc''http://www.loc.gov/MARC21/slim');
  727.         // $xpath->registerNamespace('', 'http://www.openarchives.org/OAI/2.0/');
  728.         //extract the relevant fields
  729.         //tag 245a = Title
  730.         //tag 245b = Subtitle
  731.         //tag 110 = Corporate authors
  732.         //tag 100a = author
  733.         //tag 710a = Other authors
  734.         // see http://zenon.dainst.org/Record/000294077 where other authors is at 700a
  735.         //tag 260a = place
  736.         //tag 260b = publisher
  737.         //tag 260c = publication year
  738.         //tag 440a = Title Edition?
  739.         //tag 995n = Included in = Title edition
  740.         //tag 300a = pages
  741.         //tag 440v = volume
  742.         //tag 700a = additional authors
  743.         
  744.         //tag 995b = included in zenon ID
  745.         
  746.         //Assuming any field could yield multiple results from zenon (authors, editors often will)
  747.         // concatenate all results with a comma
  748.         
  749.         $output = [
  750.             'zenon_url' => $url
  751.         ];
  752.         
  753.         $errs $xmlDoc->getElementsByTagName('error');
  754.         if($errs->length) {
  755.             $output['zenon_error'] = $errs->item(0)->textContent;
  756.         } else {
  757.             //title
  758.             $titles $this->extractZenonParam($xpath'245''a'false);
  759.             $subtitles $this->extractZenonParam($xpath'245''b'false);
  760.             //combine subtitles. Unlikely to be more than one of each, but just in case
  761.             // $output['title'] = $this->cleanZenonField(implode(', ', $titles) ." ". implode(', ', $subtitles));
  762.             $output['title'] = $this->cleanZenonField($this->joinZenonEntries($titles) ." "$this->joinZenonEntries($subtitles));
  763.             
  764.             //authors
  765.             $mainAuthors $this->extractZenonParam($xpath'100''a');
  766.             $output['mainAuthors'] = $this->joinZenonEntries($mainAuthors);
  767.             $additionalAuthors $this->extractZenonParam($xpath'700''a');
  768.             $output['additionalAuthors'] = $this->joinZenonEntries($additionalAuthors);
  769.             $allAuthors array_merge($mainAuthors$additionalAuthors);
  770.             $output['authors'] = $this->joinZenonEntries($allAuthors);
  771.             
  772.             //place
  773.             $places $this->extractZenonParam($xpath'260''a');
  774.             $output['place'] = $this->joinZenonEntries($places);
  775.             
  776.             //publisher
  777.             $publishers $this->extractZenonParam($xpath'260''a');
  778.             $output['publisher'] = $this->joinZenonEntries($publishers);
  779.             
  780.             //publication year
  781.             $pubYears $this->extractZenonParam($xpath'260''c');
  782.             $output['year'] = $this->joinZenonEntries($pubYears);
  783.             
  784.             //title edition, might be tag 440a or 995n (for a chapter)
  785.             $titleEds $this->extractZenonParam($xpath'440''a');
  786.             // don't use the 995 field - get by following link to parent
  787.             // if(count($titleEds) == 0) {
  788.             //     $titleEds = $this->extractZenonParam($xpath, '995', 'n');
  789.             // }
  790.             $output['titleEdition'] = $this->joinZenonEntries($titleEds);
  791.             
  792.             //pages
  793.             $pagesSet $this->extractZenonParam($xpath'300''a');
  794.             $output['pages'] = $this->joinZenonEntries($pagesSet);
  795.             
  796.             //volume - might be tag 440v, or if this is a parent record representing a volume, tag 245n
  797.             $volumes $this->extractZenonParam($xpath'440''v');
  798.             if(count($volumes) == 0) {
  799.                 $volumes $this->extractZenonParam($xpath'245''n');
  800.             }
  801.             $output['volume'] = $this->joinZenonEntries($volumes);
  802.             
  803.             //additional authors
  804.             $additionalAuthors $this->extractZenonParam($xpath'700''a');
  805.             $output['additionalAuthors'] = $this->joinZenonEntries($additionalAuthors);
  806.             
  807.             // get further info from the publication which this is included in (e.g. for article / chapter)
  808.             $parentIds $this->extractZenonParam($xpath'995''b');
  809.             if(count($parentIds) > 0) {
  810.                 //assume only 1 parent
  811.                 $parentId $parentIds[0];
  812.                 $parentData $this->getZenonInfo($parentId);
  813.                 if(!isset($output['place']) || $output['place'] == '') {
  814.                     $output['place'] = $parentData['place'];
  815.                 }
  816.                 if(!isset($output['publisher']) || $output['publisher'] == '') {
  817.                     $output['publisher'] = $parentData['publisher'];
  818.                 }
  819.                 if(!isset($output['year']) || $output['year'] == '') {
  820.                     $output['year'] = $parentData['year'];
  821.                 }
  822.                 if(!isset($output['editors']) || $output['editors'] == '') {
  823.                     $output['editors'] = $parentData['additionalAuthors'];
  824.                 }
  825.                 // Use the author of the parent reference as editor of this reference?
  826.                 
  827.                 if(!isset($output['volume']) || $output['volume'] == '') {
  828.                     $output['volume'] = $parentData['volume'];
  829.                 }
  830.                 if(!isset($output['titleEdition']) || $output['titleEdition'] == '') {
  831.                     $output['titleEdition'] = $parentData['title'];
  832.                 }
  833.             }
  834.         }
  835.         return $output;
  836.     }
  837.     /**
  838.      *  Look up ocre reference
  839.      *  @Route("/ocre_lookup/{id}", name="ocre_lookup", methods={"GET"})
  840.      */
  841.     public function ocreLookupAction($id) {
  842.         $output $this->getOcreInfo($id);
  843.         if (is_array($output) && $output['error_code']) {
  844.             return new JsonResponse($output['error'], $output['error_code']);
  845.         } else {
  846.             return new JsonResponse($output);
  847.         }
  848.     }
  849.     
  850.     private function getOcreInfo($id) {
  851.         $url "http://numismatics.org/ocre/id/"$id .".jsonld";
  852.         $defaults = array(
  853.             CURLOPT_URL => $url,
  854.             CURLOPT_HEADER => 0,
  855.             CURLOPT_RETURNTRANSFER => TRUE,
  856.             CURLOPT_TIMEOUT => 4
  857.         );
  858.         
  859.         $ch curl_init();
  860.         curl_setopt_array($ch$defaults);
  861.         $result curl_exec($ch);
  862.         $httpCode curl_getinfo($chCURLINFO_HTTP_CODE);
  863.         curl_close($ch);
  864.         if($httpCode != "200")
  865.         {
  866.             return [
  867.                 'error' => 'Error querying '$url,
  868.                 'error_code' => $httpCode
  869.             ];
  870.         }
  871.         $output json_decode($result);
  872.         return $output;
  873.     }
  874.     /**
  875.      * checks permission of user's current request
  876.      *
  877.      * @param mixed $entity The entity being validated
  878.      *
  879.      * @param string $attribute - 'view' or 'edit' or 'delete'
  880.      *
  881.      * @param boolean $throwException - whether to throw an exception if false - defaults to true
  882.      *
  883.      * @return boolean
  884.      *
  885.      * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
  886.      */
  887.     private function checkAccess($entity$attribute$throwException true) {
  888.         // call security voter(s)
  889.         if (!$this->getUser()) {
  890.             if ($throwException) {
  891.                 throw new AccessDeniedException('Unauthorised access!');
  892.             }
  893.             return false;
  894.         }
  895.         return true;
  896.     }
  897.     private function userIsAdmin() {
  898.         if($this->getUser() && ($this->getUser()->hasRole('ROLE_ADMIN') || $this->getUser()->hasRole('ROLE_SUPER_ADMIN')))
  899.         {
  900.             return true;
  901.         }
  902.         return false;
  903.     }
  904.     private function getPermanentReferenceRootDir() {
  905.         return "/srv/hoards_references/";
  906.     }
  907.     
  908. }