Overview

Namespaces

  • Cron
  • None

Classes

  • _HtmlGrid_TableOut
  • _TransactionModel_RawSaveOperation
  • AccessControlComponent
  • AccessControlHelper
  • ActionListHelper
  • ActiveDirectoryUtils
  • AddCurrentPidToSchedulingShellCallLogs
  • AnonymousFunctionOperation
  • ArrayUtil
  • AssociationIntegrityBehavior
  • AtomicOperation
  • AuthenticationComponent
  • AuthenticationController
  • AuthenticationUser
  • AutocompleteDatasourceComponent
  • BaseModelComponent
  • Basics
  • CakeLayersHelper
  • CheckAndRunShell
  • ClassSearcher
  • CommandLineUtil
  • CommonValidationBehavior
  • ConfigurableShellCallsSchedulingTask
  • ConfigurationKey
  • ConfigurationKeys
  • ConfigurationKeysController
  • Context
  • ContextComponent
  • ContextHelper
  • Contexts
  • ControllerInspector
  • ControllerMenuHelper
  • CreateJournalingTables
  • CreateTableConfigurationKeys
  • CreateTableSchedulingConfigurableShellCalls
  • CreateTableSchedulingShellCallLogs
  • CreateTableSettedConfigurationKeys
  • CreateTableUserResetPasswordRequests
  • CreateTableUsers
  • CronSchedulingInstaller
  • CronValidationBehavior
  • CssBox
  • CssController
  • CssProperties
  • CssShell
  • CsvUtil
  • CustomDataModel
  • DatasourceDumperManager
  • DateTimeInput
  • DependencyShell
  • DetailHelper
  • DumperShell
  • ExtendedFieldsAccessControl
  • ExtendedFieldSet
  • ExtendedFieldSetHelper
  • ExtendedFieldsParser
  • ExtendedFormHelper
  • ExtendedHasManyAppModel
  • ExtendedOperationsBehavior
  • FieldDefinition
  • FieldRowDefinition
  • FieldSetDefinition
  • FieldSetLayoutHelper
  • FileOperations
  • FileOperations_Rename
  • FileOperations_SymLink
  • FileOperations_Touch
  • FileOperations_Unlink
  • FileSystem
  • FixConfigurationKeysPrimaryKey
  • FixSettedConfigurationKeysPrimaryKey
  • HasManyUtilsBehavior
  • HtmlDocument
  • HtmlGrid
  • HtmlGrid_Cell
  • HttpClient
  • HttpResponse
  • ImapClient
  • ImapMailBox
  • ImapParserShell
  • IncludePath
  • InputMasked
  • InputSearchable
  • InputsOnSubmit
  • InstallShell
  • JenkinsBuildShell
  • Journal
  • JournalDetail
  • JournalizedBehavior
  • JsonResponseComponent
  • LayoutsHelper
  • Ldap
  • LdapUtils
  • ListFieldSet
  • ListFieldSetHelper
  • ListsHelper
  • MailParser
  • Make
  • MenuHelper
  • MigrationAllPluginsShell
  • ModelOperations
  • ModelOperations_Delete
  • ModelOperations_Save
  • ModelTraverser
  • MysqlDumper
  • OpenLdapUtils
  • PaginatorUtilComponent
  • PaginatorUtilComponentFilter
  • PaginatorUtilHelper
  • Plugin
  • PluginManager
  • Reflections
  • RenameEnabledToActiveFromUsersTable
  • RunShellCallShell
  • ScaffoldUtilComponent
  • ScaffoldUtilHelper
  • Scheduling
  • SchedulingConfigurableShellCall
  • SchedulingConfigurableShellCallsController
  • SchedulingShellCallLog
  • SchedulingShellCallLogsController
  • SettedConfigurationKey
  • StuffreposPluginsRename
  • TimeZoneBehavior
  • TransactionModel
  • TransactionOperation
  • Translator
  • TranslatorShell
  • User
  • UserAuthenticationComponent
  • UserChangePassword
  • UserResetPassword
  • UserResetPasswordRequest
  • UserResetPasswordRequestSubmission
  • UsersController
  • ViewUtilHelper

Interfaces

  • AccessControlFilter
  • CommitableOperation
  • DatasourceDumper
  • MakeListener
  • SchedulingInstaller
  • TasksObject
  • UndoableOperation

Exceptions

  • LdapObjectNotWritableException
  • ModelTraverserException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: App::uses('ArrayUtil', 'Base.Lib');
  4: App::uses('AppHelper', 'View/Helper');
  5: App::uses('ControllerInspector', 'Base.Lib');
  6: App::uses('ActionListHelper', 'Widgets.View/Helper');
  7: 
  8: /**
  9:  * Monta menus automaticamente baseados em convenções ou configurações
 10:  * por controller.
 11:  */
 12: class ControllerMenuHelper extends AppHelper {
 13: 
 14:     public $helpers = array(
 15:         'Html',
 16:         'AccessControl.AccessControl',
 17:         'Base.CakeLayers',
 18:         'Widgets.ActionList',
 19:     );
 20: 
 21:     /**
 22:      * @var array
 23:      */
 24:     private $defaultActions = array(
 25:         array(
 26:             'url' => array('action' => 'index'),
 27:             'hasId' => false,
 28:             'format' => 'Listar %s',
 29:             'plural' => true
 30:         ),
 31:         array(
 32:             'url' => array('action' => 'add'),
 33:             'hasId' => false,
 34:             'format' => 'Novo(a) %s',
 35:             'plural' => false
 36:         ),
 37:         array('url' => array('action' => 'view'), 'hasId' => true, 'format' => 'Visualizar %s', 'plural' => false),
 38:         array('url' => array('action' => 'edit'), 'hasId' => true, 'format' => 'Editar %s', 'plural' => false),
 39:         array('url' => array('action' => 'delete'), 'hasId' => true, 'format' => 'Remover %s', 'plural' => false,
 40:             'question' => 'Tem certeza de que deseja remover?', 'post' => true)
 41:     );
 42: 
 43:     /**
 44:      * @var array
 45:      */
 46:     public $settings = array(
 47:         'listLayoutBeforeAll' => '',
 48:         'listLayoutAfterAll' => '',
 49:         'listLayoutBeforeEach' => '',
 50:         'listLayoutAfterEach' => '',
 51:         'tableLayoutBeforeAll' => '',
 52:         'tableLayoutAfterAll' => '',
 53:         'tableLayoutBeforeEach' => '',
 54:         'tableLayoutAfterEach' => '',
 55:         'layout' => ActionListHelper::LAYOUT_LIST,
 56:         'skipActions' => array(),
 57:         'controller' => null,
 58:         'id' => null,
 59:         'debug' => false,
 60:     );
 61: 
 62:     /**
 63:      * @var array
 64:      */
 65:     private $moduleMenuDefaultOptions = array(
 66:         'shortFormat' => false,
 67:         'skipNoRequiredIdActions' => false,
 68:         'layout' => ActionListHelper::LAYOUT_LIST,
 69:     );
 70: 
 71:     /**
 72:      * @var array
 73:      */
 74:     private $instanceMenuDefaultOptions = array(
 75:         'shortFormat' => true,
 76:         'skipNoRequiredIdActions' => true,
 77:         'layout' => ActionListHelper::LAYOUT_TABLE,
 78:     );
 79: 
 80:     /**
 81:      * 
 82:      * @param array $options
 83:      * @return string
 84:      */
 85:     public function moduleMenu($options = array()) {
 86:         $options = $this->_buildOptions($this->moduleMenuDefaultOptions, $options);
 87:         return $this->_menuByOptions(
 88:                         $options
 89:         );
 90:     }
 91: 
 92:     /**
 93:      * 
 94:      * @param array $instance
 95:      * @param array $options
 96:      * @return string
 97:      */
 98:     public function instanceMenu($instance, $options = array()) {
 99:         $options = $this->_buildOptions($this->instanceMenuDefaultOptions, $options);
100:         $options['id'] = $this->_getInstanceId($instance, $options);
101:         return $this->_menuByOptions($options);
102:     }
103: 
104:     /**
105:      * 
106:      * @param array $defaultOptions
107:      * @param array $userOptions
108:      * @return array
109:      */
110:     private function _buildOptions($defaultOptions, $userOptions) {
111:         $ret = array_merge($this->settings, $defaultOptions, $userOptions);
112:         $ret['_currentController'] = $this->CakeLayers->getController($this->params['controller']);
113:         $ret['_targetController'] = $this->CakeLayers->getController($ret['controller']);
114:         $ret['_targetObjectModel'] = $ret['_targetController']->{$ret['_targetController']->modelClass};
115:         return $ret;
116:     }
117: 
118:     /**
119:      * 
120:      * @param array $options
121:      * @return string
122:      */
123:     private function _menuByOptions($options) {
124:         $controllerActions = $this->_navigableActions(
125:                 $this->_moduleActions($options), $options
126:         );
127:         $actions = array();
128:         foreach ($controllerActions as $controllerAction) {            
129:             $actions[] = array(
130:                 'caption' => $this->_getTitle($controllerAction, $options),
131:                 'post' => array_key_exists('post', $controllerAction) && $controllerAction['post'],
132:                 'url' => $this->_buildActionUrl($controllerAction, $options),
133:                 'question' => array_key_exists('question', $controllerAction) ? $controllerAction['question'] : false,
134:             );
135:         }
136:         return $this->ActionList->actionList($actions, $options);
137:     }
138: 
139:     /**
140:      * 
141:      * @param array $instance
142:      * @param array $options
143:      * @return mixed
144:      */
145:     private function _getInstanceId($instance, $options) {
146:         if (empty($options['model'])) {
147:             $model = $options['_targetController']->{
148:                     $options['_targetController']->modelClass
149:                     };
150:         } else {
151:             $model = $this->CakeLayers->getModel($options['model']);
152:         }
153:         return $instance[$model->alias][$model->primaryKey];
154:     }
155: 
156:     private function _navigableActions($actions, $options) {
157:         $navigableActions = array();
158:         foreach ($actions as $action) {
159:             if ($this->_isNavigable($action, $options)) {
160:                 $navigableActions[] = $action;
161:             }
162:         }
163:         return $navigableActions;
164:     }
165: 
166:     private function _moduleActions($options) {
167:         $groups = array($this->defaultActions);
168:         if (!empty($options['moduleActions'])) {
169:             $groups[] = $options['moduleActions'];
170:         }
171:         if (!empty($options['_targetController']->moduleActions)) {
172:             $groups[] = $options['_targetController']->moduleActions;
173:         }
174: 
175:         $added = array();
176: 
177:         foreach ($groups as $group) {
178:             foreach ($group as $action) {
179:                 $url = $this->_extractActionUrl($action, $options);
180:                 $actionPath = $url['controller'] . '/' . $url['action'];
181:                 $added[$actionPath] = $action;
182:             }
183:         }
184: 
185:         return $added;
186:     }
187: 
188:     public function setDefaultOption($key, $value) {
189:         $this->defaultOptions[$key] = $value;
190:     }
191: 
192:     private function _isNavigable($targetAction, $options) {
193:         $message = $this->_checkNavigable($targetAction, $options);
194:         if ($message == false) {
195:             return true;
196:         } else {
197:             if ($options['debug']) {
198:                 debug(array('notNavigable' => compact('message', 'targetAction')));
199:             }
200: 
201:             return false;
202:         }
203:     }
204: 
205:     private function _checkNavigable($targetAction, $options) {
206:         $actionUrl = $this->_extractActionUrl($targetAction, $options);
207: 
208:         //Acesso negado
209:         if (!$this->AccessControl->hasAccessByUrl($this->_buildActionUrl($targetAction, $options))) {
210:             return __d('widgets','Access denied.');
211:         }
212: 
213:         $currentUrl = $this->_extractCurrentUrl($options);
214: 
215:         // Mesma action
216:         if (($currentUrl['controller'] == $actionUrl['controller']) &&
217:                 ($currentUrl['action'] == $actionUrl['action'])) {
218:             return __d('widgets','Same controller/action.');
219:         }
220: 
221:         // Formato curto
222:         if ($options['shortFormat'] && !empty($targetAction['skipOnShort'])) {
223:             return __d('widgets','Skip on short format menu.');
224:         }
225: 
226:         // Não tem ID requerido
227:         if ($targetAction['hasId'] && $actionUrl['id'] == null) {
228:             return __d('widgets','Has not required id.');
229:         }
230: 
231:         // Não necessita de ID e opção para excluir
232:         if (!$targetAction['hasId'] && $options['skipNoRequiredIdActions']) {
233:             return __d('widgets','Skip no required id actions.');
234:         }
235: 
236:         // Negado pelo controller
237:         if ($this->_deniedAction($actionUrl, $options)) {
238:             return __d('widgets','Denied by controller.');
239:         }
240: 
241:         // Registrado na opção skipActions
242:         foreach ($options['skipActions'] as $skipActionUrl) {
243:             if ($this->_isUrlEquals($this->_parseUrl($skipActionUrl), $actionUrl)) {
244:                 return __d('widgets','Action skipped.');
245:             }
246:         }
247: 
248:         // Método próprio no controller
249:         if (!$this->_isNavigableControllerMethod($targetAction, $options)) {
250:             return __d('widgets','Navigable method returned false.');
251:         }
252: 
253:         return false;
254:     }
255: 
256:     private function _deniedAction($actionUrl, $options) {
257:         if ($actionUrl['controller'] == $this->_getTargetControllerUri($options)) {
258:             return !ControllerInspector::actionExists($options['_targetController'], $actionUrl['action']) ||
259:                     (isset($options['_targetController']->notModuleActions) &&
260:                     array_search($actionUrl['action'], $options['_targetController']->notModuleActions) !== false);
261:         } else {
262:             return false;
263:         }
264:     }
265: 
266:     private function _buildActionUrl($targetAction, $options) {
267:         $actionUrl = $this->_extractActionUrl($targetAction, $options);
268: 
269:         $url = '';
270: 
271:         if ($actionUrl['plugin']) {
272:             $url .= "/{$actionUrl['plugin']}";
273:         }
274: 
275:         $url .= "/{$actionUrl['controller']}/{$actionUrl['action']}";
276: 
277:         if ($targetAction['hasId']) {
278:             if (isset($targetAction['namedParam']) && $targetAction['namedParam']) {
279:                 $url .= "/{$targetAction['namedParam']}:{$actionUrl['id']}";
280:             } else {
281:                 $url .= "/{$actionUrl['id']}";
282:             }
283:         }
284:         $current = Router::parse($this->request->url);
285:         foreach($current['named'] as $key => $value) {
286:             $url .= "/$key:$value";
287:         }
288:         return $url;
289:     }
290: 
291:     private function _getTitle($action, $options) {
292:         $actionUrl = $this->_extractActionUrl($action, $options);
293: 
294:         if ($options['shortFormat']) {
295:             return trim(sprintf($action['format'], ''));
296:         } else {
297:             $title = Inflector::singularize($actionUrl['controller']);
298:             $title = !empty($action['plural']) ? $actionUrl['controller'] : Inflector::singularize($actionUrl['controller']);
299:             $title = Inflector::humanize($title);
300:             $title = str_replace(' ', '', $title);
301:             return trim(sprintf($action['format'], __d('widgets',$title)));
302:         }
303:     }
304: 
305:     private function _extractCurrentUrl($options) {
306:         $controller = $this->params['controller'];
307:         $action = isset($this->params['action']) ? $this->params['action'] : 'index';
308:         $id = isset($this->params['pass'][0]) ? $this->params['pass'][0] : null;
309: 
310:         // Resolve add_or_edit
311:         if ($action == 'add_or_edit') {
312:             $action = empty($id) ? 'add' : 'edit';
313:         }
314: 
315:         return array(
316:             'controller' => $controller,
317:             'action' => $action,
318:             'id' => ($options['id'] ? $options['id'] : $id )
319:         );
320:     }
321: 
322:     private function _getTargetControllerUri($options) {
323:         return Inflector::underscore($options['_targetController']->name);
324:     }
325: 
326:     private function _getTargetControllerPluginUri($options) {
327:         return empty($options['_targetController']->plugin) ? null : Inflector::underscore($options['_targetController']->plugin);
328:     }
329: 
330:     private function _extractActionUrl($action, $options) {
331:         $actionUrl = $this->_parseUrl($action['url']);
332:         return array(
333:             'plugin' => $actionUrl['plugin'] ? $actionUrl['plugin'] : $this->_getTargetControllerPluginUri($options),
334:             'controller' => $actionUrl['controller'] ? $actionUrl['controller'] : $this->_getTargetControllerUri($options),
335:             'action' => isset($actionUrl['action']) ? $actionUrl['action'] : 'index',
336:             'id' => $this->_extractActionId($action, $options)
337:         );
338:     }
339: 
340:     private function _parseUrl($url) {
341:         if (is_string($url)) {
342:             $url = Router::parse($url);
343:         }
344: 
345:         $url['plugin'] = isset($url['plugin']) ? $url['plugin'] : null;
346:         $url['controller'] = isset($url['controller']) ? $url['controller'] : null;
347:         $url['action'] = isset($url['action']) ? $url['action'] : 'index';
348: 
349:         return $url;
350:     }
351: 
352:     private function _extractActionId($action, $options) {
353:         $currentUrl = $this->_extractCurrentUrl($options);
354: 
355:         if ($action['hasId']) {
356:             if (isset($action['field']) && $action['field']) {
357:                 $obj = $this->_getTargetControllerObject($currentUrl['id'], $options);
358:                 $model = $options['_targetObjectModel'];
359:                 return $obj && $model ?
360:                         $this->_getObjectFieldValue($model->name, $obj, $action['field']) :
361:                         $this->_getCurrentActionFieldValue($action['field']);
362:             } else {
363:                 return $currentUrl['id'];
364:             }
365:         } else {
366:             return null;
367:         }
368:     }
369: 
370:     private function _getTargetControllerObject($primaryKeyValue, $options) {
371:         $model = $options['_targetObjectModel'];
372:         return $model->find(
373:                         'first', array(
374:                     'conditions' => array(
375:                         "{$model->name}.{$model->primaryKey}" => $primaryKeyValue
376:                     )
377:                         )
378:         );
379:     }
380: 
381:     private function _getObjectFieldValue($model, $object, $field) {
382:         return $this->CakeLayers->modelInstanceField($model, $object, $field);
383:     }
384: 
385:     private function _getCurrentActionFieldValue($field) {
386:         $parts = explode('.', $field);
387:         $underscoreParts = array();
388:         foreach ($parts as $part) {
389:             $underscoreParts[] = Inflector::underscore($part);
390:         }
391:         $field = implode('_', $underscoreParts);
392: 
393:         if (!empty($this->params['named'][$field])) {
394:             return $this->params['named'][$field];
395:         }
396:         if (count($parts) == 1) {
397:             $parts = array_merge(
398:                     $this->CakeLayers->getModel()->alias, $parts
399:             );
400:         }
401:         if (ArrayUtil::hasArrayIndex($this->data, $parts)) {
402:             return ArrayUtil::arrayIndex($this->data, $parts);
403:         }
404: 
405:         return null;
406:     }
407: 
408:     private function _isUrlEquals($url1, $url2) {
409:         return $url1['controller'] == $url2['controller']
410:                 && $url1['action'] == $url2['action'];
411:     }
412: 
413:     private function _isNavigableControllerMethod($targetAction, $options) {
414:         $actionUrl = $this->_extractActionUrl($targetAction, $options);
415:         $methodName = '__' . Inflector::variable("is_navigable_" . $actionUrl['action']);
416:         $controller = $this->CakeLayers->getController($actionUrl['controller']);
417: 
418:         if (method_exists($controller, $methodName)) {
419:             return call_user_func(array($controller, $methodName), array(
420:                         'options' => $options,
421:                         'currentUrl' => $this->_extractCurrentUrl($options),
422:                         'targetAction' => $targetAction,
423:                         'targetActionUrl' => $actionUrl,
424:                     ));
425:         } else {
426:             return true;
427:         }
428:     }
429: 
430: }
431: 
432: ?>
433: 
API documentation generated by ApiGen 2.8.0