classes/Gems/Controller/ModelSnippetActionAbstract.php
<?php
/**
*
* @package Gems
* @subpackage Controller
* @author Matijs de Jong <mjong@magnafacta.nl>
* @copyright Copyright (c) 2011 Erasmus MC
* @license New BSD License
*/
/**
* Class contains Gems specific adaptations to parent class.
*
* @package Gems
* @subpackage Controller
* @copyright Copyright (c) 2011 Erasmus MC
* @license New BSD License
* @since Class available since version 1.4.2
*/
abstract class Gems_Controller_ModelSnippetActionAbstract extends \MUtil_Controller_ModelSnippetActionAbstract
{
/**
* Gems only parameters used for the autofilter action. Can be overruled
* by setting $this->autofilterParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_autofilterExtraParameters = array(
'browse' => true,
'containingId' => 'autofilter_target',
'keyboard' => true,
'onEmpty' => 'getOnEmptyText',
'sortParamAsc' => 'asrt',
'sortParamDesc' => 'dsrt',
);
/**
* Gems only parameters used for the create action. Can be overruled
* by setting $this->createParameters or $this->createEditParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_createExtraParameters = array(
'formTitle' => 'getCreateTitle',
'topicCallable' => 'getTopicCallable',
);
/**
* Gems only parameters used for the deactivate action. Can be overruled
* by setting $this->deactivateParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_deactivateExtraParameters = array(
'confirmQuestion' => 'getDeactivateQuestion',
'displayTitle' => 'getDeactivateTitle',
'formTitle' => 'getDeactivateTitle',
'topicCallable' => 'getTopicCallable',
);
/**
* Gems only parameters used for the delete action. Can be overruled
* by setting $this->deleteParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_deleteExtraParameters = array(
'deleteQuestion' => 'getDeleteQuestion',
'displayTitle' => 'getDeleteTitle',
'formTitle' => 'getDeleteTitle',
'topicCallable' => 'getTopicCallable',
);
/**
* Gems only parameters used for the edit action. Can be overruled
* by setting $this->editParameters or $this->createEditParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_editExtraParameters = array(
'formTitle' => 'getEditTitle',
'topicCallable' => 'getTopicCallable',
);
/**
* Gems only parameters used for the export action. Can be overruled
* by setting $this->editParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_exportExtraParameters = [
'exportClasses' => 'getExportClasses',
];
/**
* Gems only parameters used for the import action. Can be overruled
* by setting $this->inmportParameters
*
* @var array Mixed key => value array for snippet initializPdfation
*/
private $_importExtraParameters = array(
'formatBoxClass' => 'browser table',
'importer' => 'getImporter',
'tempDirectory' => 'getImportTempDirectory',
'topicCallable' => 'getTopic',
);
/**
* Gems only parameters used for the deactivate action. Can be overruled
* by setting $this->deactivateParameters
*
* @var array Mixed key => value array for snippet initialization
*/
private $_reactivateExtraParameters = array(
'confirmQuestion' => 'getReactivateQuestion',
'displayTitle' => 'getReactivateTitle',
'formTitle' => 'getReactivateTitle',
'topicCallable' => 'getTopicCallable',
);
/**
*
* @var \Gems_AccessLog
*/
public $accesslog;
/**
* The snippets used for the autofilter action.
*
* @var mixed String or array of snippets name
*/
protected $autofilterSnippets = 'ModelTableSnippetGeneric';
/**
* The snippets used for the create and edit actions.
*
* @var mixed String or array of snippets name
*/
protected $createEditSnippets = 'ModelFormSnippetGeneric';
/**
* The snippets used for the delete action.
*
* @var mixed String or array of snippets name
*/
protected $deleteSnippets = 'ModelItemYesNoDeleteSnippetGeneric';
/**
*
* @var GemsEscort
*/
public $escort;
/**
* The snippets used for the export action
*
* @var mixed String or array of snippets name
*/
protected $exportFormSnippets = 'Export\\ExportFormSnippet';
/**
* The parameters used for the export actions.
*
* When the value is a function name of that object, then that functions is executed
* with the array key as single parameter and the return value is set as the used value
* - unless the key is an integer in which case the code is executed but the return value
* is not stored.
*
* @var array Mixed key => value array for snippet initialization
*/
protected $exportParameters = [];
/**
*
* @var \Gems_Loader
*/
public $loader;
/**
*
* @var \Gems_Menu
*/
public $menu;
/**
* The snippets used for the index action, before those in autofilter
*
* @var mixed String or array of snippets name
*/
protected $indexStartSnippets = array('Generic\\ContentTitleSnippet', 'AutosearchFormSnippet');
/**
* The snippets used for the index action, after those in autofilter
*
* @var mixed String or array of snippets name
*/
protected $indexStopSnippets = 'Generic\\CurrentSiblingsButtonRowSnippet';
/**
*
* @var \Zend_Controller_Action_Helper_FlashMessenger
*/
public $messenger;
/**
* The snippets used for the show action
*
* @var mixed String or array of snippets name
*/
protected $showSnippets = array('Generic\\ContentTitleSnippet', 'ModelItemTableSnippetGeneric');
/**
* Array of the actions that use a summarized version of the model.
*
* This determines the value of $detailed in createAction(). As it is usually
* less of a problem to use a $detailed model with an action that should use
* a summarized model and I guess there will usually be more detailed actions
* than summarized ones it seems less work to specify these.
*
* @var array $summarizedActions Array of the actions that use a
* summarized version of the model.
*/
public $summarizedActions = array('index', 'autofilter', 'export');
/**
*
* @var \Gems_Util
*/
public $util;
/**
* The automatically filtered result
*
* @param $resetMvc When true only the filtered resulsts
*/
public function autofilterAction($resetMvc = true)
{
$htmlOrig = $this->html;
$div = $this->html->div(array('id' => 'autofilter_target', 'class' => 'table-container'));
// Already done when this value is false
if ($resetMvc) {
$this->autofilterParameters = $this->autofilterParameters + $this->_autofilterExtraParameters;
}
$this->html = $div;
parent::autofilterAction($resetMvc);
$this->html = $htmlOrig;
}
/**
* Action for showing a create new item page with extra title
*/
public function createAction()
{
$this->createEditParameters = $this->createEditParameters + $this->_createExtraParameters;
parent::createAction();
}
/**
* Action for showing a deactivate item page with extra titles
*/
public function deactivateAction()
{
$this->deactivateParameters = $this->deactivateParameters + $this->_deactivateExtraParameters;
parent::deactivateAction();
}
/**
* Action for showing a delete item page with extra titles
*/
public function deleteAction()
{
$this->deleteParameters = $this->deleteParameters + $this->_deleteExtraParameters;
parent::deleteAction();
}
/**
* Action for showing a edit item page with extra title
*/
public function editAction()
{
$this->createEditParameters = $this->createEditParameters + $this->_editExtraParameters;
parent::editAction();
}
/**
* Export model data
*/
public function exportAction()
{
$step = $this->request->getParam('step');
$post = $this->request->getPost();
$this->autofilterParameters = $this->autofilterParameters + $this->_autofilterExtraParameters;
$model = $this->getExportModel();
if (isset($this->autofilterParameters['sortParamAsc'])) {
$model->setSortParamAsc($this->autofilterParameters['sortParamAsc']);
}
if (isset($this->autofilterParameters['sortParamDesc'])) {
$model->setSortParamDesc($this->autofilterParameters['sortParamDesc']);
}
$model->applyParameters($this->getSearchFilter(false), true);
if (!empty($post)) {
$this->accesslog->logChange($this->request, null, $post + $model->getFilter());
}
// Add any defaults.
if (isset($this->autofilterParameters['extraFilter'])) {
$model->addFilter($this->autofilterParameters['extraFilter']);
}
if (isset($this->autofilterParameters['extraSort'])) {
$model->addSort($this->autofilterParameters['extraSort']);
}
if ((!$step) || ($post && $step == 'form')) {
$params = $this->_processParameters($this->exportParameters + $this->_exportExtraParameters);
$this->addSnippet($this->exportFormSnippets, $params);
$batch = $this->loader->getTaskRunnerBatch('export_data');
$batch->reset();
} elseif ($step == 'batch') {
$batch = $this->loader->getTaskRunnerBatch('export_data');
$batch->setVariable('model', $model);
if (!$batch->count()) {
$batch->minimalStepDurationMs = 2000;
$batch->finishUrl = $this->view->url(array('step' => 'download'));
$batch->setSessionVariable('files', array());
if (! isset($post['type'])) {
// Export type is needed, use most basic type
$post['type'] = 'CsvExport';
}
$batch->addTask('Export_ExportCommand', $post['type'], 'addExport', $post);
$batch->addTask('addTask', 'Export_ExportCommand', $post['type'], 'finalizeFiles', $post);
$export = $this->loader->getExport()->getExport($post['type']);
if ($snippet = $export->getHelpSnippet()) {
$this->addSnippet($snippet);
}
$batch->autoStart = true;
}
if (\MUtil_Console::isConsole()) {
// This is for unit tests, if we want to be able to really export from
// cli we need to place the exported file somewhere.
// This is out of scope for now.
$batch->runContinuous();
} elseif ($batch->run($this->request)) {
exit;
} else {
$controller = $this;
if ($batch->isFinished()) {
/*\MUtil_Echo::track('finished');
$file = $batch->getSessionVariable('file');
if ((!empty($file)) && isset($file['file']) && file_exists($file['file'])) {
// Forward to download action
$this->_session->exportFile = $file;
}*/
} else {
if ($batch->count()) {
$controller->html->append($batch->getPanel($controller->view, $batch->getProgressPercentage() . '%'));
} else {
$controller->html->pInfo($controller->_('Nothing to do.'));
}
$url = $this->getExportReturnLink();
if ($url) {
$controller->html->pInfo()->a(
$url,
array('class'=>'actionlink'),
$this->_('Back')
);
}
}
}
} elseif ($step == 'download') {
$batch = $this->loader->getTaskRunnerBatch('export_data');
$file = $batch->getSessionVariable('file');
if ($file && is_array($file) && is_array($file['headers'])) {
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
foreach($file['headers'] as $header) {
header($header);
}
while (ob_get_level()) {
ob_end_clean();
}
readfile($file['file']);
// Now clean up the file
unlink($file['file']);
exit;
}
$this->addMessage($this->_('Download no longer available.'), 'warning');
}
}
/**
* Finds the first item with one of the actions specified as parameter and using the current controller
*
* @param string $action
* @param string $action2
* @return \Gems_Menu_SubMenuItem
*/
protected function firstAllowedMenuItem($action, $action2 = null)
{
$actions = \MUtil_Ra::args(func_get_args());
$controller = $this->_getParam('controller');
foreach ($actions as $action) {
$menuItem = $this->menu->find(array('controller' => $controller, 'action' => $action, 'allowed' => true));
if ($menuItem) {
return $menuItem;
}
}
}
/**
* Helper function to get the title for the create action.
*
* @return $string
*/
public function getCreateTitle()
{
return sprintf($this->_('New %s...'), $this->getTopic(1));
}
/**
* Name of the default import translator
*
* @return string
*/
public function getDefaultImportTranslator()
{
return $this->loader->getImportLoader()->getDefaultTranslator($this->getRequest()->getControllerName());
}
/**
* Helper function to get the question for the deactivate action.
*
* @return $string
*/
public function getDeactivateQuestion()
{
return sprintf($this->_('Do you want to deactivate this %s?'), $this->getTopic(1));
}
/**
* Helper function to get the title for the deactivate action.
*
* @return $string
*/
public function getDeactivateTitle()
{
return sprintf($this->_('Deactivate %s'), $this->getTopic(1));
}
/**
* Helper function to get the question for the delete action.
*
* @return $string
*/
public function getDeleteQuestion()
{
return sprintf($this->_('Do you want to delete this %s?'), $this->getTopic(1));
}
/**
* Helper function to get the title for the delete action.
*
* @return $string
*/
public function getDeleteTitle()
{
return sprintf($this->_('Delete %s'), $this->getTopic(1));
}
/**
* Helper function to get the title for the edit action.
*
* @return $string
*/
public function getEditTitle()
{
return sprintf($this->_('Edit %s'), $this->getTopic(1));
}
public function getExportClasses()
{
return $this->loader->getExport()->getExportClasses();
}
/**
* Get the model for export and have the option to change it before using for export
* @return
*/
protected function getExportModel()
{
$model = $this->getModel();
$noExportColumns = $model->getColNames('noExport');
foreach($noExportColumns as $colName) {
$model->remove($colName, 'label');
}
return $model;
}
/**
* Get the return url
*
* @return array
*/
protected function getExportReturnLink()
{
return \MUtil_Html_UrlArrayAttribute::rerouteUrl($this->getRequest(), array('action'=>'index', 'step' => false));
}
/**
* Get an Importer object for this actions
*
* @return \MUtil_Model_Importer
*/
public function getImporter()
{
return $this->loader->getImportLoader()->getImporter(
$this->getRequest()->getControllerName(),
$this->getModel()
);
}
/**
* The directory to use for temporary storage
*
* @return string
*/
public function getImportTempDirectory()
{
return $this->loader->getImportLoader()->getTempDirectory();
}
/**
* Get the possible translators for the import snippet.
*
* @return \MUtil_Model_ModelTranslatorInterface[]
*/
public function getImportTranslators()
{
return $this->loader->getImportLoader()->getTranslators($this->getRequest()->getControllerName());
}
/**
* Helper function to get the title for the index action.
*
* @return $string
*/
public function getIndexTitle()
{
return ucfirst($this->getTopic(100));
}
/**
* Return the current request ID, if any.
*
* Overrule this function if the last item in the page title
* should be something other than te value of
* \MUtil_Model::REQUEST_ID.
*
* @return mixed
*/
public function getInstanceId()
{
if ($id = $this->_getParam(\MUtil_Model::REQUEST_ID)) {
return $id;
}
}
/**
* Returns a session based message store for adding messages to.
*
* @return \Zend_Controller_Action_Helper_FlashMessenger
*/
public function getMessenger()
{
if (! $this->messenger) {
$this->setMessenger($this->loader->getMessenger());
}
return $this->messenger;
}
/**
* Returns the on empty texts for the autofilter snippets
*
* @return string
*/
public function getOnEmptyText()
{
return sprintf($this->_('No %s found...'), $this->getTopic(0));
}
/**
* Helper function to get the question for the reactivate action.
*
* @return $string
*/
public function getReactivateQuestion()
{
return sprintf($this->_('Do you want to reactivate this %s?'), $this->getTopic(1));
}
/**
* Helper function to get the title for the reactivate action.
*
* @return $string
*/
public function getReactivateTitle()
{
return sprintf($this->_('Reactivate %s'), $this->getTopic(1));
}
/**
* Helper function to get the title for the show action.
*
* @return $string
*/
public function getShowTitle()
{
return sprintf($this->_('Showing %s'), $this->getTopic(1));
}
/**
* Returns the current html/head/title for this page.
*
* If the title is an array the seperator concatenates the parts.
*
* @param string $separator
* @return string
*/
public function getTitle($separator = null)
{
if ($titleSet = parent::getTitle($separator)) {
return $titleSet;
}
$title = array();
foreach($this->menu->getActivePath($this->getRequest()) as $menuItem) {
$title[] = $menuItem->get('label');
}
if ($id = $this->getInstanceId()) {
$title[] = $id;
}
return implode($separator, $title);
}
/**
* Helper function to allow generalized statements about the items in the model.
*
* @param int $count
* @return $string
*/
public function getTopic($count = 1)
{
return $this->plural('item', 'items', $count);
}
/**
* Get a callable for the gettopic function
* @return callable
*/
public function getTopicCallable()
{
return array($this, 'getTopic');
}
/**
* Generic model based import action
*/
public function importAction()
{
$this->importParameters = $this->importParameters + $this->_importExtraParameters;
parent::importAction();
}
/**
* Action for showing a browse page
*/
public function indexAction()
{
$this->autofilterParameters = $this->autofilterParameters + $this->_autofilterExtraParameters;
if (! isset($this->indexParameters['contentTitle'])) {
$this->indexParameters['contentTitle'] = $this->getIndexTitle();
}
return parent::indexAction();
}
/**
* Intializes the html component.
*
* @param boolean $reset Throws away any existing html output when true
* @return void
*/
public function initHtml($reset = false)
{
if (! $this->html) {
\Gems_Html::init();
}
parent::initHtml($reset);
}
/**
* Stub for overruling default snippet loader initiation.
*/
protected function loadSnippetLoader()
{
// Create the snippet with this controller as the parameter source
$this->snippetLoader = $this->loader->getSnippetLoader($this);
}
/**
* Action for showing a reactivate item page with extra titles
*/
public function reactivateAction()
{
$this->reactivateParameters = $this->reactivateParameters + $this->_reactivateExtraParameters;
parent::reactivateAction();
}
/**
* Set the session based message store.
*
* @param \Zend_Controller_Action_Helper_FlashMessenger $messenger
* @return \MUtil_Controller_Action
*/
public function setMessenger(\Zend_Controller_Action_Helper_FlashMessenger $messenger)
{
$this->messenger = $messenger;
$this->view->messenger = $messenger;
return $this;
}
/**
* Action for showing an item page with title
*/
public function showAction()
{
if (! isset($this->showParameters['contentTitle'])) {
$this->showParameters['contentTitle'] = $this->getShowTitle();
}
parent::showAction();
}
}