All Data Structures Functions Variables Pages
ZurmoBaseController.php
1 <?php
2  /*********************************************************************************
3  * Zurmo is a customer relationship management program developed by
4  * Zurmo, Inc. Copyright (C) 2017 Zurmo Inc.
5  *
6  * Zurmo is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  *
13  * Zurmo is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  *
23  * You can contact Zurmo, Inc. with a mailing address at 27 North Wacker Drive
24  * Suite 370 Chicago, IL 60606. or at email address contact@zurmo.com.
25  *
26  * The interactive user interfaces in original and modified versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  *
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the Zurmo
32  * logo and Zurmo copyright notice. If the display of the logo is not reasonably
33  * feasible for technical reasons, the Appropriate Legal Notices must display the words
34  * "Copyright Zurmo Inc. 2017. All rights reserved".
35  ********************************************************************************/
36 
37  abstract class ZurmoBaseController extends Controller
38  {
39  const RIGHTS_FILTER_PATH = 'application.modules.zurmo.controllers.filters.RightsControllerFilter';
40 
41  const REQUIRED_ATTRIBUTES_FILTER_PATH = 'application.modules.zurmo.controllers.filters.RequiredAttributesControllerFilter';
42 
43  const ADMIN_VIEW_MOBILE_CHECK_FILTER_PATH = 'application.modules.zurmo.controllers.filters.AdminViewMobileCheckControllerFilter';
44 
45  const ROOT_USER_ACCESS_FILTER_PATH = 'application.modules.zurmo.controllers.filters.RootUserAccessControllerFilter';
46 
47  public function filters()
48  {
49  $moduleClassName = $this->resolveModuleClassNameForFilters();
50  $filters = array();
51  if (is_subclass_of($moduleClassName, 'SecurableModule'))
52  {
53  $filters[] = array(
54  self::getRightsFilterPath(),
55  'moduleClassName' => $moduleClassName,
56  'rightName' => $moduleClassName::getAccessRight(),
57  );
58  $filters[] = array(
59  self::getRightsFilterPath() . ' + create, createFromRelation, inlineCreateSave, copy, modalCreate',
60  'moduleClassName' => $moduleClassName,
61  'rightName' => $moduleClassName::getCreateRight(),
62  );
63  $filters[] = array(
64  self::getRightsFilterPath() . ' + delete',
65  'moduleClassName' => $moduleClassName,
66  'rightName' => $moduleClassName::getDeleteRight(),
67  );
68  }
69  $filters[] = array(
70  self::getRightsFilterPath() . ' + massEdit, massEditProgressSave',
71  'moduleClassName' => 'ZurmoModule',
72  'rightName' => ZurmoModule::RIGHT_BULK_WRITE,
73  );
74  $filters['RIGHT_BULK_DELETE'] = array(
75  self::getRightsFilterPath() . ' + massDelete, massDeleteProgress',
76  'moduleClassName' => 'ZurmoModule',
77  'rightName' => ZurmoModule::RIGHT_BULK_DELETE,
78  );
79  return $filters;
80  }
81 
82  public function resolveModuleClassNameForFilters()
83  {
84  return get_class($this->getModule());
85  }
86 
87  public function __construct($id, $module = null)
88  {
89  parent::__construct($id, $module);
90  }
91 
92  public static function getRightsFilterPath()
93  {
94  return static::RIGHTS_FILTER_PATH;
95  }
96 
97  protected function makeActionBarSearchAndListView($searchModel, $dataProvider,
98  $actionBarViewClassName = 'SecuredActionBarForSearchAndListView',
99  $viewPrefixName = null, $activeActionElementType = null,
100  IntroView $introView = null)
101  {
102  assert('is_string($actionBarViewClassName)');
103  assert('is_string($viewPrefixName) || $viewPrefixName == null');
104  assert('is_string($activeActionElementType) || $activeActionElementType == null');
105  if ($viewPrefixName == null)
106  {
107  $viewPrefixName = $this->getModule()->getPluralCamelCasedName();
108  }
109  $listModel = $searchModel->getModel();
110  return new ActionBarSearchAndListView(
111  $this->getId(),
112  $this->getModule()->getId(),
113  $searchModel,
114  $listModel,
115  $viewPrefixName,
116  $dataProvider,
118  $actionBarViewClassName,
119  $activeActionElementType,
120  $introView
121  );
122  }
123 
124  protected function makeActionBarAndListView($listModel, $dataProvider, $actionBarViewClassName = 'ActionBarForSearchAndListView',
125  $viewPrefixName = null, $activeActionElementType = null)
126  {
127  assert('is_string($actionBarViewClassName)');
128  assert('is_string($viewPrefixName) || $viewPrefixName == null');
129  assert('is_string($activeActionElementType) || $activeActionElementType == null');
130  if ($viewPrefixName == null)
131  {
132  $viewPrefixName = $this->getModule()->getPluralCamelCasedName();
133  }
134  return new ActionBarAndListView(
135  $this->getId(),
136  $this->getModule()->getId(),
137  $listModel,
138  $viewPrefixName,
139  $dataProvider,
141  $actionBarViewClassName,
142  $activeActionElementType
143  );
144  }
145 
146  protected function makeListView(SearchForm $searchForm, $dataProvider, $listViewClassName = null)
147  {
148  assert('is_string($listViewClassName) || $listViewClassName == null');
149  $listModel = $searchForm->getModel();
150  if ($listViewClassName == null)
151  {
152  $listViewClassName = $this->getModule()->getPluralCamelCasedName() . 'ListView';
153  }
154  $listView = new $listViewClassName(
155  $this->getId(),
156  $this->getModule()->getId(),
157  get_class($listModel),
158  $dataProvider,
160  null,
161  array(),
162  $searchForm->getListAttributesSelector(),
163  $searchForm->getKanbanBoard());
164  return $listView;
165  }
166 
167  protected function resolveSearchDataProvider(
168  $searchModel,
169  $pageSize,
170  $stateMetadataAdapterClassName = null,
171  $stickySearchKey = null,
172  $setSticky = true)
173  {
174  assert('$searchModel instanceof RedBeanModel || $searchModel instanceof ModelForm');
175  assert('$stickySearchKey == null || is_string($stickySearchKey)');
176  assert('is_bool($setSticky)');
177  $listModelClassName = get_class($searchModel->getModel());
178  static::resolveToTriggerOnSearchEvents($listModelClassName);
179  $this->resolveKanbanBoardIsActiveByGet($searchModel);
180  $dataCollection = $this->makeDataCollectionAndResolveSavedSearch($searchModel, $stickySearchKey, $setSticky);
181  $pageSize = $this->resolvePageSizeForKanbanBoard($searchModel, $pageSize);
182  $dataProvider = $this->makeRedBeanDataProviderByDataCollection($searchModel, $pageSize,
183  $stateMetadataAdapterClassName, $dataCollection);
184  return $dataProvider;
185  }
186 
190  private function resolveKanbanBoardIsActiveByGet($searchModel)
191  {
192  if (!$searchModel instanceof SearchForm || $searchModel->getKanbanBoard() == null)
193  {
194  return;
195  }
196  if (isset($_GET['kanbanBoard']) && $_GET['kanbanBoard'] && !Yii::app()->userInterface->isMobile())
197  {
198  $searchModel->getKanbanBoard()->setIsActive();
199  }
200  elseif (isset($_GET['kanbanBoard']) && !$_GET['kanbanBoard'])
201  {
202  $searchModel->getKanbanBoard()->setIsNotActive();
203  $searchModel->getKanbanBoard()->setClearSticky();
204  }
205  elseif (Yii::app()->userInterface->isMobile())
206  {
207  $searchModel->getKanbanBoard()->setIsNotActive();
208  }
209  }
210 
216  private function resolvePageSizeForKanbanBoard($searchModel, $pageSize)
217  {
218  if (!$searchModel instanceof SearchForm)
219  {
220  return $pageSize;
221  }
222  if ($searchModel instanceof TasksForRelatedKanbanSearchForm)
223  {
224  return $pageSize;
225  }
226  if ($searchModel->getKanbanBoard() !== null && $searchModel->getKanbanBoard()->getIsActive())
227  {
229  }
230  return $pageSize;
231  }
232 
233  private function makeDataCollectionAndResolveSavedSearch($searchModel, $stickySearchKey = null, $setSticky = true)
234  {
235  $dataCollection = new SearchAttributesDataCollection($searchModel);
236  if ($searchModel instanceof SavedDynamicSearchForm)
237  {
238  $getData = GetUtil::getData();
239  if ($stickySearchKey != null && isset($getData['clearingSearch']) && $getData['clearingSearch'])
240  {
241  StickySearchUtil::clearDataByKey($stickySearchKey);
242  }
243  if ($stickySearchKey != null && null != $stickySearchData = StickySearchUtil::getDataByKey($stickySearchKey))
244  {
245  SavedSearchUtil::resolveSearchFormByStickyDataAndModel($stickySearchData, $searchModel);
246  SavedSearchUtil::resolveSearchFormByStickySortData($getData, $searchModel, $stickySearchData);
247  SearchUtil::resolveSearchFormByStickyFilterByStarredData($getData, $searchModel, $stickySearchData);
248  SearchUtil::resolveSearchFormByStickyFilteredByData($getData, $searchModel, $stickySearchData);
249  SearchUtil::resolveSearchFormByStickyFilteredByData($getData, $searchModel, $stickySearchData);
250  $dataCollection = new SavedSearchAttributesDataCollection($searchModel);
251  }
252  else
253  {
254  SavedSearchUtil::resolveSearchFormByData($getData, $searchModel);
255  if ($searchModel->savedSearchId != null)
256  {
257  $dataCollection = new SavedSearchAttributesDataCollection($searchModel);
258  }
259  }
260  if ($stickySearchKey != null && ($setSticky ||
261  ($searchModel->getKanbanBoard() != null && $searchModel->getKanbanBoard()->getClearSticky())))
262  {
263  if ($stickySearchData == null)
264  {
265  $stickySearchData = array();
266  }
267  SavedSearchUtil::setDataByKeyAndDataCollection($stickySearchKey, $dataCollection, $stickySearchData);
268  }
269  $searchModel->loadSavedSearchUrl = Yii::app()->createUrl($this->getModule()->getId() . '/' . $this->getId() . '/list/');
270  }
271  return $dataCollection;
272  }
273 
274  protected function resolveToTriggerOnSearchEvents($listModelClassName)
275  {
276  $pageVariableName = $listModelClassName . '_page';
277  if (isset($_GET[$pageVariableName]) && $_GET[$pageVariableName] == null)
278  {
279  Yii::app()->gameHelper->triggerSearchModelsEvent($listModelClassName);
280  }
281  }
282 
283  protected function getDataProviderByResolvingSelectAllFromGet(
284  $searchModel,
285  $pageSize,
286  $userId,
287  $stateMetadataAdapterClassName = null,
288  $stickySearchKey = null
289  )
290  {
291  assert('$searchModel instanceof RedBeanModel || $searchModel instanceof ModelForm');
292  assert('is_string($stickySearchKey) || $stickySearchKey == null');
293  if ($_GET['selectAll'])
294  {
295  if (!isset($_GET[get_class($searchModel)]) && $stickySearchKey != null)
296  {
297  $resolvedStickySearchKey = $stickySearchKey;
298  }
299  else
300  {
301  $resolvedStickySearchKey = null;
302  }
303  return $this->resolveSearchDataProvider(
304  $searchModel,
305  $pageSize,
306  $stateMetadataAdapterClassName,
307  $resolvedStickySearchKey);
308  }
309  else
310  {
311  return null;
312  }
313  }
314 
320  protected function processMassEdit(
321  $pageSize,
322  $activeAttributes,
323  $selectedRecordCount,
324  $pageViewClassName,
325  $listModel,
326  $title,
327  $dataProvider = null
328  )
329  {
330  // TODO: @Shoaibi/@Jason: Low: Deprecated
331  // trigger_error('Deprecated');
332  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
333  $modelClassName = get_class($listModel);
334  $selectedRecordCount = static::getSelectedRecordCountByResolvingSelectAllFromGet($dataProvider);
335  if (isset($_POST[$modelClassName]))
336  {
337  PostUtil::sanitizePostForSavingMassEdit($modelClassName);
338  //Generically test that the changes are valid before attempting to save on each model.
339  $sanitizedPostData = PostUtil::sanitizePostByDesignerTypeForSavingModel(new $modelClassName(false), $_POST[$modelClassName]);
340  $sanitizedOwnerPostData = PostUtil::sanitizePostDataToJustHavingElementForSavingModel($sanitizedPostData, 'owner');
341  $sanitizedPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($sanitizedPostData, 'owner');
342  $massEditPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($_POST['MassEdit'], 'owner');
343  $listModel->setAttributes($sanitizedPostDataWithoutOwner);
344  if ($listModel->validate(array_keys($massEditPostDataWithoutOwner)))
345  {
346  $passedOwnerValidation = true;
347  if ($sanitizedOwnerPostData != null)
348  {
349  $listModel->setAttributes($sanitizedOwnerPostData);
350  $passedOwnerValidation = $listModel->validate(array('owner'));
351  }
352  if ($passedOwnerValidation)
353  {
355  Yii::app()->gameHelper->triggerMassEditEvent(get_class($listModel));
356  $this->saveMassEdit(
357  get_class($listModel),
358  $modelClassName,
359  $selectedRecordCount,
360  $dataProvider,
361  $_GET[$modelClassName . '_page'],
362  $pageSize
363  );
364  //cancel diminish of save scoring
365  if ($selectedRecordCount > $pageSize)
366  {
367  $view = new $pageViewClassName(ZurmoDefaultViewUtil::
368  makeStandardViewForCurrentUser($this,
369  $this->makeMassEditProgressView(
370  $listModel,
371  1,
372  $selectedRecordCount,
373  1,
374  $pageSize,
375  $title,
376  null)
377  ));
378  echo $view->render();
379  Yii::app()->end(0, false);
380  }
381  else
382  {
383  $skipCount = MassEditInsufficientPermissionSkipSavingUtil::getCount($modelClassName);
385  $selectedRecordCount, $skipCount);
387  $notificationContent = Zurmo::t('ZurmoModule', 'Successfully updated') . ' ' .
388  $successfulCount . ' ' .
390  '.';
391  if ($skipCount > 0)
392  {
393  $notificationContent .= ' ' .
395  $skipCount, $modelClassName);
396  }
397  Yii::app()->user->setFlash('notification', $notificationContent);
398  $this->redirect(array('default/'));
399  Yii::app()->end(0, false);
400  }
401  }
402  }
403  }
404  return $listModel;
405  }
406 
412  protected function processMassEditProgressSave(
413  $modelClassName,
414  $pageSize,
415  $title,
416  $dataProvider = null)
417  {
418  // TODO: @Shoaibi/@Jason: Low: Deprecated
419  // trigger_error('Deprecated');
420  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
421  $listModel = new $modelClassName(false);
422  $selectedRecordCount = static::getSelectedRecordCountByResolvingSelectAllFromGet($dataProvider);
423  PostUtil::sanitizePostForSavingMassEdit($modelClassName);
424  $this->saveMassEdit(
425  get_class($listModel),
426  $modelClassName,
427  $selectedRecordCount,
428  $dataProvider,
429  $_GET[$modelClassName . '_page'],
430  $pageSize
431  );
432  $view = $this->makeMassEditProgressView(
433  $listModel,
434  $_GET[$modelClassName . '_page'],
435  $selectedRecordCount,
436  $this->getMassEditProgressStartFromGet(
437  $modelClassName,
438  $pageSize
439  ),
440  $pageSize,
441  $title,
443  );
444  echo $view->renderRefreshJSONScript();
445  }
446 
447  protected function makeMassEditProgressView(
448  $model,
449  $page,
450  $selectedRecordCount,
451  $start,
452  $pageSize,
453  $title,
454  $skipCount)
455  {
456  // TODO: @Shoaibi/@Jason: Low: Deprecated
457  // trigger_error('Deprecated');
458  assert('$skipCount == null || is_int($skipCount)');
459  return new MassEditProgressView(
460  $this->getId(),
461  $this->getModule()->getId(),
462  $model,
463  $selectedRecordCount,
464  $start,
465  $pageSize,
466  $page,
467  'massEditProgressSave',
468  $title,
469  $skipCount
470  );
471  }
472 
476  protected function saveMassEdit($modelClassName, $postVariableName, $selectedRecordCount, $dataProvider, $page, $pageSize)
477  {
478  // TODO: @Shoaibi/@Jason: Low: Deprecated
479  // trigger_error('Deprecated');
480  Yii::app()->gameHelper->muteScoringModelsOnSave();
481  $modelsToSave = $this->getModelsToSave($modelClassName, $dataProvider, $selectedRecordCount, $page, $pageSize);
482  foreach ($modelsToSave as $modelToSave)
483  {
485  {
486  $sanitizedPostData = PostUtil::sanitizePostByDesignerTypeForSavingModel($modelToSave, $_POST[$modelClassName]);
487  $sanitizedOwnerPostData = PostUtil::sanitizePostDataToJustHavingElementForSavingModel($sanitizedPostData, 'owner');
488  $sanitizedPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($sanitizedPostData, 'owner');
489  $modelToSave->setAttributes($sanitizedPostDataWithoutOwner);
490  if ($sanitizedOwnerPostData != null)
491  {
492  $modelToSave->setAttributes($sanitizedOwnerPostData);
493  }
494  $modelToSave->save(false);
495  }
496  else
497  {
499  $modelClassName, $modelToSave->id, $modelToSave->name);
500  }
501  }
502  Yii::app()->gameHelper->unmuteScoringModelsOnSave();
503  }
504 
510  protected function processMassDelete(
511  $pageSize,
512  $activeAttributes,
513  $selectedRecordCount,
514  $pageViewClassName,
515  $listModel,
516  $title,
517  $dataProvider = null,
518  $redirectUrl = null
519  )
520  {
521  // TODO: @Shoaibi/@Jason: Low: Deprecated
522  // trigger_error('Deprecated');
523  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
524  $modelClassName = get_class($listModel);
525  $selectedRecordCount = static::getSelectedRecordCountByResolvingSelectAllFromGet($dataProvider);
526  if (isset($_POST['selectedRecordCount']))
527  {
528  $this->doMassDelete(
529  get_class($listModel),
530  $modelClassName,
531  $selectedRecordCount,
532  $dataProvider,
533  $_GET[$modelClassName . '_page'],
534  $pageSize
535  );
536 
537  // Cancel diminish of save scoring
538  if ($selectedRecordCount > $pageSize)
539  {
540  $view = new $pageViewClassName( ZurmoDefaultViewUtil::
541  makeStandardViewForCurrentUser($this,
542  $this->makeMassDeleteProgressView(
543  $listModel,
544  1,
545  $selectedRecordCount,
546  1,
547  $pageSize,
548  $title,
549  null)
550  ));
551  echo $view->render();
552  Yii::app()->end(0, false);
553  }
554  else
555  {
556  $skipCount = MassDeleteInsufficientPermissionSkipSavingUtil::getCount($modelClassName);
558  $selectedRecordCount, $skipCount);
560  $notificationContent = $successfulCount . ' ' .
562  ' ' . Zurmo::t('Core', 'successfully deleted') . '.';
563  if ($skipCount > 0)
564  {
565  $notificationContent .= ' ' .
567  $skipCount, $modelClassName);
568  }
569  Yii::app()->user->setFlash('notification', $notificationContent);
570  if ($redirectUrl === null)
571  {
572  $this->redirect(array('default/'));
573  }
574  else
575  {
576  $this->redirect($redirectUrl);
577  }
578  Yii::app()->end(0, false);
579  }
580  }
581  return $listModel;
582  }
583 
584  protected function processMassDeleteProgress(
585  $modelClassName,
586  $pageSize,
587  $title,
588  $dataProvider = null)
589  {
590  // TODO: @Shoaibi/@Jason: Low: Deprecated
591  // trigger_error('Deprecated');
592  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
593  $listModel = new $modelClassName(false);
594 
595  $postData = PostUtil::getData();
596  $selectedRecordCount = ArrayUtil::getArrayValue($postData, 'selectedRecordCount');
597 
598  $this->doMassDelete(
599  get_class($listModel),
600  $modelClassName,
601  $selectedRecordCount,
602  $dataProvider,
603  $_GET[$modelClassName . '_page'],
604  $pageSize
605  );
606  $view = $this->makeMassDeleteProgressView(
607  $listModel,
608  $_GET[$modelClassName . '_page'],
609  $selectedRecordCount,
611  $modelClassName,
612  $pageSize
613  ),
614  $pageSize,
615  $title,
617  );
618  echo $view->renderRefreshJSONScript();
619  }
620 
621  protected function makeMassDeleteProgressView(
622  $model,
623  $page,
624  $selectedRecordCount,
625  $start,
626  $pageSize,
627  $title,
628  $skipCount)
629  {
630  // TODO: @Shoaibi/@Jason: Low: Deprecated
631  // trigger_error('Deprecated');
632  assert('$skipCount == null || is_int($skipCount)');
633  return new MassDeleteProgressView(
634  $this->getId(),
635  $this->getModule()->getId(),
636  $model,
637  $selectedRecordCount,
638  $start,
639  $pageSize,
640  $page,
641  'massDeleteProgress',
642  $title,
643  $skipCount
644  );
645  }
646 
647  protected function doMassDelete($modelClassName, $postVariableName, $selectedRecordCount, $dataProvider, $page, $pageSize)
648  {
649  // TODO: @Shoaibi/@Jason: Low: Deprecated
650  // trigger_error('Deprecated');
651  Yii::app()->gameHelper->muteScoringModelsOnDelete();
652  $modelsToDelete = $this->getModelsToDelete($modelClassName, $dataProvider, $selectedRecordCount, $page, $pageSize);
653  foreach ($modelsToDelete as $modelToDelete)
654  {
655  if (ControllerSecurityUtil::doesCurrentUserHavePermissionOnSecurableItem($modelToDelete, Permission::DELETE))
656  {
657  $modelToDelete->delete(false);
658  }
659  else
660  {
662  $modelClassName, $modelToDelete->id, $modelToDelete->name);
663  }
664  }
665  Yii::app()->gameHelper->unmuteScoringModelsOnDelete();
666  }
667 
668  protected static function resolvePageValueForMassAction($modelClassName)
669  {
670  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
671  return intval(Yii::app()->request->getQuery($modelClassName . '_page'));
672  }
673 
674  protected function resolveReturnUrlForMassAction()
675  {
676  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
677  return $this->createUrl('/' . $this->getModule()->getId() . '/' . $this->getId() . '/');
678  }
679 
680  protected static function resolveViewIdByMassActionId($actionId, $returnProgressViewName, $moduleName = null)
681  {
682  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
683  if (static::applyGenericViewIdGenerationRules($actionId)) // decides when to use generic rules to build ViewId
684  {
685  $viewNameSuffix = (!$returnProgressViewName)? 'View': 'ProgressView';
686  $viewNamePrefix = static::resolveMassActionId($actionId, true);
687  if (MassActionUtil::isMassEditLikeAction($actionId))
688  {
689  $viewNamePrefix = $moduleName . $viewNamePrefix;
690  }
691  return $viewNamePrefix . $viewNameSuffix;
692  }
693  else
694  {
695  throw new NotSupportedException();
696  }
697  }
698 
699  protected static function applyGenericViewIdGenerationRules($actionId)
700  {
701  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
702  // overridden in Contacts/DefaultController
703  return MassActionUtil::isMassEditOrDeleteLikeAction($actionId);
704  }
705 
706  protected static function resolveTitleByMassActionId($actionId)
707  {
708  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
709  if (MassActionUtil::isMassDeleteLikeAction($actionId))
710  {
711  return Zurmo::t('Core', 'Mass Delete');
712  }
713  elseif (MassActionUtil::isMassEditLikeAction($actionId))
714  {
715  return Zurmo::t('Core', 'Mass Update');
716  }
717  else
718  {
719  throw new NotSupportedException();
720  }
721  }
722 
727  protected function attemptToSaveModelFromPost($model, $redirectUrlParams = null, $redirect = true, $returnOnValidate = false)
728  {
729  assert('$redirectUrlParams == null || is_array($redirectUrlParams) || is_string($redirectUrlParams)');
730  $savedSuccessfully = false;
731  $modelToStringValue = null;
732  $postVariableName = get_class($model);
733  if (isset($_POST[$postVariableName]))
734  {
735  $postData = $_POST[$postVariableName];
736  $controllerUtil = static::getZurmoControllerUtil();
737  $model = $controllerUtil->saveModelFromPost($postData, $model, $savedSuccessfully,
738  $modelToStringValue, $returnOnValidate);
739  }
740  if ($savedSuccessfully && $redirect)
741  {
742  $this->actionAfterSuccessfulModelSave($model, $modelToStringValue, $redirectUrlParams);
743  }
744  return $model;
745  }
746 
747  protected static function getZurmoControllerUtil()
748  {
749  return new ZurmoControllerUtil();
750  }
751 
752  protected function actionAfterSuccessfulModelSave($model, $modelToStringValue, $redirectUrlParams = null)
753  {
754  assert('is_string($modelToStringValue)');
755  assert('$redirectUrlParams == null || is_array($redirectUrlParams) || is_string($redirectUrlParams)');
757  {
758  if ($model instanceof RedBeanModel)
759  {
760  $this->beforeRedirect($model);
761  }
762  $this->redirectAfterSaveModel($model->id, $redirectUrlParams);
763  }
764  else
765  {
766  $notificationContent = Zurmo::t('ZurmoModule', 'You no longer have permissions to access {modelName}.',
767  array('{modelName}' => $modelToStringValue)
768  );
769  Yii::app()->user->setFlash('notification', $notificationContent);
770  $this->redirect(array($this->getId() . '/index'));
771  }
772  }
773 
774  protected function redirectAfterSaveModel($modelId, $urlParams = null)
775  {
776  if ($urlParams == null)
777  {
778  $urlParams = array($this->getId() . '/details', 'id' => $modelId);
779  }
780  $this->redirect($urlParams);
781  }
782 
788  protected static function getModelAndCatchNotFoundAndDisplayError($modelClassName, $id)
789  {
790  assert('is_string($modelClassName)');
791  assert('is_int($id)');
792  try
793  {
794  return $modelClassName::getById($id);
795  }
796  catch (NotFoundException $e)
797  {
798  $messageContent = Zurmo::t('ZurmoModule', 'The record you are trying to access does not exist.');
799  $messageView = new ModelNotFoundView($messageContent);
800  $view = new ModelNotFoundPageView($messageView);
801  echo $view->render();
802  Yii::app()->end(0, false);
803  }
804  }
805 
806  protected function triggerMassAction($modelClassName, $searchForm, $pageView, $title, $searchView = null,
807  $stateMetadataAdapterClassName = null, $useModuleClassNameForItemLabel = true)
808  {
809  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
810  $actionId = $this->getAction()->getId();
811  $pageSize = static::resolvePageSizeByMassActionId($actionId);
812  $model = new $modelClassName(false);
813  $dataProvider = $this->getDataProviderByResolvingSelectAllFromGet(
814  new $searchForm($model),
815  $pageSize,
816  Yii::app()->user->userModel->id,
817  $stateMetadataAdapterClassName,
818  $searchView
819  );
820  static::resolveOffsetForDataProvider($dataProvider, $actionId);
821  if (MassActionUtil::isMassProgressLikeAction($actionId))
822  {
823  $this->massActionProgress($model, $pageSize, $title, $actionId, $dataProvider);
824  }
825  else
826  {
827  $this->massAction($model, $pageSize, $title, $pageView, $actionId, $dataProvider, $useModuleClassNameForItemLabel);
828  }
829  }
830 
831  protected function massActionProgress($model, $pageSize, $title, $actionId, $dataProvider)
832  {
833  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
834  $this->processMassActionProgress(
835  $model,
836  $pageSize,
837  $title,
838  $actionId,
839  $dataProvider
840  );
841  }
842 
843  protected function massAction($model, $pageSize, $title, $pageView, $actionId, $dataProvider, $useModuleClassNameForItemLabel = true)
844  {
845  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
846  $activeAttributes = static::resolveActiveAttributesFromPostForMassAction($actionId);
847  $selectedRecordCount = static::resolveSelectedRecordCountByMassActionId($actionId, $dataProvider, array());
848  $model = $this->processMassAction(
849  $pageSize,
850  $selectedRecordCount,
851  $pageView,
852  $model,
853  $title,
854  $actionId,
855  $dataProvider
856  );
857  $massActionView = $this->makeMassActionView(
858  $model,
859  $activeAttributes,
860  $selectedRecordCount,
861  $title,
862  $actionId,
863  $useModuleClassNameForItemLabel
864  );
866  $this, $massActionView));
867  echo $view->render();
868  }
869 
870  protected function processMassAction($pageSize, $selectedRecordCount, $pageViewClassName, $listModel, $title,
871  $actionId, $dataProvider = null)
872  {
873  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
874  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
875  $postSelectedRecordCount = Yii::app()->request->getPost('selectedRecordCount');
876  $modelClassName = get_class($listModel);
877  $postModelClassName = Yii::app()->request->getPost($modelClassName);
878  if (isset($postSelectedRecordCount) || isset($postModelClassName))
879  {
880  $page = static::resolvePageValueForMassAction($modelClassName);
881  $insufficientPermissionSkipSavingUtil = static::resolveInsufficientPermissionSkipSavingUtilByMassActionId($actionId);
882  $start = ($selectedRecordCount > $pageSize)? 1: $selectedRecordCount;
883  $skipCount = ($selectedRecordCount > $pageSize)? null: 0;
884  $massActionSuccessful = static::processModelsForMassAction($listModel,
885  $modelClassName,
886  $selectedRecordCount,
887  $dataProvider,
888  $page,
889  $pageSize,
890  $insufficientPermissionSkipSavingUtil,
891  $postModelClassName,
892  $actionId);
893  if ($massActionSuccessful)
894  {
895  $progressView = $this->makeMassActionProgressView(
896  $listModel,
897  1,
898  $selectedRecordCount,
899  $start,
900  $pageSize,
901  $title,
902  $skipCount,
903  $actionId);
904  if ($selectedRecordCount > $pageSize)
905  {
906  $view = new $pageViewClassName(
908  $this, $progressView));
909  echo $view->render();
910  }
911  else
912  {
913  $refreshScript = $progressView->renderRefreshScript();
914  Yii::app()->user->setFlash('notification', $refreshScript['message']);
915  $this->redirect($this->resolveReturnUrlForMassAction());
916  }
917  Yii::app()->end(0, false);
918  }
919  }
920  return $listModel;
921  }
922 
923  protected static function processModelsForMassAction($model, $modelClassName, $selectedRecordCount, $dataProvider,
924  $page, $pageSize, $insufficientPermissionSkipSavingUtil,
925  $postModelClassName, $actionId)
926  {
927  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
928  $doMassActionFunctionName = 'processModelsForMassActionWithoutScoring';
929  $doMassActionFunctionArguments = array(
930  $modelClassName,
931  $selectedRecordCount,
932  $dataProvider,
933  $page,
934  $pageSize,
935  $insufficientPermissionSkipSavingUtil,
936  $actionId
937  );
938  if (MassActionUtil::isMassEditLikeAction($actionId) && !MassActionUtil::isMassProgressLikeAction($actionId))
939  {
940  $doMassActionFunctionName = 'processModelsForMassEditAction';
941  array_unshift($doMassActionFunctionArguments, $postModelClassName, $model);
942  }
943  $doMassActionFunctionName = 'static::' . $doMassActionFunctionName;
944  return call_user_func_array($doMassActionFunctionName, $doMassActionFunctionArguments);
945  }
946 
947  protected static function processModelsForMassActionWithoutScoring($modelClassName, $selectedRecordCount, $dataProvider,
948  $page, $pageSize, $insufficientPermissionSkipSavingUtil, $actionId)
949  {
950  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
951  $returnValue = false;
952  static::toggleMuteScoringModelValueByMassActionId($actionId, true);
953  $modelsToProcess = static::getModelsToUpdate($modelClassName, $dataProvider, $selectedRecordCount, $page, $pageSize);
954  $modelPermission = static::resolvePermissionOnSecurableItemByMassActionId($actionId);
955  foreach ($modelsToProcess as $modelToProcess)
956  {
957  if (ControllerSecurityUtil::doesCurrentUserHavePermissionOnSecurableItem($modelToProcess, $modelPermission))
958  {
959  $function = 'processModelFor' . static::resolveMassActionId($actionId, true);
960  $returnValue = static::$function($modelToProcess);
961  }
962  else
963  {
964  $insufficientPermissionSkipSavingUtil::setByModelIdAndName($modelClassName,
965  $modelToProcess->id,
966  $modelToProcess->name);
967  }
968  }
969  static::toggleMuteScoringModelValueByMassActionId($actionId, false);
970  return $returnValue;
971  }
972 
973  protected static function processModelsForMassEditAction($postModelClassName, $model, $modelClassName, $selectedRecordCount, $dataProvider,
974  $page, $pageSize, $insufficientPermissionSkipSavingUtil, $actionId)
975  {
976  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
977  PostUtil::sanitizePostForSavingMassEdit($modelClassName);
978  //Generically test that the changes are valid before attempting to save on each model.
979  $sanitizedPostData = PostUtil::sanitizePostByDesignerTypeForSavingModel(new $modelClassName(false), $postModelClassName);
980  $sanitizedOwnerPostData = PostUtil::sanitizePostDataToJustHavingElementForSavingModel($sanitizedPostData, 'owner');
981  $sanitizedPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($sanitizedPostData, 'owner');
982  $postMassEdit = Yii::app()->request->getPost('MassEdit');
983  $massEditPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($postMassEdit, 'owner');
984  $model->setAttributes($sanitizedPostDataWithoutOwner);
985  if ($model->validate(array_keys($massEditPostDataWithoutOwner)))
986  {
987  $passedOwnerValidation = true;
988  if ($sanitizedOwnerPostData != null)
989  {
990  $model->setAttributes($sanitizedOwnerPostData);
991  $passedOwnerValidation = $model->validate(array('owner'));
992  }
993  if ($passedOwnerValidation)
994  {
996  Yii::app()->gameHelper->triggerMassEditEvent($modelClassName);
997  return static::processModelsForMassActionWithoutScoring($modelClassName, $selectedRecordCount, $dataProvider,
998  $page, $pageSize, $insufficientPermissionSkipSavingUtil, $actionId);
999  }
1000  }
1001  return false;
1002  }
1003 
1004  protected function makeMassActionView(
1005  $model,
1006  $activeAttributes,
1007  $selectedRecordCount,
1008  $title,
1009  $actionId,
1010  $useModuleClassNameForItemLabel = true)
1011  {
1012  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1013  $moduleName = $this->getModule()->getPluralCamelCasedName();
1014  $moduleClassName = $moduleName . 'Module';
1015  $alertMessage = static::resolveMassActionAlertMessage(get_class($model), $actionId);
1016  $title = static::resolveTitleByMassActionId($actionId) . ': ' . $title;
1017  $massActionViewClassName = static::resolveViewIdByMassActionId($actionId, false, $moduleName);
1018  $view = new $massActionViewClassName(
1019  $this->getId(),
1020  $this->getModule()->getId(),
1021  $model,
1022  $activeAttributes,
1023  $selectedRecordCount,
1024  $title,
1025  $alertMessage,
1026  $moduleClassName,
1027  $useModuleClassNameForItemLabel);
1028  return $view;
1029  }
1030 
1031  protected function processMassActionProgress(
1032  $listModel,
1033  $pageSize,
1034  $title,
1035  $actionId,
1036  $dataProvider = null)
1037  {
1038  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1039  assert('$dataProvider == null || $dataProvider instanceof CDataProvider');
1040  $modelClassName = get_class($listModel);
1041  $startPage = static::resolvePageValueForMassAction($modelClassName);
1042  $postData = static::resolvePostDataByMassActionId($actionId, $modelClassName);
1043  $postModelClassName = Yii::app()->request->getPost($modelClassName);
1044  $pageVariableName = $modelClassName . '_page';
1045  $selectedRecordCount = static::resolveSelectedRecordCountByMassActionId($actionId, $dataProvider, $postData);
1046  $insufficientPermissionSkipSavingUtil = static::resolveInsufficientPermissionSkipSavingUtilByMassActionId($actionId);
1047  static::processModelsForMassAction($listModel,
1048  $modelClassName,
1049  $selectedRecordCount,
1050  $dataProvider,
1051  $startPage,
1052  $pageSize,
1053  $insufficientPermissionSkipSavingUtil,
1054  $postModelClassName,
1055  $actionId);
1056  $view = $this->makeMassActionProgressView(
1057  $listModel,
1058  $startPage,
1059  $selectedRecordCount,
1060  static::getMassActionProgressStartFromGet($pageVariableName, $pageSize),
1061  $pageSize,
1062  $title,
1063  $insufficientPermissionSkipSavingUtil::getCount($modelClassName),
1064  $actionId);
1065  echo $view->renderRefreshJSONScript();
1066  }
1067 
1068  protected function makeMassActionProgressView(
1069  $model,
1070  $page,
1071  $selectedRecordCount,
1072  $start,
1073  $pageSize,
1074  $title,
1075  $skipCount,
1076  $actionId)
1077  {
1078  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1079  assert('$skipCount == null || is_int($skipCount)');
1080  $massActionProgressActionName = static::resolveProgressActionId($actionId);
1081  $progressViewClassName = static::resolveViewIdByMassActionId($actionId, true);
1082  $params = $this->resolveParamsForMassProgressView();
1083  return new $progressViewClassName(
1084  $this->getId(),
1085  $this->getModule()->getId(),
1086  $model,
1087  $selectedRecordCount,
1088  $start,
1089  $pageSize,
1090  $page,
1091  $massActionProgressActionName,
1092  $title,
1093  $skipCount,
1094  $params
1095  );
1096  }
1097 
1098  protected static function resolvePostDataByMassActionId($actionId, $modelClassName = null)
1099  {
1100  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1101  if (MassActionUtil::isMassEditLikeAction($actionId))
1102  {
1103  PostUtil::sanitizePostForSavingMassEdit($modelClassName);
1104  }
1105  return PostUtil::getData();
1106  }
1107 
1108  protected static function resolveSelectedRecordCountByMassActionId($actionId, $dataProvider = null, $postData = array())
1109  {
1110  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1111  $selectedRecordCount = static::getSelectedRecordCountByResolvingSelectAllFromGet($dataProvider);
1112  if (MassActionUtil::isMassProgressLikeAction($actionId) && !MassActionUtil::isMassEditLikeAction($actionId))
1113  {
1114  $selectedRecordCount = ArrayUtil::getArrayValue($postData, 'selectedRecordCount');
1115  }
1116  return $selectedRecordCount;
1117  }
1118 
1119  protected static function resolveMassActionAlertMessage($postVariableName, $actionId)
1120  {
1121  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1122  $actionId = static::resolveMassActionId($actionId, true);
1123  $alertMessageHandler = 'resolve' . $actionId . 'AlertMessage';
1124  return (method_exists(get_called_class(), $alertMessageHandler))?
1125  static::$alertMessageHandler($postVariableName) : null;
1126  }
1127 
1128  protected static function resolvePageSizeByMassActionId($actionId)
1129  {
1130  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1131  $type = 'massEditProgressPageSize';
1132  if (MassActionUtil::isMassDeleteLikeAction($actionId))
1133  {
1134  $type = 'massDeleteProgressPageSize';
1135  }
1136  elseif (MassActionUtil::isMassSubscribeLikeAction($actionId))
1137  {
1138  $type = 'massSubscribeProgressPageSize';
1139  }
1140  return Yii::app()->pagination->resolveActiveForCurrentUserByType($type);
1141  }
1142 
1143  protected static function toggleMuteScoringModelValueByMassActionId($actionId, $mute = true)
1144  {
1145  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1146  $toggle = ($mute)? 'mute' : 'unmute';
1147  $function = (MassActionUtil::isMassDeleteLikeAction($actionId))? 'Delete' : 'Save';
1148  $function = $toggle . 'ScoringModelsOn' . $function;
1149  Yii::app()->gameHelper->$function();
1150  }
1151 
1152  protected static function resolvePermissionOnSecurableItemByMassActionId($actionId)
1153  {
1154  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1155  return (MassActionUtil::isMassDeleteLikeAction($actionId)) ? Permission::DELETE : Permission::WRITE;
1156  }
1157 
1158  protected static function processModelForMassDelete(& $model)
1159  {
1160  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1161  if (!$model->delete(false))
1162  {
1163  throw new FailedToDeleteModelException();
1164  }
1165  else
1166  {
1167  return true;
1168  }
1169  }
1170 
1171  protected static function resolveOffsetForDataProvider($dataProvider, $actionId)
1172  {
1173  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1174  // if we are doing something for massDelete we want offset to be 0 always because rows keep getting deleted.
1175  if (isset($dataProvider) && MassActionUtil::isMassDeleteLikeAction($actionId)) // works for massDelete and massDeleteProgress
1176  {
1177  $dataProvider->setOffset(0);
1178  }
1179  }
1180 
1181  protected static function processModelForMassEdit(& $model)
1182  {
1183  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1184  $postModelClassName = Yii::app()->request->getPost(get_class($model));
1185  $sanitizedPostData = PostUtil::sanitizePostByDesignerTypeForSavingModel($model, $postModelClassName);
1186  $sanitizedOwnerPostData = PostUtil::sanitizePostDataToJustHavingElementForSavingModel($sanitizedPostData, 'owner');
1187  $sanitizedPostDataWithoutOwner = PostUtil::removeElementFromPostDataForSavingModel($sanitizedPostData, 'owner');
1188  $model->setAttributes($sanitizedPostDataWithoutOwner);
1189  if ($sanitizedOwnerPostData != null)
1190  {
1191  $model->setAttributes($sanitizedOwnerPostData);
1192  }
1193  if (!$model->save(false))
1194  {
1195  throw new FailedToSaveModelException();
1196  }
1197  else
1198  {
1199  return true;
1200  }
1201  }
1202 
1203  protected static function resolveInsufficientPermissionSkipSavingUtilByMassActionId($actionId)
1204  {
1205  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1206  $insufficientPermissionSkipSavingUtil = 'MassEditInsufficientPermissionSkipSavingUtil';
1207  if (MassActionUtil::isMassDeleteLikeAction($actionId))
1208  {
1209  $insufficientPermissionSkipSavingUtil = 'MassDeleteInsufficientPermissionSkipSavingUtil';
1210  }
1211  return $insufficientPermissionSkipSavingUtil;
1212  }
1213 
1214  protected static function resolveProgressActionId($actionId)
1215  {
1216  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1217  $actionId = static::resolveMassActionId($actionId, false);
1218  $actionId .= 'Progress';
1219  $actionId = (MassActionUtil::isMassEditLikeAction($actionId))? $actionId . 'Save' : $actionId;
1220  return $actionId;
1221  }
1222 
1223  protected function resolveParamsForMassProgressView()
1224  {
1225  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1226  return array(
1227  'insufficientPermissionSkipSavingUtil' => null,
1228  'returnUrl' => $this->resolveReturnUrlForMassAction(),
1229  'returnMessage' => null,
1230  );
1231  }
1232 
1233  protected static function resolveMassActionId($actionId, $capitalizeFirst = true)
1234  {
1235  // TODO: @Shoaibi/@Jason: Low: Candidate for MassActionController
1236  $actionId = str_replace(array('Progress', 'Save'), '', $actionId);
1237  return ($capitalizeFirst)? ucfirst($actionId) : $actionId;
1238  }
1239 
1240  protected function resolveActiveElementTypeForKanbanBoard(SearchForm $searchForm)
1241  {
1242  if ($searchForm->getKanbanBoard()->getIsActive())
1243  {
1244  return ListViewTypesToggleLinkActionElement::TYPE_KANBAN_BOARD;
1245  }
1246  else
1247  {
1248  return ListViewTypesToggleLinkActionElement::TYPE_NON_KANBAN_BOARD;
1249  }
1250  }
1251 
1257  protected function resolveActiveElementTypeForKanbanBoardInDetailView($detailsAndRelationsView)
1258  {
1259  $detailsAndRelationsView = $this->resolveKanbanBoardIsActiveByGetForDetailsView($detailsAndRelationsView);
1260 
1261  if ($detailsAndRelationsView->getKanbanBoard()->getIsActive())
1262  {
1263  return DetailsAndRelationsViewTypesToggleLinkActionElement::TYPE_KANBAN_BOARD;
1264  }
1265  else
1266  {
1267  return DetailsAndRelationsViewTypesToggleLinkActionElement::TYPE_NON_KANBAN_BOARD;
1268  }
1269  }
1270 
1274  protected function resolveKanbanBoardIsActiveByGetForDetailsView($detailsAndRelationsView)
1275  {
1276  if (isset($_GET['kanbanBoard']) && $_GET['kanbanBoard'] && !Yii::app()->userInterface->isMobile())
1277  {
1278  $detailsAndRelationsView->getKanbanBoard()->setIsActive();
1279  }
1280  elseif (isset($_GET['kanbanBoard']) && !$_GET['kanbanBoard'])
1281  {
1282  $detailsAndRelationsView->getKanbanBoard()->setIsNotActive();
1283  $detailsAndRelationsView->getKanbanBoard()->setClearSticky();
1284  }
1285  elseif (Yii::app()->userInterface->isMobile())
1286  {
1287  $detailsAndRelationsView->getKanbanBoard()->setIsNotActive();
1288  }
1289 
1290  return $detailsAndRelationsView;
1291  }
1292 
1296  protected function beforeRedirect($model)
1297  {
1298  }
1299 
1307  protected function makeSearchAndListView($searchModel, $moduleName, $dataProvider)
1308  {
1309  $listModel = $searchModel->getModel();
1310  return new SearchAndListView(
1311  $this->getId(),
1312  $this->getModule()->getId(),
1313  $searchModel,
1314  $listModel,
1315  $moduleName,
1316  $dataProvider,
1318  );
1319  }
1320  }
1321 ?>
static resolveSelectedIdsFromGet()
Definition: GetUtil.php:65
getListAttributesSelector()
Definition: SearchForm.php:600
resolveActiveElementTypeForKanbanBoardInDetailView($detailsAndRelationsView)
resolveKanbanBoardIsActiveByGetForDetailsView($detailsAndRelationsView)
processMassEditProgressSave($modelClassName, $pageSize, $title, $dataProvider=null)
static doesCurrentUserHavePermissionOnSecurableItem($securableItem, $permissionToCheck)
static getArrayValue($array, $element, $defaultValue=null)
Definition: ArrayUtil.php:45
static setDataByKeyAndDataCollection($key, SearchAttributesDataCollection $dataCollection, $stickyData)
getMassDeleteProgressStartFromGet($getVariableName, $pageSize)
Definition: Controller.php:367
attemptToSaveModelFromPost($model, $redirectUrlParams=null, $redirect=true, $returnOnValidate=false)
makeRedBeanDataProviderByDataCollection($searchModel, $pageSize, $stateMetadataAdapterClassName=null, $dataCollection=null)
Definition: Controller.php:83
processMassEdit($pageSize, $activeAttributes, $selectedRecordCount, $pageViewClassName, $listModel, $title, $dataProvider=null)
saveMassEdit($modelClassName, $postVariableName, $selectedRecordCount, $dataProvider, $page, $pageSize)
static resolveSearchFormByStickySortData(array $getData, DynamicSearchForm $searchForm, $stickyData)
getModelsToDelete($modelClassName, $dataProvider, $selectedRecordCount, $page, $pageSize)
Definition: Controller.php:434
static resolveSearchFormByData(array $data, DynamicSearchForm $searchForm)
static removeElementFromPostDataForSavingModel($sanitizedPostData, $elementName)
Definition: PostUtil.php:116
processMassDelete($pageSize, $activeAttributes, $selectedRecordCount, $pageViewClassName, $listModel, $title, $dataProvider=null, $redirectUrl=null)
static getUncapitalizedRecordLabelByCount($count)
Definition: LabelUtil.php:46
static makeStandardViewForCurrentUser(CController $controller, View $containedView)
static resolveSearchFormByStickyDataAndModel($stickyData, SavedDynamicSearchForm $model)
static setByModelIdAndName($modelClassName, $modelId, $modelName)
static getModelAndCatchNotFoundAndDisplayError($modelClassName, $id)
makeSearchAndListView($searchModel, $moduleName, $dataProvider)
static sanitizePostDataToJustHavingElementForSavingModel($sanitizedPostData, $elementName)
Definition: PostUtil.php:106
static sanitizePostByDesignerTypeForSavingModel($model, $postData)
Definition: PostUtil.php:94
Generated on Sat Mar 28 2020 07:10:45