Skip to content

Instantly share code, notes, and snippets.

@randm-ch
Created February 26, 2015 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randm-ch/66e7bcfada8d85608fcc to your computer and use it in GitHub Desktop.
Save randm-ch/66e7bcfada8d85608fcc to your computer and use it in GitHub Desktop.
<?php
namespace MyCompany\MyApplication\Controller;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Mvc\Controller\ActionController;
use MyCompany\MyApplication\Domain\Model\Report;
use MyCompany\MyApplication\Domain\Model\DqlStatement;
use MyCompany\MyApplication\Exception;
use MyCompany\MyApplication\Utility\TagsinputTag;
class ReportController extends ActionController {
/**
* @var \MyCompany\MyApplication\Domain\Repository\ReportRepository
* @Flow\Inject
*/
protected $reportRepository;
/**
* @var \MyCompany\MyApplication\Utility\DataClassReflection
* @Flow\Inject
*/
protected $dataClassReflection;
/**
* @var \TYPO3\Flow\Reflection\ReflectionService
* @Flow\Inject
*/
protected $reflectionService;
/**
* @var \Doctrine\Common\Persistence\ObjectManager
* @Flow\Inject
*/
protected $entityManager;
/**
* @var array
*/
protected $supportedMediaTypes = array('text/html', 'application/json');
/**
* @var array
*/
protected $viewFormatToObjectNameMap = array(
'html' => 'TYPO3\Fluid\View\TemplateView',
'json' => 'TYPO3\Flow\Mvc\View\JsonView'
);
/**
* @return void
*/
public function indexAction() {
$this->view->assign('reports', $this->reportRepository->findAll());
}
/**
* @param \MyCompany\MyApplication\Domain\Model\Report $report
* @return void
*/
public function showAction(Report $report) {
try {
$this->view->assign('report', $report);
}
catch(\Exception $e) {
$this->addFlashMessage('Die DQL-Syntax scheint nicht korrekt zu sein. Bitte überprüfen Sie die Report-Vorgaben. Query: '.$report->getDqlStatement()->getDql().'<br><strong>Fehler!</strong> '.$e->getMessage(), '', \TYPO3\Flow\Error\Message::SEVERITY_ERROR);
$this->redirect('index');
}
}
/**
* @return void
*/
public function newAction() {
}
/**
* @param \MyCompany\MyApplication\Domain\Model\Report $report
* @param array $statement
* @return void
*/
public function createAction(Report $report, array $statement) {
$propertyMapper = new \TYPO3\Flow\Property\PropertyMapper();
/** @var \MyCompany\MyApplication\Domain\Model\DqlStatement $statement */
$statement = $propertyMapper->convert($statement, 'MyCompany\\MyApplication\\Domain\\Model\\DqlStatement');
$statement->generate($this->getAllTags($statement->getFromStatement(), $statement->getJoinStatement()));
$report->setDqlStatement($statement);
$this->reportRepository->add($report);
$this->addFlashMessage('Neuen Report generiert.');
$this->redirect('index');
}
/**
* @param \MyCompany\MyApplication\Domain\Model\Report $report
* @return void
*/
public function editAction(Report $report) {
$statement = $report->getDqlStatement();
$this->view->assign('fromTags', TagsinputTag::fetchMultipleTags($statement->getFromStatement()));
$this->view->assign('joinTags', TagsinputTag::fetchMultipleTags($statement->getJoinStatement()));
$this->view->assign('selectTags', TagsinputTag::fetchMultipleTags($statement->getSelectStatement()));
$this->view->assign('whereTags', TagsinputTag::fetchMultipleTags($statement->getWhereStatement()));
$this->view->assign('orderTags', TagsinputTag::fetchMultipleTags($statement->getOrderStatement(), TRUE));
$this->view->assign('report', $report);
}
/**
* @param \MyCompany\MyApplication\Domain\Model\Report $report
* @param array $statement
* @return void
*/
public function updateAction(Report $report, array $statement) {
$propertyMapper = new \TYPO3\Flow\Property\PropertyMapper();
/** @var \MyCompany\MyApplication\Domain\Model\DqlStatement $statement */
$statement = $propertyMapper->convert($statement, 'MyCompany\\MyApplication\\Domain\\Model\\DqlStatement');
$statement->generate($this->getAllTags($statement->getFromStatement(), $statement->getJoinStatement()));
$report->setDqlStatement($statement);
$this->reportRepository->update($report);
$this->addFlashMessage('Report bearbeitet.');
$this->redirect('index');
}
/**
* @param \MyCompany\MyApplication\Domain\Model\Report $report
* @return void
*/
public function deleteAction(Report $report) {
$this->reportRepository->remove($report);
$this->addFlashMessage('Report gelöscht.');
$this->redirect('index');
}
/**
* @param string $query The current search string provided by the user
* @return void
*/
public function fromQueryAction($query = NULL) {
$classNames = $this->reflectionService->getAllSubClassNamesForClass("\\MyCompany\\MyApplication\\Domain\\Model\\AbstractDataModel");
foreach($classNames as $className) {
$tag = new \MyCompany\MyApplication\Utility\TagsinputTag(substr($className, 1));
if(!is_string($query) || (strlen($query) > 0 && (stripos($tag->getValue(), $query) !== FALSE || stripos($tag->getOutput(), $query) !== FALSE))) {
$classNames[] = $tag;
}
}
$this->view->assign('value', $classNames);
}
/**
* @param string $query The current search string provided by the user
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @return void
*/
public function joinQueryAction($from, $join, $query = NULL) {
// get join operations
$joins = $joinOperands = array();
foreach(DqlStatement::getJoins() as $joinOperand) {
$tag = new \MyCompany\MyApplication\Utility\TagsinputTag($joinOperand);
$joins[] = $tag;
$joinOperands[] = $tag->getValue();
}
// check what the next input should be
$joinStatements = explode(',', $join);
if(!in_array(end($joinStatements), $joinOperands)) $tags = $joins;
else $tags = $this->getAllJoinableTags($from, $join);
/** @var \MyCompany\MyApplication\Utility\TagsinputTag $tag */
foreach($tags as $i => $tag) {
if(is_string($query) && strlen($query) > 0 && stripos($tag->getValue(), $query) === FALSE && stripos($tag->getOutput(), $query) === FALSE) {
unset($tags[$i]);
}
}
$this->view->assign('value', $tags);
}
/**
* @param string $query The current search string provided by the user
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @return void
*/
public function selectQueryAction($from, $join, $query = NULL) {
$tags = $this->getAllTags($from, $join);
/** @var \MyCompany\MyApplication\Utility\TagsinputTag $tag */
foreach($tags as $i => $tag) {
if(is_string($query) && strlen($query) > 0 && stripos($tag->getValue(), $query) === FALSE && stripos($tag->getOutput(), $query) === FALSE) {
unset($tags[$i]);
}
}
$this->view->assign('value', $tags);
}
/**
* @param string $query The current search string provided by the user
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @param string $where DQL where statement, separated by commas
* @return void
*/
public function whereQueryAction($from, $join, $where, $query = NULL) {
$tags = $tagValues = array();
$where = (strlen(trim($where)) > 0) ? explode(',', $where) : array();
// add whatever the user typed in, because here free input is possible
if(in_array(end($where), DqlStatement::getOperations())) {
$tag = new \MyCompany\MyApplication\Utility\TagsinputTag();
$tag->setValue('\''.$query.'\'');
$tag->setOutput($query);
$tag->setType(TagsinputTag::TYPE_FREE);
$tags[] = $tag;
}
$tags = array_merge($tags, $this->getAllTags($from, $join), $this->getAllJoinableTags($from, $join, TRUE));
/** @var \MyCompany\MyApplication\Utility\TagsinputTag $tag */
foreach($tags as $tag) $tagValues[] = $tag->getValue();
// get all operations
$operations = $conjunctions = $functions = array();
foreach(DqlStatement::getOperations() as $operation) $operations[] = new \MyCompany\MyApplication\Utility\TagsinputTag($operation);
foreach(DqlStatement::getConjunctions() as $conjunction) $conjunctions[] = new \MyCompany\MyApplication\Utility\TagsinputTag($conjunction);
foreach(DqlStatement::getFunctions() as $function) $functions[] = new \MyCompany\MyApplication\Utility\TagsinputTag($function);
// check what the next input should be
if(count($where) <= 0) $tags = array_merge($tags, $conjunctions);
elseif(in_array(end($where), $tagValues)) $tags = array_merge($operations, $conjunctions, $functions);
elseif(in_array(end($where), DqlStatement::getOperations())) $tags = array_merge($tags, $functions); // & free input
elseif(in_array(end($where), DqlStatement::getConjunctions())) $tags = array_merge($tags, $conjunctions);
else $tags = $conjunctions;
/** @var \MyCompany\MyApplication\Utility\TagsinputTag $tag */
foreach($tags as $i => $tag) {
if(is_string($query) && strlen($query) > 0 && stripos($tag->getValue(), $query) === FALSE && stripos($tag->getOutput(), $query) === FALSE) {
unset($tags[$i]);
}
}
$this->view->assign('value', $tags);
}
/**
* @param string $query The current search string provided by the user
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @return void
*/
public function orderQueryAction($from, $join, $query = NULL) {
$allTags = $this->getAllTags($from, $join);
$tags = array();
/** @var \MyCompany\MyApplication\Utility\TagsinputTag $tag */
foreach($allTags as $tag) {
if(!is_string($query) || (strlen($query) > 0 && (stripos($tag->getValue(), $query) !== FALSE || stripos($tag->getOutput(), $query) !== FALSE))) {
$tags = array_merge($tag->getOrderingTags(), $tags);
}
}
$this->view->assign('value', $tags);
}
/**
* Gets all tags of the objects provided in $from and $join that can be joined
*
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @param boolean $includeObjectProperties
* @return array<\MyCompany\MyApplication\Utility\TagsinputTag>
*/
protected function getAllJoinableTags($from, $join, $includeObjectProperties = FALSE) {
$tags = array();
$sourceClassNames = array();
if(is_string($from) && strlen($from) > 0) {
foreach(explode(',', $from) as $fromClassName) {
$fromPropertyName = $this->dataClassReflection->getPropertyNameFromClassname($fromClassName);
$sourceClassNames[$fromPropertyName] = $fromClassName;
if(strlen($fromPropertyName) > 0 && $includeObjectProperties === TRUE) $tags[] = new \MyCompany\MyApplication\Utility\TagsinputTag($fromPropertyName);
foreach($this->reflectionService->getClassPropertyNames($fromClassName) as $propertyName) {
$reflection = new \TYPO3\Flow\Reflection\PropertyReflection($fromClassName, $propertyName);
if($reflection->isTaggedWith('onetoone') || $reflection->isTaggedWith('manytoone') || $reflection->isTaggedWith('onetomany') || $reflection->isTaggedWith('manytomany')) {
if(!in_array($propertyName, $this->dataClassReflection->getForbiddenProperties())) {
$tags[] = new \MyCompany\MyApplication\Utility\TagsinputTag($fromPropertyName.'.'.$propertyName);
}
}
}
}
}
// get joined fields
if(is_string($join) && strlen($join) > 0) {
foreach(explode(',', $join) as $joinStatement) {
// if this join statement is a join operand (like 'LEFT JOIN'), ignore it
if(in_array($joinStatement, DqlStatement::getJoins())) continue;
list($sourcePropertyName, $joinPropertyName) = explode('.', trim($joinStatement)); // something like 'link.student'
$varValue = $this->reflectionService->getPropertyTagValues($sourceClassNames[$sourcePropertyName], $joinPropertyName, 'var');
// get first @var tag value, like '\MyCompany\MyApplication\Domain\Model\Student'
$joinClassName = $this->dataClassReflection->getGenericTypeOfCollection($varValue[0]);
foreach($this->reflectionService->getClassPropertyNames($joinClassName) as $propertyName) {
$reflection = new \TYPO3\Flow\Reflection\PropertyReflection($joinClassName, $propertyName);
if($reflection->isTaggedWith('onetoone') || $reflection->isTaggedWith('manytoone') || $reflection->isTaggedWith('onetomany') || $reflection->isTaggedWith('manytomany')) {
if(!in_array($propertyName, $this->dataClassReflection->getForbiddenProperties())) {
$tags[] = new \MyCompany\MyApplication\Utility\TagsinputTag($joinPropertyName.'.'.$propertyName);
}
}
}
// this class is now joined, add to source classes
$sourceClassNames[$joinPropertyName] = $joinClassName;
}
}
return $tags;
}
/**
* Gets all tags of the objects provided in $from and $join
*
* @param string $from A fully specified class name
* @param string $join Comma separated list of joined properties
* @return array<\MyCompany\MyApplication\Utility\TagsinputTag>
*/
protected function getAllTags($from, $join) {
$tags = array();
$sourceClassNames = array();
if(is_string($from) && strlen($from) > 0) {
foreach(explode(',', $from) as $fromClassName) {
$fromPropertyName = $this->dataClassReflection->getPropertyNameFromClassname($fromClassName);
$sourceClassNames[$fromPropertyName] = $fromClassName;
foreach($this->dataClassReflection->getProperties($fromClassName, 1) as $propertyName) {
try {
$tags[] = new \MyCompany\MyApplication\Utility\TagsinputTag($fromPropertyName.'.'.$propertyName, (!$this->dataClassReflection->isRealPropertyOfClass($fromClassName, $propertyName)));
}
catch(Exception\TagNotAllowedException $e) {}
}
}
}
// get joined fields
if(is_string($join) && strlen($join) > 0) {
foreach(explode(',', $join) as $joinStatement) {
// if this join statement is a join operand (like 'LEFT JOIN'), ignore it
if(in_array($joinStatement, DqlStatement::getJoins())) continue;
list($sourcePropertyName, $joinPropertyName) = explode('.', $joinStatement); // something like 'link.student'
$varValue = $this->reflectionService->getPropertyTagValues($sourceClassNames[$sourcePropertyName], $joinPropertyName, 'var');
// get first @var tag value, like '\MyCompany\MyApplication\Domain\Model\Student'
$joinClassName = $this->dataClassReflection->getGenericTypeOfCollection($varValue[0]);
foreach($this->dataClassReflection->getProperties($joinClassName, 1) as $propertyName) {
try {
$tags[] = new \MyCompany\MyApplication\Utility\TagsinputTag($joinPropertyName.'.'.$propertyName, (!$this->dataClassReflection->isRealPropertyOfClass($joinClassName, $propertyName)));
}
catch(Exception\TagNotAllowedException $e) {}
}
// this class is now joined, add to source classes
$sourceClassNames[$joinPropertyName] = $joinClassName;
}
}
return $tags;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment