1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: App::uses('Model', 'Model');
18:
19: 20: 21: 22: 23:
24: class AclNode extends Model {
25:
26: 27: 28: 29: 30:
31: public $cacheQueries = false;
32:
33: 34: 35: 36: 37:
38: public $actsAs = array('Tree' => array('type' => 'nested'));
39:
40: 41: 42: 43:
44: public function __construct() {
45: $config = Configure::read('Acl.database');
46: if (isset($config)) {
47: $this->useDbConfig = $config;
48: }
49: parent::__construct();
50: }
51:
52: 53: 54: 55: 56: 57: 58:
59: public function node($ref = null) {
60: $db = $this->getDataSource();
61: $type = $this->alias;
62: $result = null;
63:
64: if (!empty($this->useTable)) {
65: $table = $this->useTable;
66: } else {
67: $table = Inflector::pluralize(Inflector::underscore($type));
68: }
69:
70: if (empty($ref)) {
71: return null;
72: } elseif (is_string($ref)) {
73: $path = explode('/', $ref);
74: $start = $path[0];
75: unset($path[0]);
76:
77: $queryData = array(
78: 'conditions' => array(
79: $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"),
80: $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght")),
81: 'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'),
82: 'joins' => array(array(
83: 'table' => $table,
84: 'alias' => "{$type}0",
85: 'type' => 'INNER',
86: 'conditions' => array("{$type}0.alias" => $start)
87: )),
88: 'order' => $db->name("{$type}.lft") . ' DESC'
89: );
90:
91: $conditionsAfterJoin = array();
92:
93: foreach ($path as $i => $alias) {
94: $j = $i - 1;
95:
96: $queryData['joins'][] = array(
97: 'table' => $table,
98: 'alias' => "{$type}{$i}",
99: 'type' => 'INNER',
100: 'conditions' => array(
101: $db->name("{$type}{$i}.alias") . ' = ' . $db->value($alias, 'string')
102: )
103: );
104:
105:
106: $conditionsAfterJoin[] = $db->name("{$type}{$j}.id") . ' = ' . $db->name("{$type}{$i}.parent_id");
107: $conditionsAfterJoin[] = $db->name("{$type}{$i}.rght") . ' < ' . $db->name("{$type}{$j}.rght");
108: $conditionsAfterJoin[] = $db->name("{$type}{$i}.lft") . ' > ' . $db->name("{$type}{$j}.lft");
109:
110: $queryData['conditions'] = array('or' => array(
111: $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght"),
112: $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}{$i}.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}{$i}.rght"))
113: );
114: }
115: $queryData['conditions'] = array_merge($queryData['conditions'], $conditionsAfterJoin);
116: $result = $db->read($this, $queryData, -1);
117: $path = array_values($path);
118:
119: if (!isset($result[0][$type]) ||
120: (!empty($path) && $result[0][$type]['alias'] != $path[count($path) - 1]) ||
121: (empty($path) && $result[0][$type]['alias'] != $start)
122: ) {
123: return false;
124: }
125: } elseif (is_object($ref) && $ref instanceof Model) {
126: $ref = array('model' => $ref->name, 'foreign_key' => $ref->id);
127: } elseif (is_array($ref) && !(isset($ref['model']) && isset($ref['foreign_key']))) {
128: $name = key($ref);
129: list(, $alias) = pluginSplit($name);
130:
131: $model = ClassRegistry::init(array('class' => $name, 'alias' => $alias));
132:
133: if (empty($model)) {
134: throw new CakeException('cake_dev', "Model class '%s' not found in AclNode::node() when trying to bind %s object", $type, $this->alias);
135: }
136:
137: $tmpRef = null;
138: if (method_exists($model, 'bindNode')) {
139: $tmpRef = $model->bindNode($ref);
140: }
141: if (empty($tmpRef)) {
142: $ref = array('model' => $alias, 'foreign_key' => $ref[$name][$model->primaryKey]);
143: } else {
144: if (is_string($tmpRef)) {
145: return $this->node($tmpRef);
146: }
147: $ref = $tmpRef;
148: }
149: }
150: if (is_array($ref)) {
151: if (is_array(current($ref)) && is_string(key($ref))) {
152: $name = key($ref);
153: $ref = current($ref);
154: }
155: foreach ($ref as $key => $val) {
156: if (strpos($key, $type) !== 0 && strpos($key, '.') === false) {
157: unset($ref[$key]);
158: $ref["{$type}0.{$key}"] = $val;
159: }
160: }
161: $queryData = array(
162: 'conditions' => $ref,
163: 'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'),
164: 'joins' => array(array(
165: 'table' => $table,
166: 'alias' => "{$type}0",
167: 'type' => 'INNER',
168: 'conditions' => array(
169: $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"),
170: $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght")
171: )
172: )),
173: 'order' => $db->name("{$type}.lft") . ' DESC'
174: );
175: $result = $db->read($this, $queryData, -1);
176:
177: if (!$result) {
178: throw new CakeException(__d('cake_dev', "AclNode::node() - Couldn't find %s node identified by \"%s\"", $type, print_r($ref, true)));
179: }
180: }
181: return $result;
182: }
183:
184: }
185: