Completed
Push — 2.0 ( b904ee...24f948 )
by Christopher
08:40
created

AcosTable::beforeSave()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 2
eloc 3
nc 2
nop 2
1
<?php
2
/**
3
 * Licensed under The GPL-3.0 License
4
 * For full copyright and license information, please see the LICENSE.txt
5
 * Redistributions of files must retain the above copyright notice.
6
 *
7
 * @since    2.0.0
8
 * @author   Christopher Castro <[email protected]>
9
 * @link     http://www.quickappscms.org
10
 * @license  http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License
11
 */
12
namespace User\Model\Table;
13
14
use Cake\Cache\Cache;
15
use Cake\Event\Event;
16
use Cake\ORM\Table;
17
use User\Model\Entity\Aco;
18
19
/**
20
 * Represents "acos" database table.
21
 *
22
 */
23
class AcosTable extends Table
24
{
25
26
    /**
27
     * Initialize a table instance. Called after the constructor.
28
     *
29
     * @param array $config Configuration options passed to the constructor
30
     * @return void
31
     */
32
    public function initialize(array $config)
33
    {
34
        $this->addBehavior('Tree');
35
        $this->belongsToMany('Roles', [
36
            'className' => 'User.Roles',
37
            'joinTable' => 'permissions',
38
            'propertyName' => 'roles',
39
        ]);
40
41
        // removes all permissions when a content is removed from the tree
42
        $this->hasMany('Permissions', [
43
            'className' => 'User.Permissions',
44
            'propertyName' => 'permissions',
45
            'dependent' => true,
46
        ]);
47
    }
48
49
    /**
50
     * We create a hash of "alias" property so we can perform
51
     * case sensitive SQL comparisons.
52
     *
53
     * @param \Cake\Event\Event $event The event that was triggered
54
     * @param \User\Model\Entity\Aco $aco ACO entity being saved
55
     * @return void
56
     */
57
    public function beforeSave(Event $event, Aco $aco)
58
    {
59
        if ($aco->isNew()) {
60
            $aco->set('alias_hash', md5($aco->alias));
61
        }
62
    }
63
64
    /**
65
     * Clear permissions cache after ACO save so new changes are applied.
66
     *
67
     * @param \Cake\Event\Event $event The event that was triggered
68
     * @param \User\Model\Entity\Aco $aco ACO entity that was saved
69
     * @return void
70
     */
71
    public function afterSave(Event $event, Aco $aco)
72
    {
73
        Cache::clear(false, 'permissions');
74
    }
75
76
    /**
77
     * Retrieves the ACO contents for the given ACO path.
78
     *
79
     * ### ACO path format:
80
     *
81
     * As a string describing a path:
82
     *
83
     *     PluginName/ControllerName/actionName
84
     *
85
     * Or an associative array which values describes a path, for instance:
86
     *
87
     * ```php
88
     * [
89
     *     'plugin' => YourPlugin,
90
     *     'prefix' => Admin,
91
     *     'controller' => Users,
92
     *     'action' => index,
93
     * ]
94
     * ```
95
     *
96
     * The above array is equivalent to: `PluginName/Admin/Users/index`
97
     *
98
     * @param string|array $ref ACO path as described above
99
     * @return \Cake\ORM\Query|bool False if not found or query result if found
100
     */
101
    public function node($ref)
102
    {
103
        $type = $this->alias();
104
        $table = $this->table();
105
        $path = [];
106
107
        if (is_array($ref)) {
108
            $path = implode('/', array_values(array_filter($ref)));
109
            $path = explode('/', $path);
110
        } elseif (is_string($ref)) {
111
            $path = explode('/', $ref);
112
        }
113
114
        if (empty($path)) {
115
            return false;
116
        }
117
118
        $start = $path[0];
119
        unset($path[0]);
120
121
        $queryData = [
122
            'conditions' => [
123
                "{$type}.lft" . ' <= ' . "{$type}0.lft",
124
                "{$type}.rght" . ' >= ' . "{$type}0.rght",
125
            ],
126
            'fields' => ['id', 'parent_id', 'alias'],
127
            'join' => [[
128
                    'table' => $table,
129
                    'alias' => "{$type}0",
130
                    'type' => 'INNER',
131
                    'conditions' => [
132
                        "{$type}0.alias_hash" => md5($start),
133
                        "{$type}0.plugin = {$type}.plugin",
134
                    ]
135
            ]],
136
            'order' => "{$type}.lft" . ' DESC'
137
        ];
138
139
        foreach ($path as $i => $alias) {
140
            $j = $i - 1;
141
142
            $queryData['join'][] = [
143
                'table' => $table,
144
                'alias' => "{$type}{$i}",
145
                'type' => 'INNER',
146
                'conditions' => [
147
                    "{$type}{$i}.lft" . ' > ' . "{$type}{$j}.lft",
148
                    "{$type}{$i}.rght" . ' < ' . "{$type}{$j}.rght",
149
                    "{$type}{$i}.alias_hash" => md5($alias),
150
                    "{$type}{$i}.plugin = {$type}{$i}.plugin",
151
                    "{$type}{$j}.id" . ' = ' . "{$type}{$i}.parent_id"
152
                ]
153
            ];
154
155
            $queryData['conditions'] = [
156
                'OR' => [
157
                    "{$type}.lft" . ' <= ' . "{$type}0.lft" . ' AND ' . "{$type}.rght" . ' >= ' . "{$type}0.rght",
158
                    "{$type}.lft" . ' <= ' . "{$type}{$i}.lft" . ' AND ' . "{$type}.rght" . ' >= ' . "{$type}{$i}.rght"
159
                ]
160
            ];
161
        }
162
        $query = $this->find('all', $queryData);
163
        $result = $query->toArray();
164
        $path = array_values($path);
165
        if (!isset($result[0]) ||
166
            (!empty($path) && $result[0]->alias !== $path[count($path) - 1]) ||
167
            (empty($path) && $result[0]->alias !== $start)
168
        ) {
169
            return false;
170
        }
171
172
        return $query;
173
    }
174
}
175