統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Model / AclNode.php @ master

履歴 | 表示 | アノテート | ダウンロード (5.505 KB)

1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP(tm) Project
12
 * @package       Cake.Model
13
 * @since         CakePHP(tm) v 0.2.9
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16

    
17
App::uses('Model', 'Model');
18

    
19
/**
20
 * ACL Node
21
 *
22
 * @package       Cake.Model
23
 */
24
class AclNode extends Model {
25

    
26
/**
27
 * Explicitly disable in-memory query caching for ACL models
28
 *
29
 * @var bool
30
 */
31
        public $cacheQueries = false;
32

    
33
/**
34
 * ACL models use the Tree behavior
35
 *
36
 * @var array
37
 */
38
        public $actsAs = array('Tree' => array('type' => 'nested'));
39

    
40
/**
41
 * Constructor
42
 */
43
        public function __construct() {
44
                $config = Configure::read('Acl.database');
45
                if (isset($config)) {
46
                        $this->useDbConfig = $config;
47
                }
48
                parent::__construct();
49
        }
50

    
51
/**
52
 * Retrieves the Aro/Aco node for this model
53
 *
54
 * @param string|array|Model $ref Array with 'model' and 'foreign_key', model object, or string value
55
 * @return array Node found in database
56
 * @throws CakeException when binding to a model that doesn't exist.
57
 */
58
        public function node($ref = null) {
59
                $db = $this->getDataSource();
60
                $type = $this->alias;
61
                $result = null;
62

    
63
                if (!empty($this->useTable)) {
64
                        $table = $this->useTable;
65
                } else {
66
                        $table = Inflector::pluralize(Inflector::underscore($type));
67
                }
68

    
69
                if (empty($ref)) {
70
                        return null;
71
                } elseif (is_string($ref)) {
72
                        $path = explode('/', $ref);
73
                        $start = $path[0];
74
                        unset($path[0]);
75

    
76
                        $queryData = array(
77
                                'conditions' => array(
78
                                        $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"),
79
                                        $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght")),
80
                                'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'),
81
                                'joins' => array(array(
82
                                        'table' => $table,
83
                                        'alias' => "{$type}0",
84
                                        'type' => 'INNER',
85
                                        'conditions' => array("{$type}0.alias" => $start)
86
                                )),
87
                                'order' => $db->name("{$type}.lft") . ' DESC'
88
                        );
89

    
90
                        $conditionsAfterJoin = array();
91

    
92
                        foreach ($path as $i => $alias) {
93
                                $j = $i - 1;
94

    
95
                                $queryData['joins'][] = array(
96
                                        'table' => $table,
97
                                        'alias' => "{$type}{$i}",
98
                                        'type' => 'INNER',
99
                                        'conditions' => array(
100
                                                $db->name("{$type}{$i}.alias") . ' = ' . $db->value($alias, 'string')
101
                                        )
102
                                );
103

    
104
                                // it will be better if this conditions will performs after join operation
105
                                $conditionsAfterJoin[] = $db->name("{$type}{$j}.id") . ' = ' . $db->name("{$type}{$i}.parent_id");
106
                                $conditionsAfterJoin[] = $db->name("{$type}{$i}.rght") . ' < ' . $db->name("{$type}{$j}.rght");
107
                                $conditionsAfterJoin[] = $db->name("{$type}{$i}.lft") . ' > ' . $db->name("{$type}{$j}.lft");
108

    
109
                                $queryData['conditions'] = array('or' => array(
110
                                        $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght"),
111
                                        $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}{$i}.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}{$i}.rght"))
112
                                );
113
                        }
114
                        $queryData['conditions'] = array_merge($queryData['conditions'], $conditionsAfterJoin);
115
                        $result = $db->read($this, $queryData, -1);
116
                        $path = array_values($path);
117

    
118
                        if (!isset($result[0][$type]) ||
119
                                (!empty($path) && $result[0][$type]['alias'] != $path[count($path) - 1]) ||
120
                                (empty($path) && $result[0][$type]['alias'] != $start)
121
                        ) {
122
                                return false;
123
                        }
124
                } elseif (is_object($ref) && $ref instanceof Model) {
125
                        $ref = array('model' => $ref->name, 'foreign_key' => $ref->id);
126
                } elseif (is_array($ref) && !(isset($ref['model']) && isset($ref['foreign_key']))) {
127
                        $name = key($ref);
128
                        list(, $alias) = pluginSplit($name);
129

    
130
                        $model = ClassRegistry::init(array('class' => $name, 'alias' => $alias));
131

    
132
                        if (empty($model)) {
133
                                throw new CakeException('cake_dev', "Model class '%s' not found in AclNode::node() when trying to bind %s object", $type, $this->alias);
134
                        }
135

    
136
                        $tmpRef = null;
137
                        if (method_exists($model, 'bindNode')) {
138
                                $tmpRef = $model->bindNode($ref);
139
                        }
140
                        if (empty($tmpRef)) {
141
                                $ref = array('model' => $alias, 'foreign_key' => $ref[$name][$model->primaryKey]);
142
                        } else {
143
                                if (is_string($tmpRef)) {
144
                                        return $this->node($tmpRef);
145
                                }
146
                                $ref = $tmpRef;
147
                        }
148
                }
149
                if (is_array($ref)) {
150
                        if (is_array(current($ref)) && is_string(key($ref))) {
151
                                $name = key($ref);
152
                                $ref = current($ref);
153
                        }
154
                        foreach ($ref as $key => $val) {
155
                                if (strpos($key, $type) !== 0 && strpos($key, '.') === false) {
156
                                        unset($ref[$key]);
157
                                        $ref["{$type}0.{$key}"] = $val;
158
                                }
159
                        }
160
                        $queryData = array(
161
                                'conditions' => $ref,
162
                                'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'),
163
                                'joins' => array(array(
164
                                        'table' => $table,
165
                                        'alias' => "{$type}0",
166
                                        'type' => 'INNER',
167
                                        'conditions' => array(
168
                                                $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"),
169
                                                $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght")
170
                                        )
171
                                )),
172
                                'order' => $db->name("{$type}.lft") . ' DESC'
173
                        );
174
                        $result = $db->read($this, $queryData, -1);
175

    
176
                        if (!$result) {
177
                                throw new CakeException(__d('cake_dev', "AclNode::node() - Couldn't find %s node identified by \"%s\"", $type, print_r($ref, true)));
178
                        }
179
                }
180
                return $result;
181
        }
182

    
183
}