<?php
namespace App\Ox\HoardBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
use Doctrine\ORM\Query\Expr\Select;
use Doctrine\ORM\Query\Expr\From;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
use App\Ox\HoardBundle\Entity\Hoard;
use App\Ox\HoardBundle\Entity\HObject;
use App\Ox\HoardBundle\Entity\Coin;
use App\Ox\HoardBundle\Entity\Container;
use App\Ox\HoardBundle\Entity\HoardCoinCount;
use App\Ox\HoardBundle\Entity\HoardImage;
use App\Ox\HoardBundle\Form\HoardType;
use App\Ox\HoardBundle\Form\HoardSearchType;
use App\Ox\HoardBundle\Form\SummaryCoinType;
use App\Ox\HoardBundle\Form\SearchType;
use SimpleThings\EntityAudit\AuditConfiguration;
use SimpleThings\EntityAudit\AuditManager;
/**
* Hoard controller.
*
* @Route("/hoard")
*/
class HoardController extends AbstractController
{
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
/**
* creates csv and appropriate page response for csv of supplied query
*
*/
private function outputCSV(Array $data, $prefix=null, $exportCoins=false, $refData=null) {
if($prefix == null) {
$prefix = "export";
}
$filename = $prefix."_".date("Y_m_d_His").".csv";
if($exportCoins) {
//build an array of column headings for the reference columns
if($refData) {
$refHeadings = [];
foreach($refData['own_column_references'] as $o_c_ref) {
if(isset($o_c_ref['abbreviation'])) {
$refHeadings[] = $o_c_ref['abbreviation'] . ' Reference';
} else {
$refHeadings[] = $o_c_ref['title'] . ' Reference';
}
}
for($i=1; $i <= $refData['num_other_references']; $i++) {
$refHeadings[] = 'Other Reference '.$i;
}
}
$response = $this->render('@OxHoardBundle/coin/csvExport.html.twig', array(
'data' => $data,
// 'numRefs' => 10,
'ref_headings' => $refHeadings,
'num_ref_columns' => count($refHeadings)
));
} else {
$response = $this->render('@OxHoardBundle/hoard/csvExport.html.twig', array(
'is_authenticated' => !!$this->getUser(),
'data' => $data
));
}
$response->headers->set('Content-Type', 'text/csv');
$response->setStatusCode(200);
$response->setCharset('UTF-8');
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Description', 'Hoards Export');
$response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->headers->set('Pragma', 'no-cache');
$response->headers->set('Expires', '0');
return $response;
}
/**
* Creates a new Hoard entity.
*
* @Route("/create", name="hoard_create", methods={"POST"})
* @Template("@OxHoardBundle/hoard/new.html.twig")
*/
public function createAction(Request $request)
{
//only logged in users can create
if(!$this->getUser()) {
throw new AccessDeniedException("Only logged in contributors may create a hoard entry");
}
$entity = new Hoard();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
//persist the hoardImages
$hoardImages = $entity->getHoardImages();
foreach ($hoardImages as $hoardImage)
if (!$hoardImage->getDeleted()) {
$em->persist($hoardImage);
}
//persist references
$hoardReferences = $entity->getHoardReferences();
foreach ($hoardReferences as $reference) {
if (!$reference->getDeleted()) {
$reference->setHoard($entity);
$em->persist($reference);
}
}
$entity->setCreated($this->getUser());
$entity->setModified($this->getUser());
$this->addRelatedCountries($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('hoard_show',
array(
'id' => $entity->getId(),
)
));
}
/**
* Creates a form to create a Hoard entity.
*
* @param Hoard $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Hoard $entity)
{
$formOptions = array(
'action' => $this->generateUrl('hoard_create'),
'method' => 'POST',
'em' => $this->getDoctrine()->getManager(),
);
if(!$this->userIsAdmin()) {
$formOptions['countries'] = $this->getUser()->getAccessibleCountries();
}
$form = $this->createForm(HoardType::class, $entity, $formOptions);
if($this->userIsAdmin())
{
$form->add('validatedByAdmin');
}
$form->add('submit', SubmitType::class, array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new Hoard entity.
*
* @Route("/new", name="hoard_new", methods={"GET"})
* @Template()
*/
public function newAction()
{
//only logged in users can create
if(!$this->getUser()) {
throw new AccessDeniedException("Only logged in contributors may create a hoard entry");
}
$hoard = new Hoard();
$form = $this->createCreateForm($hoard);
$coinAddForm = $this->createForm(SummaryCoinType::class, null, array());
$object_prototype = array(
'id' => '__id__',
'object' => '',
'description' => '',
);
$container_prototype = array(
'id' => '__id__',
'container' => '',
'comment' => ''
);
$em = $this->getDoctrine()->getManager();
$referenceTypes = $em->createQuery('SELECT rt FROM OxHoardBundle:ReferenceType rt ORDER BY rt.sortValue DESC, rt.referenceType ASC')->getResult();
return $this->render('@OxHoardBundle/hoard/edit.html.twig', array(
'object_proto' => $object_prototype,
'container_proto' => $container_prototype,
'hoard' => $hoard,
'images' => array(),
'coin_data' => array(),
'coin_add_form' => $coinAddForm->createView(),
'edit_form' => $form->createView(),
'reference_types' => $referenceTypes,
'create' => true,
'is_admin' => true,
'showRedirectField' => false,
));
}
/**
* Returns a Hoard entity as a csv file
*
* @Route("/{id}/csv", name="hoard_csv_download", requirements={
* "id": "\d+"
* }, methods={"GET"})
*/
public function csvExportAction($id) {
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
if(!$hoard) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
$this->checkAccess($hoard, 'view');
$qb = $em->createQueryBuilder();
$qb ->select( 'h',
'partial type.{id, hoardType}',
'coinCount',
'partial countries.{id, country}',
'partial province.{id, province}',
'partial ancientPlace.{id, ancientPlace}',
'partial location_detail.{id, findSpotLocationDetail}',
'partial reign1.{id, reign}',
'partial reign2.{id, reign}',
'partial disc_method.{id, discoveryMethod}',
'partial disc_landuse.{id, discoveryLandUse}',
'partial recovery_method.{id, archaeologyRecoveryMethod}',
'partial site_context.{id, archaeologySiteContext}',
'partial arch_site_context_details.{id, archaeologySiteContextDetail}',
'partial arch_period.{id, archaeologyPeriod}',
'partial arch_end_period.{id, archaeologyPeriod}',
'partial arch_context_natures.{id, title}',
'partial findspot_rating.{id, rating}',
'partial contextual_rating.{id, rating}',
'partial rating.{id, rating}',
'partial containers.{id, container}',
'partial objects.{id, object}',
'partial coinLevelData.{id, coinLevelData}',
'partial hoardReferences.{id, reference_str}',
'partial references.{id, abbreviation, authors, year, title}',
'partial refType.{id}',
)
->from('OxHoardBundle:Hoard', 'h')
->where('h.id = :hoardId')
->setParameter('hoardId', $hoard->getId())
->leftJoin('h.hoardType', 'type')
->leftJoin('h.coinCount', 'coinCount')
->leftJoin('h.countries', 'countries')
->leftJoin('h.province', 'province')
->leftJoin('h.ancientPlace', 'ancientPlace')
->leftJoin('h.findSpotLocationDetail', 'location_detail')
->leftJoin('h.closingReign1', 'reign1')
->leftJoin('h.closingReign2', 'reign2')
->leftJoin('h.discoveryMethod', 'disc_method')
->leftJoin('h.discoveryLandUse', 'disc_landuse')
->leftJoin('h.archaeologyRecoveryMethod', 'recovery_method')
->leftJoin('h.archaeologySiteContext', 'site_context')
->leftJoin('h.archaeologySiteContextDetails', 'arch_site_context_details')
->leftJoin('h.archaeologyPeriod', 'arch_period')
->leftJoin('h.archaeologyContextNatures', 'arch_context_natures')
->leftJoin('h.archaeologyEndPeriod', 'arch_end_period')
->leftJoin('h.findSpotRating', 'findspot_rating')
->leftJoin('h.contextualRating', 'contextual_rating')
->leftJoin('h.rating', 'rating')
->leftJoin('h.containers', 'containers')
->leftJoin('h.objects', 'objects')
->leftJoin('h.coinLevelData', 'coinLevelData')
->leftJoin('h.hoardReferences', 'hoardReferences')
->leftJoin('hoardReferences.reference', 'references')
->leftJoin('references.referenceType', 'refType')
;
$data = $qb->getQuery()->getArrayResult();
// echo '<pre>'; print_r($data); echo '</pre>';
$isAuthenticated = false;
if($this->getUser()) {
$isAuthenticated = true;
}
//loop over hoards and flag if they should be hidden
// var_dump($data);
foreach($data as &$hoard) {
if($isAuthenticated) {
$hoard['can_see_location'] = true;
} else {
$hoard['can_see_location'] = !$hoard['hideLocation'];
}
$hoardOnlineDatabases = array();
$hoard['hoardReferences'] = array_filter($hoard['hoardReferences'], function($reference) use (&$hoardOnlineDatabases) {
if ($reference && $reference['reference'] &&
$reference['reference']['referenceType'] &&
$reference['reference']['referenceType']['id'] &&
$reference['reference']['referenceType']['id'] != '11') { // reference's type is a "Permalink in other online database"
return true;
} else {
$hoardOnlineDatabases[] = $reference;
return false;
}
});
$hoard['hoardOnlineDatabases'] = $hoardOnlineDatabases;
}
return $this->outputCSV($data, 'hoard_'.$id);
}
/**
* Returns a Hoard entity as a csv file
*
* @Route("/{id}/csv/coins", name="hoard_csv_download_coins", requirements={
* "id": "\d+"
* }, methods={"GET"})
*/
public function csvExportActionCoins($id) {
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
if(!$hoard) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
$this->checkAccess($hoard, 'view');
$qb = $em->createQueryBuilder();
$qb->select(
'partial h.{id, findSpotName, findSpotLatitude, findSpotLongitude, terminalYear1, terminalYear2},
c,
partial countries.{id, country},
partial coinLevelData.{id, coinLevelData},
partial period.{id, period},
partial d.{id, denomination},
partial material.{id, material},
partial mints.{id, mint},
partial reigns.{id, reign},
partial persons.{id, person, title},
partial condition.{id, condition},
partial aspects.{id, aspect},
partial container.{id, container},
partial coinAdditionalFields.{id, comment},
partial additionalFields.{id, additionalField, description},
partial coinReferences.{id, reference_str, comment},
partial references.{id, abbreviation, authors, year, title, sortValue, hasOwnColumn},
partial ocre.{id, sortValue},
partial ocre_person.{id, person},
partial ocre_mint.{id, mint}'
)
->from('OxHoardBundle:Hoard', 'h')
->where('h.id = :hoardId')
->leftJoin('h.countries', 'countries')
->leftJoin('h.coinLevelData', 'coinLevelData')
->setParameter('hoardId', $hoard->getId())
->leftjoin('h.coins', 'c')
->leftjoin('c.period', 'period')
->leftjoin('c.denominations', 'd')
->leftjoin('d.material', 'material')
->leftjoin('c.mints', 'mints')
->leftjoin('c.reigns', 'reigns')
->leftjoin('c.persons', 'persons')
->leftjoin('c.condition', 'condition')
->leftjoin('c.aspects', 'aspects')
->leftjoin('c.container', 'container')
->leftJoin('c.coinAdditionalFields', 'coinAdditionalFields')
->leftJoin('coinAdditionalFields.additionalField', 'additionalFields')
->leftJoin('c.coinReferences', 'coinReferences')
->leftJoin('coinReferences.reference', 'references')
->leftJoin('reigns.ocreLookups', 'ocre')
->leftJoin('ocre.person', 'ocre_person')
->leftJoin('ocre.mint', 'ocre_mint')
;
$data = $qb->getQuery()->getArrayResult();
$refData = $this->processHoardDataForCSV($data);
//for some reason the results are wrapped in an array here, unlike when exporting from search results.
return $this->outputCSV(array($data[0]), 'hoard_'.$id.'_coins', true, $refData);
}
//process the hoard data
// This sorts the coins and normalises the references to consistent columns
private function processHoardDataForCSV(&$data) {
$seenOwnColumnReferences = [];
$seenOtherReferences = [];
//sort the references by sort value
foreach($data as &$hoard) {
foreach($hoard['coins'] as &$coin) {
//get the sort value
$reigns = $coin['reigns'];
if($reigns && count($reigns)) {
//just look at first reign
$reign = $reigns[0];
$lookups = $reign['ocreLookups'];
foreach($lookups as $lookup) {
$coinPersons = [];
foreach($coin['persons'] as $person) {
$coinPersons[] = $person['id'];
}
if(in_array($lookup['person']['id'], $coinPersons)) {
//check mint if necessary
if(isset($lookup['mint'])) {
//see if it matches
$coinMints = [];
foreach($coin['mints'] as $mint) {
$coinMints[] = $mint['id'];
}
if(in_array($lookup['mint']['id'], $coinMints)) {
//this is a match
$coin['sortValue'] = $lookup['sortValue'];
// echo 'found a match with mint, sort value = '.$coin['sortValue'].'<br/>';
}
} else {
//this is a match
$coin['sortValue'] = $lookup['sortValue'];
// echo 'found a match without mint, sort value = '.$coin['sortValue'].'<br/>';
}
}
}
}
// echo '<pre>'; print_r($coin); echo '</pre>';
//note which references are seen
// keep separate arrays of references which should have their own column
foreach($coin['coinReferences'] as $coinRef) {
$ref = $coinRef['reference'];
if($ref) {
if($coinRef['reference']['hasOwnColumn']) {
if(!in_array($ref, $seenOwnColumnReferences)) {
$seenOwnColumnReferences[] = $ref;
}
} else {
if(!in_array($ref, $seenOtherReferences)) {
$seenOtherReferences[] = $ref;
}
}
}
}
usort($coin['coinReferences'], array($this,"compareRefs"));
}
//now sort coins by their sort value
usort($seenOwnColumnReferences, array($this,"compareSeenRefs"));
usort($hoard['coins'], array($this,"compareCoins"));
// var_dump($hoard);
}
//at this point we have a list of coin references seen in this dataset, and the coin references are sorted
//rewrite the coin references with the references in the relevant columns
$maxOtherReferences = 0;
foreach($data as &$hoard) {
foreach($hoard['coins'] as &$coin) {
//keyed array of those references which should have their own column
$newOwnColumnCoinReferences = [];
//plain array of all other references
$newOtherCoinReferences = [];
$coinReferences = $coin['coinReferences'];
foreach($coinReferences as $coinRef) {
if($coinRef['reference']['hasOwnColumn']) {
$key = $coinRef['reference']['id'];
$newOwnColumnCoinReferences[$key] = $coinRef;
} else {
$newOtherCoinReferences[] = $coinRef;
}
}
//now build the full array of references
$newCoinReferences = [];
// var_dump($seenOwnColumnReferences);
foreach($seenOwnColumnReferences as $ownColumnRef) {
$val = '';
// var_dump($seenOwnColumnReferences);
if(isset($newOwnColumnCoinReferences[$ownColumnRef['id']])) {
$val = $newOwnColumnCoinReferences[$ownColumnRef['id']];
} else {
$val = array();
}
$newCoinReferences[] = $val;
}
//keep track of how many columns we need
if(count($newOtherCoinReferences) > $maxOtherReferences) {
$maxOtherReferences = count($newOtherCoinReferences);
}
//add the non-own-column references
$newCoinReferences = array_merge($newCoinReferences, $newOtherCoinReferences);
$coin['coinReferences'] = $newCoinReferences;
}
}
//return some data about the references seen
return array(
'own_column_references' => $seenOwnColumnReferences,
'num_other_references' => $maxOtherReferences
);
}
function compareCoins($a, $b) {
//compare period
if (isset($a['period'])) { $periodA = $a['period']['id']; } else { $periodA = 0; }
if (isset($b['period'])) { $periodB = $b['period']['id']; } else { $periodB = 0; }
if($periodA < $periodB) { return -1; }
else if($periodB < $periodA ) { return 1; }
else {
if(isset($a['sortValue'])) { $sortA = $a['sortValue']; } else { $sortA = 0; }
if(isset($b['sortValue'])) { $sortB = $b['sortValue']; } else { $sortB = 0; }
//periods are equal, compare by ocre table
if($sortA > $sortB) { return 1; }
else if($sortB > $sortA) { return -1; }
else {
//same ocre prefix
//todo compare ric reference value
$refValueA = $this->getSortableRef($a);
if($refValueA) {
$refValueB = $this->getSortableRef($b);
if($refValueB) {
//compare numerical part
$numA = intval($refValueA['num']);
$numB = intval($refValueB['num']);
if($numA > $numB) { return 1; }
else if($numB > $numA) {return -1; }
else {
//compare alphabetic part
$lowerA = strtolower($refValueA['char']);
$lowerB = strtolower($refValueB['char']);
if($lowerA < $lowerB) { return -1; }
else if($lowerB < $lowerA) { return 1; }
else return 0;
}
}
}
return 0;
}
}
}
//given an array of coinData, get the most relevant reference as an array of numerical part and alphabetic part
function getSortableRef($coinArray) {
// var_dump($coinArray);
foreach($coinArray['coinReferences'] as $coinRef) {
if(isset($coinRef['reference'])) {
$refs = ['RIC', 'RIC (2nd ed.)', 'RRC', 'RPC'];
if(in_array($coinRef['reference']['abbreviation'], $refs)) {
//this is a reference we care about sorting on
//extract the numerical and alphabetic components
$matches = null;
if (preg_match('/(\d+)\/(\d+)(\w*)/', $coinRef['reference_str'], $matches)) {
//RRC reference format e.g. 123/1b
//derive a number that can be used to compare
$num = $matches[1] * 1000 + $matches[2];
$refData = array(
'num' => $num,
'char' => $matches[3]
);
return $refData;
} else if (preg_match('/(\d+)(\w*)/', $coinRef['reference_str'], $matches)) {
//RIC reference format e.g. 123a (or somethings 123a/b or )
$refData = array(
'num' => $matches[1],
'char' => $matches[2]
);
return $refData;
}
}
}
}
return null;
}
//order coinreference array data by sortvalue of the reference (decreasing)
function compareSeenRefs($a, $b) {
if($a['sortValue'] > $b['sortValue']) {
return -1;
} else if ($a['sortValue'] == $b['sortValue']) {
return 0;
} else {
return 1;
}
}
//order coinreference array data by sortvalue of the reference (decreasing)
function compareRefs($a, $b) {
if($a['reference']['sortValue'] > $b['reference']['sortValue']) {
return -1;
} else if ($a['reference']['sortValue'] == $b['reference']['sortValue']) {
return 0;
} else {
return 1;
}
}
/**
* Finds and displays a Hoard entity.
*
* @Route("/{id}", name="hoard_show", requirements={
* "id": "\d+"
* }, methods={"GET"})
* @Template()
*/
public function showAction($id)
{
$isAdmin = $this->userIsAdmin();
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
// if the hoard is not found check if it soft-deleted
if (!$hoard) {
$em->getFilters()->disable('softdeleteable');
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$em->getFilters()->enable('softdeleteable');
// if it is not soft-deleted return "not found"
if (!$hoard) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
} else {
// else check if it is really soft-deleted and redirect to the redirectId
$redirect_id = $hoard->getRedirectToHoard();
if ($hoard->getDeletedAt() && $redirect_id) {
return $this->redirect($this->generateUrl('hoard_show', array('id' => $redirect_id)));
} else {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
}
}
// validate permission
$this->checkAccess ($hoard, 'view');
$deleteForm = $this->createDeleteForm($id);
$images =$this->getImages($hoard);
$discoveryMonth1Text = $this->monthTextForMonth($hoard->getDiscoverymonth1());
$discoveryMonth2Text = $this->monthTextForMonth($hoard->getDiscoverymonth2());
foreach($images as &$image) {
//add metadata about the image
$hoardimage = $em->getRepository('OxHoardBundle:HoardImage')->find($image['hoardImages_id']);
$image['uri1'] = $hoardimage->getUri1();
$image['uri2'] = $hoardimage->getUri2();
$image['comment'] = $hoardimage->getComment();
}
$isAuthenticated = false;
if($this->getUser()) { $isAuthenticated = true; }
if (!$isAuthenticated && !$hoard->getCoinDataValidatedByUser()) {
$show_coins = false;
$show_coins_summary = false;
} else {
$show_coins = $this->security->isGranted('view_coins', $hoard);
$show_coins_summary = $this->security->isGranted('view_coins_summary', $hoard);
}
$hoardReferences = $hoard->getHoardReferences();
$iterator = $hoardReferences->getIterator();
$iterator->uasort(function ($a, $b) {
if ($a->getReference() && $b->getReference()) {
if ($a->getReference()->getYear() != $b->getReference()->getYear()) {
// sort by reference year first
return $a->getReference()->getYear() - $b->getReference()->getYear();
} else {
// alphabetically by authors if years are the same
return strcasecmp($a->getReference()->getAuthors(), $b->getReference()->getAuthors());
}
}
});
$hoardReferences->clear();
foreach($iterator as $item) {
$hoardReferences->add($item);
}
// Create separate arrays for OnlineDB references and other references.
$hoardReferenceArray = [];
$onlineDatabaseReferenceArray = [];
// Loop through HoardReferences.
foreach ($hoardReferences->getValues() as $reference) {
if ($referenceType = $reference->getReference() && $reference->getReference()->getReferenceType()) {
// Check ID, if matches Online Database, add to relevant array.
$referenceType = $reference->getReference()->getReferenceType()->getId();
if ($referenceType === 11) {
$onlineDatabaseReferenceArray[] = $reference;
}
else {
$hoardReferenceArray[] = $reference;
}
}
}
// Generate a permalink to display on the hoard page.
$permalink = "https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$reigns = $em->getRepository('OxHoardBundle:Reign')->findAll();
$persons = $em->getRepository('OxHoardBundle:Person')->findAll();
return array(
'images' => $images,
'hoard' => $hoard,
'hoardReferences' => $hoardReferenceArray,
'onlineDatabaseReferences' => $onlineDatabaseReferenceArray,
'is_admin' => $isAdmin,
'is_authenticated' => $isAuthenticated,
'can_see_location' => $isAuthenticated || !$hoard->getHideLocation(),
'is_authorised_to_edit' => $this->checkAccess($hoard, 'edit', false),
'show_coins' => $show_coins,
'show_coins_summary' => $show_coins_summary,
'discoverymonth1_text' => $discoveryMonth1Text,
'discoverymonth2_text' => $discoveryMonth2Text,
'permalink' => $permalink,
'reigns' => $reigns,
'persons' => $persons
);
}
private function monthTextForMonth($num) {
switch($num) {
case 1:
return 'Jan';
case 2:
return 'Feb';
case 3:
return 'Mar';
case 4:
return 'Apr';
case 5:
return 'May';
case 6:
return 'Jun';
case 7:
return 'Jul';
case 8:
return 'Aug';
case 9:
return 'Sep';
case 10:
return 'Oct';
case 11:
return 'Nov';
case 12:
return 'Dec';
default:
return '';
}
}
/**
* @Route("/coinData/{id}", name="ajax_hoard_coin_data", requirements={
* "id": "\d+"
* }, methods={"GET"})
*/
public function ajaxHoardCoins($id)
{
$em = $this->getDoctrine()->getManager();
$hoard= $em->getRepository('OxHoardBundle:Hoard')->find($id);
if(!$hoard) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
//check that the user can at least see the coins summary
$isAuthenticated = false;
if($this->getUser()) { $isAuthenticated = true; }
if (!$isAuthenticated && !$hoard->getCoinDataValidatedByUser()) {
$show_coins = false;
} else {
$show_coins = $this->security->isGranted('view_coins_summary', $hoard);;
}
if ($show_coins) {
$coinData = $this->getCoinData($hoard);
return new JsonResponse($coinData);
} else {
throw new AccessDeniedException('Unauthorised access!');
}
}
private function getCoinData($hoard) {
$em = $this->getDoctrine()->getManager();
// Generate the coin summaries
$queryBuilder = $em->createQueryBuilder();
$queryBuilder->select('c, aspects, period, reigns, mints, persons, denominations, materials, partial coin_references.{id, reference_str}, partial ref.{id, abbreviation}')
->from('OxHoardBundle:Coin', 'c')
->leftJoin('c.reigns', 'reigns')
->leftJoin('c.persons', 'persons')
->leftJoin('c.denominations', 'denominations')
->leftJoin('denominations.material', 'materials')
->leftJoin('c.mints', 'mints')
->leftJoin('c.period', 'period')
->leftJoin('c.aspects', 'aspects')
->leftJoin('c.coinReferences', 'coin_references')
->leftJoin('coin_references.reference', 'ref')
;
$queryBuilder->where('c.hoard = :hoard')
->setParameter('hoard', $hoard);
$query = $queryBuilder->getQuery();
$queryResult = $query->getArrayResult();
return $queryResult;
}
/**
* Displays a form to edit an existing Hoard entity.
*
* @Route("/{id}/edit", name="hoard_edit", methods={"GET"})
* @Template()
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$em->getFilters()->enable('softdeleteable');
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$showRedirectField = false;
if (!$hoard) {
$em->getFilters()->disable('softdeleteable');
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$em->getFilters()->enable('softdeleteable');
// if it is not soft-deleted return "not found"
if (!$hoard) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
} else {
// else check if it is really soft-deleted to enable the redirect id field
if ($hoard->getDeletedAt() && $this->userIsAdmin()) {
$showRedirectField = true;
} else {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
}
}
// validate permission
$this->checkAccess($hoard, 'edit');
$editForm = $this->createEditForm($hoard);
$deleteForm = $this->createDeleteForm($id);
$objects = $hoard->getObjects();
$object_prototype = array(
'id' => '__id__',
'object' => '',
'description' => '',
);
$container_prototype = array(
'id' => '__id__',
'container' => '',
'comment' => ''
);
// echo '<pre>'; print_r($object_prototype); exit;
//get the list of image
$images = $this->getImages($hoard);
$coinAddForm = $this->createForm(SummaryCoinType::class, null, array());
//reference types to pass to the view
$referenceTypes = $em->createQuery('SELECT rt FROM OxHoardBundle:ReferenceType rt ORDER BY rt.sortValue DESC, rt.referenceType ASC')->getResult();
$massEditCoinsData = $this->massEditCoinsData();
$disaggregateForm = $this->createDisaggregateForm($id);
return array(
'object_proto' => $object_prototype,
'container_proto' => $container_prototype,
'hoard' => $hoard,
'images' => $images,
'coin_add_form' => $coinAddForm->createView(),
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
'reference_types' => $referenceTypes,
'create' => false,
'massEditCoinsData' => $massEditCoinsData,
'disaggregate_form' => $disaggregateForm->createView(),
'is_admin' => $this->userIsAdmin(),
'showRedirectField' => $showRedirectField,
);
}
/**
* Shows the revisions of an existing Hoard entity.
*
* @Route("/{id}/revisions", name="hoard_revisions", methods={"GET"})
* @Template("@OxHoardBundle/hoard/revisions.html.twig")
*/
public function revisionsAction(Request $request, $id) {
// check User
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$this->checkAccess($hoard, 'edit');
$auditConfig = new AuditConfiguration();
$auditConfig->setAuditedEntityClasses([Hoard::class]);
$auditManager = new AuditManager($auditConfig);
$auditReader = $auditManager->createAuditReader($em);
$revisions = $auditReader->findRevisions(Hoard::class, $id);
$revs = [];
foreach($revisions as $key => $revision) {
$revs[$key]['username'] = $revision->getUsername();
$revs[$key]['rev'] = $revision->getRev();
$revs[$key]['date'] = $revision->getTimestamp()->format("H:i:s d-m-Y");
}
$coinsRevs = [];
$coins = $hoard->getCoins();
foreach($coins as $coin) {
$coinId = $coin->getId();
$auditConfig = new AuditConfiguration();
$auditConfig->setAuditedEntityClasses([Coin::class]);
$auditManager = new AuditManager($auditConfig);
$auditReader = $auditManager->createAuditReader($em);
$coinRevisions = $auditReader->findRevisions(Coin::class, $coinId);
foreach($coinRevisions as $key => $revision) {
$coinsRevs[$coinId][$key]['username'] = $revision->getUsername();
$coinsRevs[$coinId][$key]['rev'] = $revision->getRev();
$coinsRevs[$coinId][$key]['date'] = $revision->getTimestamp()->format("H:i:s d-m-Y");
}
}
return array(
'revs' => $revs,
'coinsRevs' => $coinsRevs,
'hoard' => $hoard,
);
}
private function massEditCoinsData() {
$em = $this->getDoctrine()->getManager();
//get all available options for the various dropdowns
$data = array();
$data['persons'] = $em->getRepository('OxHoardBundle:Person')->findAll();
$data['period'] = $em->getRepository('OxHoardBundle:Period')->findAll();
$data['reigns'] = $em->getRepository('OxHoardBundle:Reign')->findAll();
$data['mints'] = $em->getRepository('OxHoardBundle:Mint')->findAll();
$data['denominations'] = $em->getRepository('OxHoardBundle:Denomination')->findAll();
$data['condition'] = $em->getRepository('OxHoardBundle:Condition')->findAll();
$data['aspects'] = $em->getRepository('OxHoardBundle:Aspect')->findAll();
$data['references'] = $em->getRepository('OxHoardBundle:Reference')->findAll();
return $data;
}
/****
* Get a list of image file names/ids for the given hoard entity
*/
private function getImages(Hoard $entity) {
$hoardImages = $entity->getHoardImages();
$images = array();
foreach($hoardImages as $hoardImage) {
$imageSrc = null;
$image = $hoardImage->getImage();
if(!empty($image)) {
$imageSrc = 'media/'.$image->getFilename();
}
array_push($images, array(
'src' => $imageSrc,
'hoardImages_id' => $hoardImage->getId()
));
}
return $images;
}
/**
* Creates a form to edit a Hoard entity.
*
* @param Hoard $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Hoard $entity)
{
$formOptions = array(
'action' => $this->generateUrl('hoard_update', array('id' => $entity->getId())),
'method' => 'PUT',
'em' => $this->getDoctrine()->getManager(),
);
//pass in the list of allowed countries
if(!$this->userIsAdmin()) {
$formOptions['countries'] = $this->getUser()->getAccessibleCountries();
}
$form = $this->createForm(HoardType::class, $entity, $formOptions);
if($this->userIsAdmin())
{
$form->add('validatedByAdmin');
}
$form->add('submit', SubmitType::class, array('label' => 'Update'));
return $form;
}
/**
* Edits an existing Hoard entity.
*
* @Route("/{id}", name="hoard_update", methods={"PUT"})
* @Template("@OxHoardBundle/hoard/edit.html.twig")
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$em->getFilters()->enable('softdeleteable');
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
if (!$hoard) {
$em->getFilters()->disable('softdeleteable');
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$em->getFilters()->enable('softdeleteable');
// if it is not soft-deleted or user is not admin return "not found"
if (!$hoard || !$this->userIsAdmin()) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
}
// validate permission
$this->checkAccess($hoard, 'edit');
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($hoard);
$editForm->handleRequest($request);
$now = new \DateTime('now');
if ($editForm->isValid()) {
//images
$hoardImages = $hoard->getHoardImages();
foreach($hoardImages as $hoardImage)
{
$em->persist($hoardImage);
if($hoardImage->getDeleted())
{
$em->remove($hoardImage);
}
}
//persist or delete references
$hoardReferences = $hoard->getHoardReferences();
foreach($hoardReferences as $reference)
{
echo 'reference found <br>';
if($reference->getDeleted())
{
//do soft delete - also persist deleted flag
$em->persist($reference);
//clear this reference from the hoard
$reference->setHoard(null);
//need to flush before removing
$em->flush();
$em->remove($reference);
}
else
{
$em->persist($reference);
$reference->setHoard($hoard);
}
}
//mark as unvalidated since it has changed
if(!$this->userIsAdmin())
{
$hoard->markUnvalidatedByAdmin();
}
$hoard->setModified($this->getUser());
$this->addRelatedCountries($hoard);
$em->flush();
$request->getSession()
->getFlashBag()
->add('success', 'Hoard has been updated');
return $this->redirect($this->generateUrl('hoard_show', array('id' => $id)));
}
//get the list of image
$images = $this->getImages($hoard);
$object_prototype = array(
'id' => '__id__',
'object' => '',
'description' => '',
);
$container_prototype = array(
'id' => '__id__',
'container' => '',
'comment' => ''
);
$referenceTypes = $em->createQuery('SELECT rt FROM OxHoardBundle:ReferenceType rt ORDER BY rt.sortValue DESC, rt.referenceType ASC')->getResult();
$request->getSession()
->getFlashBag()
->add('error', 'Error updating hoard!');
return array(
'object_proto' => $object_prototype,
'container_proto' => $container_prototype,
'hoard' => $hoard,
'images' => $images,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
'reference_types' => $referenceTypes,
'create' => false,
);
}
/**
* Deletes a Hoard entity.
*
* @Route("/{id}", name="hoard_delete", methods={"DELETE"})
*/
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('OxHoardBundle:Hoard')->find($id);
if (!$this->getUser() || !($this->getUser()->hasRole('ROLE_ADMIN') || $this->getUser()->hasRole('ROLE_SUPER_ADMIN'))) {
$request->getSession()->getFlashBag()
->add('error', 'Unable to delete Hoard. Only admins can delete hoards.');
return $this->redirect($this->generateUrl('hoard_edit', array('id' => $entity->getId())));
}
if (!$entity) {
throw $this->createNotFoundException('Unable to find Hoard entity.');
}
// validate permission
$this->checkAccess($entity, 'delete');
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('hoard'));
}
/**
* Creates a form to delete a Hoard entity by id.
*
* @param mixed $id The entity id
*
* @return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('hoard_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', ButtonType::class, array(
'label' => 'Delete this hoard',
'attr' => array(
'class' => 'delete-button btn btn-danger'
)
))
->getForm()
;
}
/**
* Add a new object to the hoard
*
* @Route("/{id}/ajax_add_object", name="hoard_ajax_add_object", methods={"POST"})
*/
public function ajaxAddObject(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$this->checkAccess($hoard, 'edit');
$object = new HObject();
$object->setHoard($hoard);
$object->setCreationDate( new \DateTime("now"));
$em->persist($object);
//mark as unvalidated since it has changed
if(!$this->userIsAdmin())
{
$hoard->markUnvalidatedByAdmin();
}
$em->flush();
return new JsonResponse(
array(
'id'=>$object->getId(),
'title'=>$object->__toString(),
'description'=>$object->GetDescription(),
'deleteURL'=>$this->generateUrl('hoard_ajax_delete_object',
array(
'id' => $hoard->getId(),
'object_id' => $object->getId(),
)
)
)
);
}
/**
* Add a new coin to the hoard
*
* @Route("/{id}/ajax_add_coin", name="hoard_ajax_add_coin", methods={"POST"})
*/
public function ajaxAddCoin(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$this->checkAccess($hoard, 'edit');
$coin = new Coin();
$coin->setHoard($hoard);
//get period
$periodID = $request->request->get('period');
$period = $em->getRepository('OxHoardBundle:Period')->find($periodID);
$coin->setPeriod($period);
$personsData = $request->request->get('persons');
if($personsData) {
foreach ($personsData as $personID) {
$person = $em->getRepository('OxHoardBundle:Person')->find($personID);
$coin->addPerson($person);
}
}
$reignsData = $request->request->get('reigns');
if($reignsData) {
foreach ($reignsData as $reignID) {
$reign = $em->getRepository('OxHoardBundle:Reign')->find($reignID);
$coin->addReign($reign);
}
}
$denominationsData = $request->request->get('denominations');
if($denominationsData) {
foreach ($denominationsData as $denominationID) {
$denomination = $em->getRepository('OxHoardBundle:Denomination')->find($denominationID);
$coin->addDenomination($denomination);
}
}
$mintsData = $request->request->get('mints');
if($mintsData) {
foreach($mintsData as $mintID) {
$mint = $em->getRepository('OxHoardBundle:Mint')->find($mintID);
$coin->addMint($mint);
}
}
$coin->setQuantity($request->request->get('quantity'));
$coin->setCreated($this->getUser());
$coin->setModified($this->getUser());
$em->persist($coin);
$em->flush();
//prepare the response to the client, which must contain json data in the format required by the
// backbone collection (various parameters for both display and sorting)
$coinPeriod = '';
if($coin->getPeriod()) {
$coinPeriod = array(
'period' => $coin->getPeriod()->__toString(),
'id' => $coin->getPeriod()->getId()
);
}
$coinPersons = array();
foreach($coin->getPersons() as $person) {
$coinPersons[] = array ( 'person' => $person->__toString() );
}
$coinReigns = array();
foreach($coin->getReigns() as $reign) {
$coinReigns[] = array(
'reign' => $reign->__toString(),
'startDate' => $reign->getStartDate(),
'endDate' => $reign->getEndDate()
);
}
$coinDenominations = array();
foreach($coin->getDenominations() as $denomination) {
$coinDenominations[] = array(
'denomination' => $denomination->__toString()
);
}
$coinMints = array();
foreach($coin->getMints() as $mint) {
$coinMints[] = array(
'mint' => $mint->__toString(),
'longitude' => $mint->getLongitude()
);
}
return new JsonResponse(
array(
'id'=>$coin->getId(),
'period'=>$coinPeriod,
'persons'=>$coinPersons,
'reigns'=>$coinReigns,
'denominations'=>$coinDenominations,
'mints'=>$coinMints,
'quantity'=>$coin->getQuantity()
)
);
}
/**
* checks permission of user's current request
*
* @param mixed $entity The entity being validated
*
* @param string $attribute - 'view' or 'edit' or 'delete'
*
* @param boolean $throwException - whether to throw an exception if false - defaults to true
*
* @return boolean
*
* @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
*/
private function checkAccess($entity, $attribute, $throwException = true) {
// call security voter(s)
if (false === $this->security->isGranted($attribute, $entity)) {
if ($throwException) {
throw new AccessDeniedException('Unauthorised access!');
}
return false;
}
return true;
}
private function userIsAdmin() {
if($this->getUser() && ($this->getUser()->hasRole('ROLE_ADMIN') || $this->getUser()->hasRole('ROLE_SUPER_ADMIN')))
{
return true;
}
return false;
}
private function userIsImporter() {
if($this->getUser() && ($this->getUser()->hasRole('ROLE_IMPORTER')))
{
return true;
}
return $this->userIsAdmin();
}
/**
* Delete an object belonging to this hoard
*
* @Route("/{id}/ajax_delete_object/{object_id}", name="hoard_ajax_delete_object", methods={"POST"})
*/
public function ajaxDeleteObject(Request $request, $id, $object_id)
{
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
//TODO - check user has permissions for this hoard
$object = $em->getRepository('OxHoardBundle:HObject')->find($object_id);
$em->remove($object);
$em->flush();
return new JsonResponse(
array(
'deleted_object_id'=>$object->getId()
)
);
}
/**
* Add a new container to the hoard
*
* @Route("/{id}/ajax_add_container", name="hoard_ajax_add_container", methods={"POST"})
*/
public function ajaxAddContainer(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$container = new Container();
$container->setHoard($hoard);
$container->setCreationDate( new \DateTime("now"));
$em->persist($container);
$em->flush();
return new JsonResponse(
array(
'id'=>$container->getId(),
'title'=>$container->__toString(),
'description'=>$container->GetComment(),
'deleteURL'=>$this->generateUrl('hoard_ajax_delete_container',
array(
'id' => $hoard->getId(),
'container_id' => $container->getId(),
)
)
)
);
}
/**
* Delete a container belonging to this hoard
*
* @Route("/{id}/ajax_delete_container/{container_id}", name="hoard_ajax_delete_container", methods={"POST"})
*/
public function ajaxDeleteContainer(Request $request, $id, $container_id)
{
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
//TODO - check user has permissions for this hoard
$container = $em->getRepository('OxHoardBundle:Container')->find($container_id);
$em->remove($container);
$em->flush();
return new JsonResponse(
array(
'deleted_object_id'=>$container->getId()
)
);
}
/**
* Generate values for Terminal Year based on Coin data in the hoard
* @Route("/generate/terminals/{id}", name="generate_terminals", methods={"GET"})
*/
public function generateTerminals(Request $request)
{
$em = $this->getDoctrine()->getManager();
$hoardID = $request->get('id');
$query = $em -> createQuery("SELECT MAX(c.startingDate) as maxStart, MAX(c.endingDate) as maxEnd FROM OxHoardBundle:Coin
c WHERE c.hoard = :hoardID")
->setParameter('hoardID', $hoardID.'%');
$results = $query->getArrayResult();
return new JsonResponse($results);
}
public function addRelatedCountries($hoard) {
$countriesUK = ['England', 'Scotland' ,'Wales', 'Northern Ireland'];
$countries = $hoard->getCountries();
$addUK = false;
$ukListed = false;
foreach($countries as $country) {
if (in_array($country->getCountry(), $countriesUK))
{
$addUK = true;
}
if ($country->getCountry() == "United Kingdom")
{
$ukListed = true;
}
}
if ($addUK && !$ukListed) {
$em = $this->getDoctrine()->getManager();
$country = $em->getRepository('OxHoardBundle:Country')->findByCountry("United Kingdom");
$hoard->addCountry($country[0]);
}
}
/**
* Disaggregate a Hoard Coins entities.
*
* @Route("/{id}/disaggregate", name="hoard_disaggregate", methods={"POST"})
*/
public function disaggregateAction(Request $request, $id)
{
$form = $this->createDisaggregateForm($id, null);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$hoard = $em->getRepository('OxHoardBundle:Hoard')->find($id);
$coins = $hoard->getCoins();
$this->checkAccess($hoard, 'edit');
foreach ($coins as $entity) {
if (!$entity) {
throw $this->createNotFoundException('Unable to find Coin entity.');
}
$quantity = $entity->getQuantity();
if ($quantity > 1) {
$entity->setQuantity(1);
for ($i = 1; $i < $quantity; $i++) {
$clone = clone $entity;
//flag this as modified (even though it's technically being created, it's probably useful to track original creator in 'created')
$clone->setModified($this->getUser());
$em->persist($clone);
// clone all CoinAdditionalFields for the coin and set CoinAdditionalFields' oin to cloned coin
$additionalFieldsId = $entity->getCoinAdditionalFields();
foreach ($additionalFieldsId as $additionalFieldId) {
$additionalField = $em->getRepository('OxHoardBundle:CoinAdditionalField')->find($additionalFieldId);
$cloneAdditionalField = clone $additionalField;
$cloneAdditionalField->setCoin($clone);
$em->persist($cloneAdditionalField);
}
// clone all CoinReferences for the coin and set CoinReferences' coin to cloned coin
$referencesId = $entity->getCoinReferences();
foreach ($referencesId as $referenceId) {
$reference = $em->getRepository('OxHoardBundle:CoinReference')->find($referenceId);
$cloneReference = clone $reference;
$cloneReference->setCoin($clone);
$em->persist($cloneReference);
}
}
$em->flush();
}
}
return $this->redirect($this->generateUrl('hoard_edit', array('id' => $id)).'#coins');
}
return $this->redirect($this->generateUrl('hoard'));
}
/**
* Creates a form to disaggregate the Coins of a Hoard by id.
*
* @param mixed $id The entity id
*
* @return \Symfony\Component\Form\Form The form
*/
private function createDisaggregateForm($id)
{
$action = $this->generateUrl('hoard_disaggregate', array('id' => $id));
return $this->createFormBuilder()
->setAction($action)
->setMethod('POST')
->add('submit', SubmitType::class, array(
'label' => 'Disaggregate coins',
'attr' => array(
'class' => 'disaggregate-button'
)
))
->getForm()
;
}
}