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: class ModelTraverser {
  4: 
  5:     const CACHE_KEY = '_modelTraverserCache';
  6:     const FIND_LAST_INSTANCE = 'LastInstance';
  7:     const FIND_ALL = 'All';
  8:     const NODE_TYPE_SELF = 'self';
  9:     const NODE_TYPE_FIELD = 'field';
 10:     const NODE_TYPE_HAS_ONE = 'has_one';
 11:     const NODE_TYPE_HAS_MANY = 'has_many';
 12: 
 13:     public static function schema(Model $model, $path) {
 14:         try {
 15:             if (!is_array($path)) {
 16:                 $path = explode('.', $path);
 17:             }
 18: 
 19:             if (self::isField($model, $path[0])) {
 20:                 if (count($path) == 1) {
 21:                     return self::fieldSchema($model, $path[0]);
 22:                 } else {
 23:                     throw new Exception("Path continues, but reached a field.");
 24:                 }
 25:             } else if (self::isBelongsToAssociation($model, $path[0]) ||
 26:                     self::isHasOneAssociation($model, $path[0])) {
 27:                 return self::schema($model->{$path[0]}, self::pathPopFirst($path));
 28:             } else {
 29:                 throw new Exception("Term is not a field or association.");
 30:             }
 31:         } catch (Exception $ex) {
 32:             throw new ModelTraverserException($ex->getMessage(), compact('model','path'), $ex);
 33:         }
 34:     }
 35: 
 36:     /**
 37:      *
 38:      * @param Model $model
 39:      * @param array $row
 40:      * @param string|array $path
 41:      * @return type
 42:      */
 43:     public static function value(Model $model, $row, $path) {
 44:         $stack = self::find($model, $row, $path);
 45:         $top = self::_pathLastNode($stack);
 46:         return $top['value'];
 47:     }
 48: 
 49:     public static function displayValue(Model $model, $row, $path) {
 50:         $stack = self::find($model, $row, $path);
 51:         $top = self::_pathLastNode($stack);
 52:         $pathLastPart = self::_pathLastNode($path);
 53:         $association = self::oneToManyAssociationByForeignKey($top['model'], $pathLastPart);
 54:         if ($association) {            
 55:             array_pop($stack);
 56:             if (empty($stack)) {
 57:                 $subTop = array(
 58:                     'model' => $model,
 59:                     'value' => $row,
 60:                 );
 61:             }
 62:             else {
 63:                 $subTop = self::_pathLastNode($stack);
 64:             }
 65:             $subPath = array($association, $subTop['model']->{$association}->displayField);
 66:             return self::value(
 67:                             $subTop['model']
 68:                             , $subTop['value']
 69:                             , $subPath
 70:             );
 71:         } else {
 72:             return $top['value'];
 73:         }
 74:     }
 75: 
 76:     private static function oneToManyAssociationByForeignKey(Model $model, $foreignKey) {
 77:         foreach ($model->getAssociated() as $associationAlias => $type) {
 78:             switch ($type) {
 79:                 case 'belongsTo':
 80:                 case 'hasOne':
 81:                     if ($model->{$type}[$associationAlias]['foreignKey'] == $foreignKey) {
 82:                         return $associationAlias;
 83:                     }
 84:             }
 85:         }
 86: 
 87:         return false;
 88:     }
 89: 
 90:     public static function find(Model $model, $row, $path) {
 91:         try {
 92:             if (!is_array($path)) {
 93:                 $path = explode('.', $path);
 94:             }
 95: 
 96:             if (count($path) == 0) {
 97:                 throw new Exception("Path size is zero.");
 98:             }
 99:             if (!is_array($row)) {
100:                 throw new Exception('$row is not a array');
101:             }
102:             $currentModel = $model;
103:             $leftPath = $path;
104:             $stack = array();
105:             while (!empty($leftPath)) {
106:                 $currentNode = $leftPath[0];
107:                 $leftPath = self::pathPopFirst($leftPath);
108:                 $currentNodeType = self::_findCurrentNodeType($currentModel, $currentNode);
109:                 switch ($currentNodeType) {
110:                     case self::NODE_TYPE_FIELD:
111:                         $currentRow = self::_findField($currentModel, $row, $currentNode);
112:                         break;
113: 
114:                     case self::NODE_TYPE_SELF:
115:                         $currentRow = self::_findSelf($currentModel, $row, $currentNode);
116:                         break;
117: 
118:                     case self::NODE_TYPE_HAS_ONE:
119:                         $currentRow = self::_findHasOne($currentModel, $row, $currentNode);
120:                         $currentModel = $currentModel->{$currentNode};
121:                         break;
122: 
123:                     case self::NODE_TYPE_HAS_MANY:
124:                         $currentRow = self::_findHasMany($currentModel, $row, $currentNode);
125:                         $currentModel = $currentModel->{$currentNode};
126:                         break;
127: 
128:                     default:
129:                         $currentRow = new Exception("Current node type \"$currentNodeType\" not mapped");
130:                         break;
131:                 }
132:                 $stack[] = array(
133:                     'value' => $currentRow,
134:                     'model' => $currentModel,
135:                 );
136:             }
137:             return $stack;
138:         } catch (Exception $ex) {
139:             throw new ModelTraverserException($ex->getMessage(), compact('model', 'row', 'path', 'leftPath', 'stack', 'currentModel', 'currentRow', 'currentNode', 'currentNodeType'), $ex);
140:         }
141:     }
142: 
143:     private static function _findCurrentNodeType(\Model $model, $currentNode) {
144:         if (self::isField($model, $currentNode)) {
145:             return self::NODE_TYPE_FIELD;
146:         } else if ($model->alias == $currentNode) {
147:             return self::NODE_TYPE_SELF;
148:         } else if (self::isBelongsToAssociation($model, $currentNode) ||
149:                 self::isHasOneAssociation($model, $currentNode)) {
150:             return self::NODE_TYPE_HAS_ONE;
151:         } else if (self::isHasManyAssociation($model, $currentNode)) {
152:             return self::NODE_TYPE_HAS_MANY;
153:         } else {
154:             throw new Exception("Node \"{$currentNode}\" is not a field or association of \"{$model->name}\" (Alias: \"{$model->alias}\").");
155:         }
156:     }
157: 
158:     public static function _findField(Model $model, $row, $field, $required = true) {
159:         if (array_key_exists($model->alias, $row) && array_key_exists($field, $row[$model->alias])) {
160:             return $row[$model->alias][$field];
161:         } else if (array_key_exists($field, $row)) {
162:             return $row[$field];
163:         } else if (empty($row[$model->alias][$model->primaryKey])) {
164:             return null;
165:         } else {
166:             $findRow = $model->find('first', array(
167:                 'recursive' => -1,
168:                 'conditions' => array(
169:                     $model->alias . '.' . $model->primaryKey => $row[$model->alias][$model->primaryKey],
170:                 ),
171:             ));
172:             if (empty($findRow)) {
173:                 if ($required) {
174:                     throw new Exception("Row not found");
175:                 }
176:                 else {
177:                     return null;
178:                 }
179:             }
180:             if (array_key_exists($model->alias, $findRow) && array_key_exists($field, $findRow[$model->alias])) {
181:                 return $findRow[$model->alias][$field];
182:             } else if ($required) {
183:                 throw new Exception("Field \"$field\" not found for \"{$model->name}\" record: " . print_r($findRow, true));
184:             } else {
185:                 return null;            
186:             }
187:         }
188:     }
189: 
190:     public static function _findSelf(Model $model, $row) {
191:         return array_key_exists($model->alias, $row) ?
192:                 $row[$model->alias] :
193:                 $row;
194:     }
195: 
196:     public static function _findHasOne(Model $model, &$row, $alias) {
197:         if (!array_key_exists($alias, $row)) {
198:             if (self::isBelongsToAssociation($model, $alias)) {
199:                 $row[$alias] = self::findBelongsToInstance($model, $row, $alias);
200:             }
201:             //self::isHasOneAssociation($model, $alias)
202:             else {
203:                 $row[$alias] = self::findHasOneInstance($model, $alias, $row);
204:             }
205:         }
206:         return $row[$alias];
207:     }
208: 
209:     public static function _findHasMany(Model $model, &$row, $alias) {
210:         if (!array_key_exists($alias, $row)) {
211:             $row[$alias] = self::findHasManyInstance($model, $row, $alias);
212:         }
213:         return $row[$alias];
214:     }
215: 
216:     private static function fieldSchema(Model $model, $name) {
217:         if (($fieldSchema = $model->schema($name))) {
218:             return $fieldSchema;
219:         } else if (!empty($model->virtualFields[$name])) {
220:             if (!empty($model->virtualFieldsSchema[$name])) {
221:                 return $model->virtualFieldsSchema[$name];
222:             } else {
223:                 return array(
224:                     'type' => 'string'
225:                 );
226:             }
227:         } else {
228:             throw new Exception("Field not found: {$model->name}.{$name}.");
229:         }
230:     }
231: 
232:     private static function isField(Model $model, $name) {
233:         if (!is_array($schema = $model->schema())) {
234:             throw new Exception("{$model->name}->schema() do not returned a array. Returned: \"$schema\"" );
235:         }
236:         return in_array($name, array_keys($model->schema())) ||
237:                 !empty($model->virtualFields[$name]);
238:     }
239: 
240:     private static function isBelongsToAssociation(Model $model, $alias) {
241:         return in_array($alias, $model->getAssociated('belongsTo'));
242:     }
243:     
244:     /**
245:      * Verifica se $alias é uma associação "hasOne" de $model.
246:      * @param Model $model
247:      * @param string $alias
248:      * @return boolean
249:      */
250:     private static function isHasOneAssociation(Model $model, $alias) {
251:         return in_array($alias, $model->getAssociated('hasOne'));
252:     }
253: 
254:     private static function findBelongsToInstance(Model $model, $row, $alias) {
255:         $ret = $model->{$alias}->find(
256:                 'first', array(
257:             'conditions' => array(
258:                 "{$alias}.{$model->{$alias}->primaryKey}" => self::_findField($model, $row, $model->belongsTo[$alias]['foreignKey']),
259:             ), 'recursive' => -1
260:                 )
261:         );
262: 
263:         if (array_key_exists($alias, $ret)) {
264:             return $ret[$alias];
265:         } else {
266:             return array();
267:         }
268:     }
269: 
270:     /**
271:      * Recupera a instância da associação "hasOne" de $model com alias $alias
272:      * associada com $row.
273:      * @param Model $model
274:      * @param string $alias
275:      * @param array $row
276:      * @return array
277:      */
278:     private static function findHasOneInstance(Model $model, $alias, $row) {
279:         return $model->{$alias}->find(
280:                         'first', array(
281:                     'conditions' => array(
282:                         "{$alias}.{$model->hasOne[$alias]['foreignKey']}" => $row[$model->alias][$model->primaryKey]
283:                     ), 'recursive' => -1
284:                         )
285:         );
286:     }
287: 
288:     private static function isHasManyAssociation(Model $model, $alias) {
289:         return in_array($alias, $model->getAssociated('hasMany'));
290:     }
291: 
292:     private static function findHasManyInstance(Model $model, $row, $alias) {
293:         if (!array_key_exists($alias, $model->hasMany)) {
294:             throw new Exception("Model \"{$model->name}\" has no hasMany association \"$alias\"");
295:         }
296:         $records = $model->{$alias}->find(
297:                 'all'
298:                 , array(
299:             'conditions' => array(
300:                 "{$alias}.{$model->hasMany[$alias]['foreignKey']}" => $row[$model->alias][$model->primaryKey]
301:             )
302:             , 'recursive' => -1
303:                 )
304:         );
305:         $ret = array();
306:         foreach ($records as $record) {
307:             $ret[] = $record[$alias];
308:         }
309:         return $ret;
310:     }
311: 
312:     private static function pathPopFirst($path) {
313:         $newPath = array();
314: 
315:         for ($i = 1; $i < count($path); ++$i) {
316:             $newPath[] = $path[$i];
317:         }
318: 
319:         return $newPath;
320:     }
321: 
322:     /**
323:      * 
324:      * @param mixed $path
325:      * @return mixed
326:      */
327:     private static function _pathLastNode($path) {
328:         $arrayPath = is_array($path) ?
329:                 $path :
330:                 explode('.', $path);
331:         if (empty($arrayPath)) {
332:             throw new ModelTraverserException("Path is empty", compact('path'));
333:         }
334:         end($arrayPath);
335:         return current($arrayPath);
336:     }
337: 
338: }
339: 
340: class ModelTraverserException extends Exception {
341: 
342:     /**
343:      * 
344:      * @param string $message
345:      * @param Model $model
346:      * @param array $params
347:      * @param Exception $previous
348:      */
349:     public function __construct($message, $params, $previous = null) {
350:         parent::__construct(
351:                 $message . ' || ' . print_r(
352:                         self::_buildDebug($params)
353:                         , true
354:                 )
355:                 , 1
356:                 , $previous
357:         );
358:     }
359: 
360:     public static function debug($var) {
361:         debug(self::_buildDebug($var));
362:     }
363: 
364:     private static function _buildDebug($var) {
365:         if ($var instanceof Model) {
366:             return get_class($var) . " ({$var->name}/{$var->alias})";
367:         } else if (is_object($var)) {
368:             return 'Object ' . get_class($var);
369:         } else if (is_array($var)) {
370:             $ret = array();
371:             foreach ($var as $key => $value) {
372:                 $ret[$key] = self::_buildDebug($value);
373:             }
374:             return $ret;
375:         } else {
376:             return $var;
377:         }
378:     }
379: 
380: }
381: 
API documentation generated by ApiGen 2.8.0