1: <?php
2:
3: class CakeLayersHelper extends Helper {
4:
5: private $dataCache;
6:
7: public function getPluginNameByControllerClass($controllerClass) {
8: foreach (CakePlugin::loaded() as $pluginName) {
9: foreach (App::objects("$pluginName.Controller") as $pluginControllerClass) {
10: if ($pluginControllerClass == $controllerClass) {
11: return $pluginName;
12: }
13: }
14: }
15: return null;
16: }
17:
18: public function getController($controllerName = null) {
19: if (empty($controllerName)) {
20: $controllerName = $this->params['controller'];
21: }
22: $controllerClassUnderscore = $controllerName . '_controller';
23: $controller = ClassRegistry::getObject($controllerClassUnderscore);
24: if (!$controller) {
25: App::import('Controller', $controllerName);
26: $controllerClass = Inflector::camelize($controllerName . '_controller');
27: if (!class_exists($controllerClass)) {
28: return null;
29: }
30: $controller = new $controllerClass;
31: $controller->constructClasses();
32: $controller->plugin = $this->getPluginNameByControllerClass($controllerClass);
33: if (!empty($controller->SubmoduleOneToMany)) {
34: $settings = array();
35: if (!empty($controller->components['SubmoduleOneToMany'])) {
36: $settings = $controller->components['SubmoduleOneToMany'];
37: }
38: $controller->SubmoduleOneToMany->initialize(
39: $controller, $settings);
40: $controller->SubmoduleOneToMany->startup($controller);
41: }
42: ClassRegistry::getInstance()->addObject($controllerClassUnderscore, $controller);
43: }
44: return $controller;
45: }
46:
47: public function getControllerDefaultModelClass($controllerName = null) {
48: return $this->getController($controllerName)->modelClass;
49: }
50:
51: public function getControllerDefaultModel($controllerName = null) {
52: return $this->getModel($this->getControllerDefaultModelClass($controllerName));
53: }
54:
55: public function getControllerByModel($model) {
56: if ($model instanceof Model) {
57: $model = $model->name;
58: }
59: return $this->getController(Inflector::underscore(Inflector::pluralize($model)));
60: }
61:
62: 63: 64: 65: 66: 67: 68:
69: public function getModel($model, $required = false) {
70: if ($model instanceof Model) {
71: return $model;
72: } elseif (is_string($model)) {
73: $modelName = $model;
74: $model = ClassRegistry::getObject($modelName);
75: if (!$model) {
76: $model = ClassRegistry::init($modelName);
77: }
78: } else {
79: $modelName = $model . ' [' . gettype($model) . ']';
80: $model = null;
81: }
82:
83: if (!$model && $required) {
84: throw new Exception("Model not found: \"$modelName\".");
85: }
86:
87: if ($model instanceof Model) {
88: $model->recursive = -1;
89: }
90:
91: return $model;
92: }
93:
94: private function getModelName($model) {
95: return $model instanceof Model ? $model->name : $model;
96: }
97:
98: public function getFieldSchema($fieldName, $modelClass) {
99: $modelSchema = $this->getModel($modelClass)->schema();
100: if (!empty($modelSchema[$fieldName])) {
101: return $modelSchema[$fieldName];
102: }
103:
104: if (!empty($this->getModel($modelClass)->virtualFieldsSchema)) {
105: $virtualModelSchema = $this->getModel($modelClass)->virtualFieldsSchema;
106: if (!empty($virtualModelSchema[$fieldName])) {
107: return $virtualModelSchema[$fieldName];
108: }
109: }
110:
111: return false;
112: }
113:
114: public function getModelAssociations($model) {
115: $modelParam = $model;
116: if ($model) {
117: if (is_string($model)) {
118: $model = $this->getModel($model);
119: }
120: } else {
121: $model = $this->getControllerDefaultModel(null);
122: }
123:
124: if (!$model instanceof Model) {
125: throw new Exception("not a model " . print_r($modelParam, true));
126: }
127: $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
128: $associations = array();
129:
130: foreach ($keys as $key => $type) {
131: foreach ($model->{$type} as $assocKey => $assocData) {
132: $associations[$type][$assocKey]['alias'] = $assocKey;
133: $associations[$type][$assocKey]['type'] = $type;
134: $associations[$type][$assocKey]['className'] = $assocData['className'];
135:
136: $associations[$type][$assocKey]['primaryKey'] =
137: $model->{$assocKey}->primaryKey;
138:
139: $associations[$type][$assocKey]['displayField'] =
140: $model->{$assocKey}->displayField;
141:
142: $associations[$type][$assocKey]['foreignKey'] =
143: $assocData['foreignKey'];
144:
145: $associations[$type][$assocKey]['order'] =
146: (empty($assocData['order']) ? false : $assocData['order']);
147:
148: $associations[$type][$assocKey]['controller'] =
149: Inflector::pluralize(Inflector::underscore($assocData['className']));
150:
151: if ($type == 'hasAndBelongsToMany') {
152: $associations[$type][$assocKey]['with'] = $assocData['with'];
153: }
154: }
155: }
156: return $associations;
157: }
158:
159: public function getCurrentView() {
160: return $this->_View;
161: }
162:
163: 164: 165: 166: 167: 168: 169: 170: 171:
172: public function modelInstanceField($model, $instance, $field, $toDisplay = false) {
173: if (!($model instanceof Model)) {
174: $model = ClassRegistry::init($model);
175: }
176: return $toDisplay ?
177: ModelTraverser::displayValue($model, $instance, $field) :
178: ModelTraverser::value($model, $instance, $field);
179: }
180:
181: public function modelInstanceFieldByPath($model, $instance, $path, $toDisplay = false) {
182: try {
183: $modelName = $model instanceof Model ? $model->name : $model;
184: $model = $this->getModel($model);
185:
186: if (isset($instance[$path[0]])) {
187: if ($toDisplay && $model && ($association = $this->_associationByForeingKey($model, $path[0]))) {
188: return $this->modelInstanceFieldByPath(
189: $model, $instance, array(
190: $association['alias'],
191: $this->getModel($association['className'])->displayField),
192: $toDisplay
193: );
194: }
195: $value = $instance[$path[0]];
196: if (is_array($value) && $model) {
197: return $this->modelInstanceFieldByPath(
198: $this->modelAssociationModel($model, $path[0])
199: , $value
200: , $this->_pathPopFirst($path)
201: , $toDisplay
202: );
203: }
204: return $value;
205: } else {
206: $association = $this->modelAssociationOneType($model, $path[0]);
207:
208: if ($association) {
209: $associationInstance = $this->associationInstance($model, $association['alias'], $instance);
210: if (isset($associationInstance[$association['alias']])) {
211: return $this->modelInstanceFieldByPath(
212: $this->modelAssociationModel($model, $association['alias'])
213: , $associationInstance[$association['alias']]
214: , $this->_pathPopFirst($path)
215: , $toDisplay);
216: }
217: }
218:
219: return null;
220: }
221: } catch (Exception $ex) {
222: throw new Exception(print_r(compact('modelName', 'instance', 'path', 'toDisplay'), true), 0, $ex);
223: }
224: }
225:
226: private function _pathPopFirst($path) {
227: $newPath = array();
228:
229: for ($i = 1; $i < count($path); ++$i) {
230: $newPath[] = $path[$i];
231: }
232:
233: return $newPath;
234: }
235:
236: public function modelAssociationModel($model, $associationAlias, $required = false) {
237: return $this->modelAssociationModelByPath(
238: $model
239: , explode('.', $associationAlias)
240: , $required
241: );
242: }
243:
244: public function modelAssociationModelByPath($model, $associationPath, $required = false) {
245: $model = $this->getModel($model);
246: $associationModel = false;
247: if ($model->alias == $associationPath[0]) {
248: $associationModel = $model;
249: } else {
250: $association = $this->modelAssociation($model, $associationPath[0]);
251:
252: if ($association) {
253: $associationModel = $model->{$association['alias']};
254: switch (get_class($associationModel)) {
255: case 'AppModel':
256: case 'Model':
257: throw new Exception("Association \"{$model->name}->{$association['alias']}\" has " . get_class($associationModel) . " class");
258: }
259: }
260: }
261:
262: if ($associationModel) {
263: if (count($associationPath) > 1) {
264: return $this->modelAssociationModelByPath(
265: $associationModel
266: , $this->_pathPopFirst($associationPath)
267: , $required
268: );
269: } else {
270: return $associationModel;
271: }
272: }
273:
274: if ($required) {
275: throw new Exception("Model de associação não foi encontrado. " .
276: 'Model->name: ' . $model->name .
277: '; Model->alias: ' . $model->alias .
278: '; Association path: [' . implode(', ', $associationPath) . ']');
279: } else {
280: return null;
281: }
282: }
283:
284: private function modelAssociation($model, $associationAlias) {
285: $modelAssociations = $this->getModelAssociations($model);
286: foreach ($modelAssociations as $type => $associations) {
287: foreach ($associations as $alias => $associationData) {
288: if ($alias == $associationAlias) {
289: return $associationData;
290: }
291: }
292: }
293:
294: return null;
295: }
296:
297: public function modelAssociationOneType($model, $associationAlias) {
298: $association = $this->modelAssociation($model, $associationAlias);
299:
300: if (!empty($association)) {
301: switch ($association['type']) {
302: case 'belongsTo':
303: case 'hasOne':
304: return $association;
305: }
306: }
307:
308: return null;
309: }
310:
311: private function associationInstance($model, $associationAlias, $instance, $required = false) {
312: $association = $this->modelAssociation($model, $associationAlias);
313:
314: if (!empty($association)) {
315: switch ($association['type']) {
316: case 'belongsTo':
317: return $this->belongsToAssociationInstance($model, $association, $instance);
318:
319: case 'hasOne':
320: return $this->hasOneAssociationInstance($model, $association, $instance);
321: }
322: }
323:
324: if ($required) {
325: $modelName = $this->getModelName($model);
326: throw new Exception("Instância de associação não foi encontrada. " . print_r(compact('modelName', 'associationAlias', 'instance'), true));
327: }
328:
329: return null;
330: }
331:
332: public function associationInstances($model, $associationAlias, $instance) {
333: return $this->associationInstancesByPath(
334: $model
335: , explode('.', $associationAlias)
336: , $instance
337: );
338: }
339:
340: 341: 342: 343: 344: 345:
346: public function associationInstancesByPath($model, $associationPath, $instance) {
347: $model = $this->getModel($model, true);
348:
349: if (count($associationPath) > 1) {
350: $associationInstance = $this->associationInstance(
351: $model
352: , $associationPath[0]
353: , $instance
354: , true
355: );
356: if ($associationInstance) {
357: return $this->associationInstancesByPath(
358: $this->modelAssociationModel($model, $associationPath[0])
359: , $this->_pathPopFirst($associationPath)
360: , $associationInstance
361: );
362: } else {
363: return array();
364: }
365: } else {
366: if (isset($instance[$model->alias])) {
367: $instance = $instance[$model->alias];
368: }
369: $associationModel = $this->modelAssociationModel($model, $associationPath[0]);
370: $association = $this->modelAssociation($model, $associationPath[0]);
371: return $associationModel->find(
372: 'all', array(
373: 'conditions' => array(
374: "{$associationModel->alias}.{$association['foreignKey']}" => $instance[$model->primaryKey]
375: ),
376: 'order' => (empty($association['order']) ? false : $association['order'])
377: )
378: );
379: }
380: }
381:
382: private function belongsToAssociationInstance(Model $model, $association, $instance) {
383: if (!isset($this->dataCache['belongsToAssociationInstance'][$model->name][$association['alias']][$instance[$association['foreignKey']]])) {
384:
385: $model = $this->getModel($model, true);
386: $associationModel = $model->{$association['alias']};
387:
388: if ($associationModel == null) {
389: throw new Exception("Association Model is null");
390: }
391:
392: $this->dataCache['belongsToAssociationInstance'][$model->name][$association['alias']][$instance[$association['foreignKey']]] = $associationModel->find(
393: 'first'
394: , array(
395: 'conditions' => array(
396: "{$associationModel->alias}.{$associationModel->primaryKey}" => $instance[$association['foreignKey']]
397: ),
398: 'recursive' => -1,
399: )
400: );
401: }
402:
403: return $this->dataCache['belongsToAssociationInstance'][$model->name][$association['alias']][$instance[$association['foreignKey']]];
404: }
405:
406: private function hasOneAssociationInstance(Model $model, $association, $instance) {
407: if (isset($instance[$model->alias])) {
408: $instance = $instance[$model->alias];
409: }
410:
411: $modelName = $model->name;
412:
413:
414: if (!isset($this->dataCache[__METHOD__][$model->name][$association['alias']][$instance[$model->primaryKey]])) {
415: $model = $this->getModel($model, true);
416: $associationModel = $model->{$association['alias']};
417:
418: $this->dataCache[__METHOD__][$model->name][$association['alias']][$instance[$model->primaryKey]] = $associationModel->find(
419: 'first'
420: , array(
421: 'conditions' => array(
422: "{$associationModel->alias}.{$association['foreignKey']}" => $instance[$model->primaryKey]
423: )
424: )
425: );
426: }
427:
428: return $this->dataCache[__METHOD__][$model->name][$association['alias']][$instance[$model->primaryKey]];
429: }
430:
431: private function _associationByForeingKey($model, $field) {
432: $modelAssociations = $this->getModelAssociations($model);
433: foreach ($modelAssociations as $type => $associations) {
434: foreach ($associations as $alias => $associationData) {
435: if ($associationData['foreignKey'] == $field) {
436: return $associationData;
437: }
438: }
439: }
440:
441: return null;
442: }
443:
444: }
445:
446: ?>
447: