markstory / story-scribbles

MIT licensed pieces

This URL has Read+Write access

story-scribbles / cakephp / shells / acl_extras.php
e10b7fba » markstory 2008-10-17 Adding acl_extras shell, ad... 1 <?php
2 /**
3 * Acl Extras Shell.
4 *
5 * Enhances the existing Acl Shell with a few handy functions
6 *
7 * Copyright 2008, Mark Story.
8 * 823 millwood rd.
9 * toronto, ontario M4G 1W3
10 *
11 * Licensed under The MIT License
12 * Redistributions of files must retain the above copyright notice.
13 *
14 * @copyright Copyright 2008, Mark Story.
15 * @link http://mark-story.com
01777828 » markstory 2008-10-27 Updating Acl_extras shell. ... 16 * @version 0.5.1
e10b7fba » markstory 2008-10-17 Adding acl_extras shell, ad... 17 * @author Mark Story <mark@mark-story.com>
18 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
19 */
20 App::import('Component', 'Acl');
21 App::import('Model', 'DbAcl');
22 /**
23 * Shell for ACO sync
24 *
25 * @package cake
26 * @subpackage cake.cake.console.libs
27 */
28 class AclExtrasShell extends Shell {
29 /**
30 * Contains instance of AclComponent
31 *
32 * @var object
33 * @access public
34 */
35 var $Acl;
36 /**
37 * Contains arguments parsed from the command line.
38 *
39 * @var array
40 * @access public
41 */
42 var $args;
43 /**
44 * Contains database source to use
45 *
46 * @var string
47 * @access public
48 */
49 var $dataSource = 'default';
50
51 /**
52 * Root node name.
53 *
54 * @var string
55 **/
56 var $rootNode = 'controllers';
57
58 /**
59 * Internal Clean Actions switch
60 *
61 * @var boolean
62 **/
63 var $_clean = false;
64
65 /**
66 * Start up And load Acl Component / Aco model
67 *
68 * @return void
69 **/
70 function startup() {
71 $this->Acl =& new AclComponent();
72 $controller = null;
73 $this->Acl->startup($controller);
74 $this->Aco =& $this->Acl->Aco;
75 }
76
77 /**
78 * Override main() for help message hook
79 *
80 * @access public
81 */
82 function main() {
83 $out = __("Available ACO sync commands:", true) . "\n";
01777828 » markstory 2008-10-27 Updating Acl_extras shell. ... 84 $out .= "\t - aco_update\n";
85 $out .= "\t - aco_sync\n";
86 $out .= "\t - recover \$type\n";
87 $out .= "\t - verify \$type\n";
e10b7fba » markstory 2008-10-17 Adding acl_extras shell, ad... 88 $out .= "\t - help\n\n";
89 $out .= __("For help, run the 'help' command. For help on a specific command, run 'help <command>'", true);
90 $this->out($out);
91 }
92
93 /**
94 * undocumented function
95 *
96 * @return void
97 **/
98 function aco_update() {
99 $root = $this->_checkNode($this->rootNode, $this->rootNode, null);
100 App::import('Core', array('Controller'));
101
102 $Controllers = Configure::listObjects('controller');
103 $appIndex = array_search('App', $Controllers);
104 if ($appIndex !== false ) {
105 unset($Controllers[$appIndex]);
106 }
107 // look at each controller in app/controllers
108 foreach ($Controllers as $ctrlName) {
109 App::import('Controller', $ctrlName);
110 // find / make controller node
111 $controllerNode = $this->_checkNode($this->rootNode .'/'.$ctrlName, $ctrlName, $root['Aco']['id']);
112 $this->_checkMethods($ctrlName, $controllerNode, $this->_clean);
113 }
114 if ($this->_clean) {
115 $this->Aco->id = $root['Aco']['id'];
116 $controllerNodes = $this->Aco->children(null, true);
117 $ctrlFlip = array_flip($Controllers);
118 foreach ($controllerNodes as $ctrlNode) {
119 if (!isset($ctrlFlip[$ctrlNode['Aco']['alias']])) {
120 $this->Aco->id = $ctrlNode['Aco']['id'];
121 if ($this->Aco->delete()) {
122 $this->out(sprintf(__('Deleted %s and all children', true), $this->rootNode . '/' . $ctrlNode['Aco']['alias']));
123 }
124 }
125 }
126 }
127 $this->out(__('Aco Update Complete', true));
128 return true;
129 }
130
131 /**
132 * Sync the ACO table
133 *
134 * @return void
135 **/
136 function aco_sync() {
137 $this->_clean = true;
01777828 » markstory 2008-10-27 Updating Acl_extras shell. ... 138 $this->aco_update();
e10b7fba » markstory 2008-10-17 Adding acl_extras shell, ad... 139 }
140
141 /**
142 * Check a node for existance, create it if it doesn't exist.
143 *
144 * @param string $path
145 * @param string $alias
146 * @param int $parentId
147 * @return array Aco Node array
148 */
149 function _checkNode($path, $alias, $parentId = null) {
150 $node = $this->Aco->node($path);
151 if (!$node) {
152 $this->Aco->create(array('parent_id' => $parentId, 'model' => null, 'alias' => $alias));
153 $node = $this->Aco->save();
154 $node['Aco']['id'] = $this->Aco->id;
155 $this->out(sprintf(__('Created Aco node: %s', true), $path));
156 } else {
157 $node = $node[0];
158 }
159 return $node;
160 }
161
162 /**
163 * Check and Add/delete controller Methods
164 *
165 * @param string $controller
166 * @param array $node
167 * @param bool $cleanup
168 * @return void
169 */
170 function _checkMethods($controller, $node, $cleanup = false) {
171 $className = $controller . 'Controller';
172 $baseMethods = get_class_methods('Controller');
173 $actions = get_class_methods($className);
174 $methods = array_diff($actions, $baseMethods);
175 foreach ($methods as $action) {
176 if (strpos($action, '_', 0) === 0) {
177 continue;
178 }
179 $this->_checkNode($this->rootNode . '/' . $controller . '/' . $action, $action, $node['Aco']['id']);
180 }
181 if ($cleanup) {
182 $actionNodes = $this->Aco->children($node['Aco']['id']);
183 $methodFlip = array_flip($methods);
184 foreach ($actionNodes as $action) {
185 if (!isset($methodFlip[$action['Aco']['alias']])) {
186 $this->Aco->id = $action['Aco']['id'];
187 if ($this->Aco->delete()) {
188 $path = $this->rootNode . '/' . $controller . '/' . $action['Aco']['alias'];
189 $this->out(sprintf(__('Deleted Aco node %s', true), $path));
190 }
191 }
192 }
193 }
194 return true;
195 }
196
197
198 /**
199 * Show help screen.
200 *
201 * @access public
202 */
203 function help() {
204 $head = __("Usage: cake acl_extras <command>", true) . "\n";
205 $head .= "-----------------------------------------------\n";
206 $head .= __("Commands:", true) . "\n\n";
207
208 $commands = array(
209 'update' => "\tcake acl_extras aco_update\n" .
210 "\t\t" . __("Add new ACOs for new controllers and actions", true) . "\n" .
211 "\t\t" . __("Create new ACO's for controllers and their actions. Does not remove any nodes from ACO table", true),
212
213 'sync' => "\tcake acl_extras aco_sync\n" .
214 "\t\tPerform a full sync on the ACO table.\n" .
215 "\t\t" . __("Creates new ACO's for missing controllers and actions. Removes orphaned entries in the ACO table.", true) . "\n",
216
217 'verify' => "\tcake acl_extras verify \$type\n" .
218 "\t\t" . __('Verify the tree structure of either your Aco or Aro Trees', true),
219
220 'recover' => "\tcake acl_extras recover \$type\n" .
221 "\t\t" . __('Recover a corrupted Tree', true),
222
223 'help' => "\thelp [<command>]\n" .
224 "\t\t" . __("Displays this help message, or a message on a specific command.", true) . "\n"
225 );
226
227 $this->out($head);
228 if (!isset($this->args[0])) {
229 foreach ($commands as $cmd) {
230 $this->out("{$cmd}\n\n");
231 }
232 } elseif (isset($commands[low($this->args[0])])) {
233 $this->out($commands[low($this->args[0])] . "\n");
234 } else {
235 $this->out(sprintf(__("Command '%s' not found", true), $this->args[0]));
236 }
237 }
238 /**
239 * Verify a Acl Tree
240 *
241 * @param string $type The type of Acl Node to verify
242 * @access public
243 * @return void
244 */
245 function verify() {
246 if (empty($this->args[0])) {
247 $this->err(__('Missing Type', true));
248 $this->_stop();
249 }
250 $type = Inflector::camelize($this->args[0]);
251 $return = $this->Acl->{$type}->verify();
252 if ($return === true) {
253 $this->out(__('Tree is valid and strong', true));
254 } else {
255 $this->out(print_r($return));
256 }
257 }
258 /**
259 * Recover an Acl Tree
260 *
261 * @param string $type The Type of Acl Node to recover
262 * @access public
263 * @return void
264 */
265 function recover() {
266 if (empty($this->args[0])) {
267 $this->err(__('Missing Type', true));
268 $this->_stop();
269 }
270 $type = Inflector::camelize($this->args[0]);
271 $return = $this->Acl->{$type}->recover();
272 if ($return === true) {
273 $this->out(__('Tree has been recovered, or tree did not need recovery.', true));
274 } else {
275 $this->out(__('Tree recovery failed.', true));
276 }
277 }
278
279 }
280 ?>