237 |
238 | Runs a PHP Script after bootstrapping Magento. Useful for testing code or writing scripts that need to run inside of Magento without having to write a full-fledged module or a sandbox.
239 |
240 | ### magento-shutdown
241 |
242 | Shuts down Magento by creating the maintenance flag file.
243 |
244 | ### magento-startup
245 |
246 | Allows Magento run by removing the maintenance flag file.
247 |
248 | ### mc-dl
249 |
250 | Downloads a Magento connect package. Yes, I know you can use ./mage but this also works.
251 |
252 | ### mc-versions
253 |
254 | Lists the available versions of a module that you can download from Magento Connect.
255 |
256 | ### module-list
257 |
258 | Displays a list of all modules on the system. Shows module name, version, active, output, and code pool.
259 |
260 | +------------------------------+------------+--------+----------+-----------+
261 | | Module Name | Version | Active | Output | Code Pool |
262 | +------------------------------+------------+--------+----------+-----------+
263 | | Mage_Core | 0.8.26 | Active | Enabled | core |
264 | | Mage_Eav | 0.7.15 | Active | Enabled | core |
265 | | Mage_Page | 0.7.0 | Active | Enabled | core |
266 | | Mage_Install | 0.7.0 | Active | Enabled | core |
267 | | ... | ... | ... | ... | ... |
268 | +------------------------------+------------+--------+----------+-----------+
269 |
270 |
271 | ### module-enable <module> [<module2>, ..., <modulen>]
272 |
273 | Enables one or more modules by modifying their config file's active flag.
274 |
275 | ### module-disable <module> [<module2>, ..., <modulen>]
276 |
277 | Disables one or more modules by modifying their config file's active flag.
278 |
279 | ### module-enableoutput <module> [<module2>, ..., <modulen>]
280 |
281 | Enables output for one or more modules.
282 |
283 | ### module-disableoutput <module> [<module2>, ..., <modulen>]
284 |
285 | Disables output for one or more modules.
286 |
287 | ### sql-info
288 |
289 | Shows Magento's SQL configuration.
290 |
291 | ### sql-cli
292 |
293 | Launches a MySQL command line session directly to Magento's database.
294 |
295 | ### sql-exec <query>
296 |
297 | Executes a query against the Magento database.
298 |
299 | ### store-list
300 |
301 | Shows a list of stores, groups, and websites. Like a boss.
302 |
303 | ### command-list
304 |
305 | Lists all of the available commands. This will run by default.
306 |
307 | ### help
308 |
309 | Displays more information about a command. These are pulled from the Docblocks in the source code.
310 |
311 | ## License
312 |
313 | Wiz is licensed under the [OSL 3.0](http://opensource.org/licenses/osl-3.0.php).
314 |
--------------------------------------------------------------------------------
/app/Wiz.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | ini_set('date.timezone', 'America/Chicago');
22 | error_reporting(-1);
23 | require 'lib/Wiz/SimpleXmlElement.php';
24 | ini_set('display_errors', 1);
25 |
26 | define('WIZ_DS', DIRECTORY_SEPARATOR);
27 |
28 | /**
29 | * Primary Wiz class. Sets up the application and gets everything going. okay?
30 | *
31 | * @package default
32 | * @author Nicholas Vahalik
33 | */
34 | class Wiz {
35 |
36 | const WIZ_VERSION = '0.9.8';
37 |
38 | static private $config;
39 |
40 | public static function getWiz() {
41 | static $_wiz;
42 | if (!is_object($_wiz)) {
43 | $_wiz = new Wiz();
44 | }
45 | return $_wiz;
46 | }
47 |
48 | public static function getVersion() {
49 | return Wiz::WIZ_VERSION;
50 | }
51 |
52 | function __construct($args = null) {
53 | $this->pluginDirectory = dirname(__FILE__). WIZ_DS . 'plugins';
54 | $this->_findPlugins();
55 | $this->_parseArgs();
56 | }
57 |
58 | static function getUserConfig() {
59 | $options = array();
60 | if (file_exists($_SERVER['HOME'].'/.wizrc')) {
61 | parse_str(strtr(file_get_contents($_SERVER['HOME'].'/.wizrc'), PHP_EOL, '&'), $options);
62 | }
63 | return $options;
64 | }
65 |
66 | static function setUserConfig($options) {
67 | file_put_contents(realpath($_SERVER['HOME'].'/.wizrc'), rawurldecode(http_build_query($options, '', PHP_EOL)));
68 | }
69 |
70 | public static function getConfigPath($path) {
71 | return (string)self::getConfig()->descend($path);
72 | }
73 |
74 | public static function getConfig() {
75 | if (empty(self::$config)) {
76 | $potentialFilesToLoad = array(
77 | dirname(__FILE__) . WIZ_DS . 'config.xml',
78 | dirname(__FILE__) . WIZ_DS . '..' . WIZ_DS . 'config.xml',
79 | $_SERVER['HOME'] . WIZ_DS . '.wiz.xml',
80 | );
81 |
82 | self::$config = simplexml_load_string('', 'Wiz_Simplexml_Element');
83 | foreach ($potentialFilesToLoad as $filePath) {
84 | if (file_exists($filePath)) {
85 | self::$config->extendByFile($filePath);
86 | }
87 | }
88 | }
89 |
90 | return self::$config;
91 | }
92 |
93 | static function saveConfig() {
94 | file_put_contents($_SERVER['HOME'] . WIZ_DS . '.wiz.xml', ''.PHP_EOL.Wiz::getConfig()->asNiceXml());
95 | }
96 |
97 | static function getMagentoRoot() {
98 | static $magentoRoot = FALSE;
99 | if ($magentoRoot === FALSE) {
100 | $wizMagentoRoot = getenv('WIZ_MAGE_ROOT') ? getenv('WIZ_MAGE_ROOT') : getcwd();
101 |
102 | // Run through all of the options until either we find something, or we've run out of places to look.
103 | do {
104 | $magePhpPath = $wizMagentoRoot . WIZ_DS . 'app' . WIZ_DS . 'Mage.php';
105 | if ($magePhpIsNotFound = !is_readable($magePhpPath)) {
106 | $wizMagentoRoot = substr($wizMagentoRoot, 0, strrpos($wizMagentoRoot, WIZ_DS));
107 | }
108 | } while ($magePhpIsNotFound && strlen($wizMagentoRoot));
109 |
110 | if ($magePhpIsNotFound) {
111 | $wizMagentoRoot = FALSE;
112 | }
113 | }
114 | return $wizMagentoRoot;
115 | }
116 |
117 | /**
118 | * Instantiates and sets up Magento. By default, use the admin scopeCode so we run
119 | * inside of the administration context.
120 | *
121 | * @param string $scopeCode
122 | * @param string $scopeId
123 | * @return Mage_Core_Model_App
124 | * @author Nicholas Vahalik
125 | */
126 | public static function getMagento($scopeCode = 'admin', $scopeId = 'store') {
127 |
128 | /**
129 | * Our local copy of the Magento Application Object
130 | *
131 | * @see Mage_Core_Model_App
132 | */
133 | static $_magento;
134 |
135 | if (!$_magento) {
136 | // Did we get a directory from an environment variable?
137 | $wizMagentoRoot = Wiz::getMagentoRoot();
138 |
139 | // No dice. :-(
140 | if ($wizMagentoRoot === FALSE) {
141 | die ('Please specify a Magento root directory by setting WIZ_MAGE_ROOT.'.PHP_EOL);
142 | }
143 |
144 | chdir($wizMagentoRoot);
145 |
146 | /**
147 | * Attempt to bootstrap Magento.
148 | */
149 | $compilerConfig = 'includes/config.php';
150 | if (file_exists($compilerConfig)) {
151 | include $compilerConfig;
152 | }
153 |
154 | require 'app/Mage.php';
155 |
156 | umask(0);
157 |
158 | // If someone passes a scope code via he CLI, then use that.
159 | foreach (array('store', 'website') as $scope) {
160 | if (($argScopeCode = Wiz::getWiz()->getArg($scope)) !== FALSE) {
161 | // If --store is specified, but not provided, use the default.
162 | $scopeCode = $argScopeCode === TRUE ? '' : $argScopeCode;
163 | $scopeId = $scope;
164 | break;
165 | }
166 | }
167 |
168 | $_magento = Mage::app($scopeCode, $scopeId);
169 |
170 | // We only want to enable profiling if it has been turned on within the
171 | // configuration AND if the --profile argument was passed into the command.
172 | if(Mage::getStoreConfig('dev/debug/profiler') && Wiz::getWiz()->getArg('profile')){
173 | Varien_Profiler::enable();
174 | }
175 | }
176 | return $_magento;
177 | }
178 |
179 | public function versionAction() {
180 | echo 'Version: '.Wiz::WIZ_VERSION;
181 | }
182 |
183 | public function updateAction() {
184 |
185 | $latestVersion = file_get_contents('http://wizcli.com/latest-version');
186 | echo 'Current Wiz Version: ' . self::WIZ_VERSION . PHP_EOL;
187 | if (version_compare(self::WIZ_VERSION, $latestVersion, 'lt')) {
188 | // There is an upgrade available.
189 | echo 'Latest Wiz Version: ' . $latestVersion . PHP_EOL;
190 | echo 'An upgrade is available.' . PHP_EOL;
191 | while (1) {
192 | echo 'Do you wish to upgrade? [y,n] ';
193 | $input = strtolower(trim(fgets(STDIN)));
194 | if (in_array(strtolower($input), array('y', 'n'))) {
195 | break;
196 | }
197 | }
198 | if ($input == 'n') {
199 | echo 'Upgrade cancelled.' . PHP_EOL;
200 | }
201 | else {
202 | // Aw snap, it's on now!
203 | $ourDirectory = dirname(dirname(__FILE__));
204 |
205 | // Do a quick sanity check to ensure that we "own" the directory.
206 | $objectsInOurDirectory = scandir(dirname(dirname(__FILE__)));
207 |
208 | // Only enable auto-upgrade if we have our own directory. This will leave some
209 | // people out, but for now it appears most people have it in ~/bin.
210 | if (count($objectsInOurDirectory) <= 7
211 | && in_array('wiz.php', $objectsInOurDirectory)
212 | && in_array('app', $objectsInOurDirectory)
213 | && in_array('wiz', $objectsInOurDirectory)) {
214 | $parentDir = dirname($ourDirectory);
215 | // Then it looks like it is ours... we can go ahead and do the upgrade.
216 | if (is_writable($parentDir)) {
217 | require 'lib/PEAR.php';
218 | require 'lib/Archive/Tar.php';
219 | $latestVersionFile = new Archive_Tar('http://wizcli.com/files/wiz-latest.tgz');
220 | // If the file loaded properly, extract the contents over the current directory.
221 | if (count($latestVersionFile->listContent()) > 0) {
222 | $cwd = getcwd();
223 | chdir($parentDir);
224 | echo 'Removing current directory.' . PHP_EOL;
225 | $this->rrmdir($ourDirectory);
226 | echo 'Extracting files...';
227 | $latestVersionFile->extract($parentDir);
228 | echo 'done.' . PHP_EOL;
229 | }
230 | else {
231 | echo 'There was a problem downloading the latest version. Unable to continue.' . PHP_EOL;
232 | }
233 | }
234 | }
235 | }
236 | }
237 | else {
238 | echo 'You are already running the latest version.' . PHP_EOL;
239 | }
240 |
241 | // Check the remote service to see what the latest version of Wiz is.
242 | }
243 |
244 | private function rrmdir($dir) {
245 | if (is_dir($dir)) {
246 | $objects = scandir($dir);
247 | foreach ($objects as $object) {
248 | if ($object != "." && $object != "..") {
249 | if (filetype($dir."/".$object) == "dir") $this->rrmdir($dir."/".$object); else unlink($dir."/".$object);
250 | }
251 | }
252 | reset($objects);
253 | rmdir($dir);
254 | }
255 | }
256 |
257 | private function _findPlugins() {
258 |
259 | $plugins = array();
260 | $pluginFiles = new DirectoryIterator($this->pluginDirectory);
261 |
262 | foreach ($pluginFiles as $file) {
263 | $fileExtension = substr($file->getFilename(), -3);
264 | if ($file->isFile() && $fileExtension == "php") {
265 | require($file->getPathname());
266 | $plugins[] = basename($file->getFilename(), '.php');
267 | }
268 | }
269 |
270 | foreach ($plugins as $pluginName) {
271 | $pluginClass = 'Wiz_Plugin_' . $pluginName;
272 | $pluginInstance = new $pluginClass();
273 | foreach ($pluginInstance->getActions() as $action) {
274 | $this->_availableCommands[strtolower($pluginName).'-'.$action] = array(
275 | 'class' => $pluginClass,
276 | 'method' => $action.'Action'
277 | );
278 | }
279 | }
280 | $this->_availableCommands['command-list'] = array(
281 | 'class' => 'Wiz',
282 | 'method' => 'listActions'
283 | );
284 | $this->_availableCommands['help'] = array(
285 | 'class' => 'Wiz',
286 | 'method' => 'helpAction'
287 | );
288 | $this->_availableCommands['update'] = array(
289 | 'class' => 'Wiz',
290 | 'method' => 'updateAction'
291 | );
292 | foreach ($this->_availableCommands as $commandName => $commandArray) {
293 | $functionInfo = new ReflectionMethod($commandArray['class'], $commandArray['method']);
294 | $comment = $functionInfo->getDocComment();
295 | if ($comment) {
296 | $comment = preg_replace('#^\s+\* ?#m', '', substr($comment, 3, -2));
297 | $this->_availableCommands[$commandName]['documentation'] = $comment;
298 | }
299 | }
300 | }
301 |
302 | /**
303 | * Gives you help on a command. For simplicity's sake, it just returns the Comment
304 | * block in the source code.
305 | *
306 | * @param string Command to get help on.
307 | * @author Nicholas Vahalik
308 | */
309 | public function helpAction($options) {
310 | $command = array_shift($options);
311 |
312 | if ($command == '') $command = 'help';
313 |
314 | if (array_key_exists($command, $this->_availableCommands)) {
315 | if (array_key_exists('documentation', $this->_availableCommands[$command])) {
316 | echo "Help for $command:".PHP_EOL.PHP_EOL;
317 | echo $this->_availableCommands[$command]['documentation'].PHP_EOL;
318 | }
319 | else {
320 | echo "No help available for: $command".PHP_EOL;
321 | }
322 | }
323 | else {
324 | echo "Unknown command: $command".PHP_EOL;
325 | }
326 | }
327 |
328 | /**
329 | * List all available actions that Wiz can perform.
330 | *
331 | * @return void
332 | * @author Nicholas Vahalik
333 | */
334 | public function listActions() {
335 | echo PHP_EOL;
336 | echo 'Available commands: '.PHP_EOL;
337 | echo PHP_EOL;
338 | foreach ($this->_availableCommands as $commandName => $commandArray) {
339 | if(!array_key_exists('documentation', $commandArray) || trim($commandArray['documentation']) == '') {
340 | continue;
341 | }
342 | $docLines = explode(PHP_EOL, $commandArray['documentation']);
343 | $docLineOne = array_shift($docLines);
344 | if (($endOfSentence = strpos($docLineOne, '.')) !== FALSE) {
345 | $docLineOne = substr($docLineOne, 0, $endOfSentence + 1);
346 | }
347 | printf(' %-23s %s' . PHP_EOL, $commandName, $docLineOne);
348 | }
349 | echo PHP_EOL;
350 | }
351 |
352 | function _initWiz() {
353 | // Look for a configuration in .wizrc
354 | if (file_exists('~/.wizrc')) {
355 | $configurationOptions = file_get_contents('~/.wizrc');
356 | }
357 | }
358 |
359 | public function run() {
360 | $argv = $_SERVER['argv'];
361 |
362 | // If the first item is us. We don't need it.
363 | if (count($argv) == 1 && $argv[0] == dirname(dirname(__FILE__)) . WIZ_DS . 'wiz.php') {
364 | array_shift($argv);
365 | }
366 |
367 | // Next item is the command
368 | $command = array_shift($argv);
369 |
370 | // Attempt to run the command.
371 | if (array_key_exists($command, $this->_availableCommands)) {
372 | if ($this->_availableCommands[$command]['class'] == __CLASS__) {
373 | $pluginInstance = $this;
374 | }
375 | else {
376 | $pluginInstance = new $this->_availableCommands[$command]['class']();
377 | }
378 | try {
379 | $pluginInstance->{$this->_availableCommands[$command]['method']}($argv);
380 | } catch(Exception $e) {
381 | echo 'An error occured while processing the command: ' . $command . PHP_EOL;
382 | echo $e->getMessage() . PHP_EOL;
383 | }
384 | }
385 | elseif ($command == '') {
386 | echo $this->getHelp();
387 | }
388 | else {
389 | echo 'Unable to find that command: ' . $command . PHP_EOL;
390 | }
391 | }
392 |
393 | public function getHelp() {
394 | $helpText = 'Wiz v'.Wiz::WIZ_VERSION.PHP_EOL;
395 | $helpText .= 'Provides a CLI interface to get information from, script, and help you manage'.PHP_EOL;
396 | $helpText .= 'your Magento installation.'.PHP_EOL;
397 | $helpText .= PHP_EOL;
398 | $helpText .= 'Usage:';
399 | $helpText .= PHP_EOL;
400 | $helpText .= ' wiz [global-options] [command-options]';
401 | $helpText .= PHP_EOL;
402 | $helpText .= ' Runs a command.';
403 | $helpText .= PHP_EOL;
404 | $helpText .= PHP_EOL;
405 | $helpText .= ' wiz help ';
406 | $helpText .= PHP_EOL;
407 | $helpText .= ' Returns help on a command.';
408 | $helpText .= PHP_EOL;
409 | $helpText .= PHP_EOL;
410 | $helpText .= ' wiz command-list';
411 | $helpText .= PHP_EOL;
412 | $helpText .= ' Returns the list of available commands.';
413 | $helpText .= PHP_EOL;
414 | $helpText .= PHP_EOL;
415 | $helpText .= 'Global Options:';
416 | $helpText .= PHP_EOL;
417 | $helpText .= ' --batch [csv|pipe|tab]';
418 | $helpText .= PHP_EOL;
419 | $helpText .= ' Returns tabular data in a parseable format. Defaults to "csv"';
420 | $helpText .= PHP_EOL;
421 | $helpText .= PHP_EOL;
422 | $helpText .= ' --store ,';
423 | $helpText .= PHP_EOL;
424 | $helpText .= ' --website ';
425 | $helpText .= PHP_EOL;
426 | $helpText .= ' Executes Magento as this particular store or website.';
427 | $helpText .= PHP_EOL;
428 | $helpText .= PHP_EOL;
429 | return $helpText . PHP_EOL;
430 | }
431 |
432 | public static function inspect() {
433 | $args = func_get_args();
434 | call_user_func_array('Wiz_Inspector::inspect', $args);
435 | }
436 |
437 | /**
438 | * Parse input arguments, removing them as we find them.
439 | *
440 | * @return Wiz_Plugin_Abstract
441 | */
442 | protected function _parseArgs() {
443 | $current = $commandStart = $inCommand = false;
444 | $commandEnd = 1;
445 |
446 | foreach ($_SERVER['argv'] as $position => $arg) {
447 |
448 | if ($commandStart === FALSE && array_key_exists($arg, $this->_availableCommands)) {
449 | $commandStart = $position;
450 | $inCommand = TRUE;
451 | }
452 |
453 | $match = array();
454 | if (preg_match('#^--([\w\d_-]{1,})$#', $arg, $match) || preg_match('#^-([\w\d_]{1,})$#', $arg, $match)) {
455 | $inCommand = false;
456 | $current = $match[1];
457 | $this->_args[$current] = true;
458 | } else {
459 | if ($current) {
460 | $this->_args[$current] = $arg;
461 | } else if (!$inCommand && preg_match('#^([\w\d_]{1,})$#', $arg, $match)) {
462 | $this->_args[$match[1]] = true;
463 | } else {
464 | if ($inCommand && $commandStart != $position) {
465 | $commandEnd++;
466 | }
467 | }
468 | }
469 | }
470 | $_SERVER['argv'] = array_slice($_SERVER['argv'], $commandStart, $commandEnd);
471 | // var_dump($commandStart, $commandEnd);
472 | // var_dump($_SERVER['argv']);
473 | // var_dump($this->_args);
474 | return $this;
475 | }
476 |
477 | /**
478 | * Retrieve argument value by name or the default specified
479 | *
480 | * @param string $name the argument name
481 | * @return mixed
482 | */
483 | public function getArg($name, $default = false) {
484 | if (isset($this->_args[$name])) {
485 | return $this->_args[$name];
486 | }
487 | return $default;
488 | }
489 |
490 | /**
491 | * get the website code
492 | *
493 | * @return string
494 | * @author Kevin Kirchner
495 | **/
496 | public function getWebsiteCode()
497 | {
498 | $wiz = Wiz::getWiz();
499 | return $wiz->getArg('website') ? $wiz->getArg('website') : Mage::app()->getWebsite()->getCode();
500 | }
501 |
502 | /**
503 | * get the website code
504 | *
505 | * @return string
506 | * @author Kevin Kirchner
507 | **/
508 | public function getStoreCode()
509 | {
510 | $wiz = Wiz::getWiz();
511 | return $wiz->getArg('store') ? $wiz->getArg('store') : Mage::app()->getStore()->getCode();
512 | }
513 |
514 | /**
515 | * Modified version of the code at the site below:
516 | * @see http://www.pyrosoft.co.uk/blog/2007/07/01/php-array-to-text-table-function/
517 | */
518 | public static function tableOutput($table) {
519 | if (Wiz::getWiz()->getArg('batch')) {
520 | return Wiz::batchOutput($table);
521 | }
522 | else {
523 | return Wiz::prettyTableOutput($table);
524 | }
525 | }
526 |
527 | public static function batchOutput($table) {
528 | $format = Wiz::getWiz()->getArg('batch');
529 | if (!is_array($table) || count($table) < 1 || !is_array($table[0])) {
530 | $table = array(array('Result' => 'No Data'));
531 | }
532 |
533 | $keys = array_keys($table[0]);
534 | $delimiter = $enclosure = '"';
535 |
536 | array_unshift($table, $keys);
537 |
538 | switch ($format) {
539 | case 'csv':
540 | default:
541 | $delimiter = ',';
542 | $enclosure = '"';
543 | // Quickly put everything
544 | break;
545 | case 'pipe':
546 | $delimiter = '|';
547 | break;
548 | case 'tab':
549 | $delimiter = "\t";
550 | break;
551 | }
552 |
553 | // We use some memory here to quickly create a CSV file.
554 | $csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
555 | foreach ($table as $row) {
556 | fputcsv($csv, $row, $delimiter, $enclosure);
557 | }
558 | rewind($csv);
559 | $output = stream_get_contents($csv);
560 | return $output;
561 | }
562 |
563 | public static function prettyTableOutput($table) {
564 | if (!is_array($table) || count($table) < 1 || !is_array($table[0])) {
565 | $table = array(array('Result' => 'No Data'));
566 | }
567 | $keys = array_keys($table[0]);
568 | array_push($table, array_combine($keys, $keys));
569 | foreach ($table AS $row) {
570 | $cell_count = 0;
571 | foreach ($row AS $key=>$cell) {
572 | $cell_length = strlen($cell);
573 | $cell_count++;
574 | if (!isset($cell_lengths[$key]) || $cell_length > $cell_lengths[$key]) $cell_lengths[$key] = $cell_length;
575 | }
576 | }
577 | array_pop($table);
578 |
579 | // Build header bar
580 | $bar = '+';
581 | $header = '|';
582 | $i=0;
583 |
584 | foreach ($cell_lengths AS $fieldname => $length) {
585 | $i++;
586 | $bar .= str_pad('', $length+2, '-')."+";
587 |
588 | $name = $fieldname;
589 | if (strlen($name) > $length) {
590 | // crop long headings
591 |
592 | $name = substr($name, 0, $length-1);
593 | }
594 | $header .= ' '.str_pad($name, $length, ' ', STR_PAD_RIGHT) . " |";
595 |
596 | }
597 |
598 | $output = '';
599 |
600 | $output .= $bar."\n";
601 | $output .= $header."\n";
602 |
603 | $output .= $bar."\n";
604 |
605 | // Draw rows
606 |
607 | foreach ($table AS $row) {
608 | $output .= "|";
609 |
610 | if (is_array($row)) {
611 | foreach ($row AS $key=>$cell) {
612 | $output .= ' '.str_pad($cell, $cell_lengths[$key], ' ', STR_PAD_RIGHT) . " |";
613 | }
614 | }
615 | else {
616 | foreach ($cell_lengths AS $key=>$length) {
617 | $output .= str_repeat($row, $length+2) . '|';
618 | }
619 | }
620 | $output .= "\n";
621 | }
622 |
623 | $output .= $bar."\n";
624 | return $output;
625 | }
626 | }
627 |
628 | // This is probably not the best place for this, but it works for now.
629 | class Wiz_Plugin_Abstract {
630 | /**
631 | * Input arguments
632 | *
633 | * @var array
634 | */
635 | protected $_args = array();
636 |
637 | /**
638 | * Initialize application with code (store, website code)
639 | *
640 | * @var string
641 | */
642 | protected $_appCode = 'admin';
643 |
644 | /**
645 | * Initialize application code type (store, website, store_group)
646 | *
647 | * @var string
648 | */
649 | protected $_appType = 'store';
650 |
651 | /**
652 | * Constructor
653 | *
654 | * @author Nicholas Vahalik
655 | */
656 | public function __construct() {
657 | // $this->_parseArgs();
658 | }
659 |
660 | /**
661 | * Returns a list of actions that this plugin contains.
662 | *
663 | * @return array
664 | * @author Nicholas Vahalik
665 | */
666 | public function getActions() {
667 | $reflector = new ReflectionClass($this);
668 | foreach ($reflector->getMethods() as $reflectionMethod) {
669 | if (($commandLength = strpos($reflectionMethod->name, 'Action')) !== FALSE &&
670 | ($commandLength + 6) == strlen($reflectionMethod->name)) {
671 | $_commands[] = substr($reflectionMethod->name, 0, $commandLength);
672 | }
673 | }
674 | return $_commands;
675 | }
676 | }
677 |
678 | class Wiz_Inspector {
679 | public static function inspect() {
680 | $args = func_get_args();
681 | echo __METHOD__.PHP_EOL;
682 | $arg = $args[0];
683 | if (is_object($arg)) {
684 | echo 'Hierarchy:'.PHP_EOL;
685 | implode(','.PHP_EOL, self::getParents($arg));
686 | // var_dump($args);
687 | }
688 | }
689 |
690 | public static function getParents($object) {
691 | $class = new ReflectionClass($object);
692 | $parents = array();
693 | $a = 0;
694 |
695 | while ($parent = $class->getParentClass()) {
696 | if ($a++ == 5)
697 | break;
698 | // var_dump($parent);
699 | $parents[] = $parent->getName();
700 | // var_dump($parents);
701 | }
702 | return $parents;
703 | }
704 |
705 | public static function getMethods($object) {
706 | $a = new ReflectionClass($object);
707 | foreach ($a->getMethods() as $method) {
708 | var_dump($method);
709 | echo $method->name.PHP_EOL;
710 | }
711 | echo PHP_EOL.PHP_EOL;
712 | }
713 | }
714 |
--------------------------------------------------------------------------------
/app/lib/PEAR.php:
--------------------------------------------------------------------------------
1 |
18 | * @author Stig Bakken
19 | * @author Tomas V.V.Cox
20 | * @author Greg Beaver
21 | * @copyright 1997-2008 The PHP Group
22 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
23 | * @version CVS: $Id: PEAR.php,v 1.104 2008/01/03 20:26:34 cellog Exp $
24 | * @link http://pear.php.net/package/PEAR
25 | * @since File available since Release 0.1
26 | */
27 |
28 | /**#@+
29 | * ERROR constants
30 | */
31 | define('PEAR_ERROR_RETURN', 1);
32 | define('PEAR_ERROR_PRINT', 2);
33 | define('PEAR_ERROR_TRIGGER', 4);
34 | define('PEAR_ERROR_DIE', 8);
35 | define('PEAR_ERROR_CALLBACK', 16);
36 | /**
37 | * WARNING: obsolete
38 | * @deprecated
39 | */
40 | define('PEAR_ERROR_EXCEPTION', 32);
41 | /**#@-*/
42 | define('PEAR_ZE2', (function_exists('version_compare') &&
43 | version_compare(zend_version(), "2-dev", "ge")));
44 |
45 | if (substr(PHP_OS, 0, 3) == 'WIN') {
46 | define('OS_WINDOWS', true);
47 | define('OS_UNIX', false);
48 | define('PEAR_OS', 'Windows');
49 | } else {
50 | define('OS_WINDOWS', false);
51 | define('OS_UNIX', true);
52 | define('PEAR_OS', 'Unix'); // blatant assumption
53 | }
54 |
55 | // instant backwards compatibility
56 | if (!defined('PATH_SEPARATOR')) {
57 | if (OS_WINDOWS) {
58 | define('PATH_SEPARATOR', ';');
59 | } else {
60 | define('PATH_SEPARATOR', ':');
61 | }
62 | }
63 |
64 | $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
65 | $GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
66 | $GLOBALS['_PEAR_destructor_object_list'] = array();
67 | $GLOBALS['_PEAR_shutdown_funcs'] = array();
68 | $GLOBALS['_PEAR_error_handler_stack'] = array();
69 |
70 | @ini_set('track_errors', true);
71 |
72 | /**
73 | * Base class for other PEAR classes. Provides rudimentary
74 | * emulation of destructors.
75 | *
76 | * If you want a destructor in your class, inherit PEAR and make a
77 | * destructor method called _yourclassname (same name as the
78 | * constructor, but with a "_" prefix). Also, in your constructor you
79 | * have to call the PEAR constructor: $this->PEAR();.
80 | * The destructor method will be called without parameters. Note that
81 | * at in some SAPI implementations (such as Apache), any output during
82 | * the request shutdown (in which destructors are called) seems to be
83 | * discarded. If you need to get any debug information from your
84 | * destructor, use error_log(), syslog() or something similar.
85 | *
86 | * IMPORTANT! To use the emulated destructors you need to create the
87 | * objects by reference: $obj =& new PEAR_child;
88 | *
89 | * @category pear
90 | * @package PEAR
91 | * @author Stig Bakken
92 | * @author Tomas V.V. Cox
93 | * @author Greg Beaver
94 | * @copyright 1997-2006 The PHP Group
95 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
96 | * @version Release: 1.7.2
97 | * @link http://pear.php.net/package/PEAR
98 | * @see PEAR_Error
99 | * @since Class available since PHP 4.0.2
100 | * @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear
101 | */
102 | class PEAR
103 | {
104 | // {{{ properties
105 |
106 | /**
107 | * Whether to enable internal debug messages.
108 | *
109 | * @var bool
110 | * @access private
111 | */
112 | var $_debug = false;
113 |
114 | /**
115 | * Default error mode for this object.
116 | *
117 | * @var int
118 | * @access private
119 | */
120 | var $_default_error_mode = null;
121 |
122 | /**
123 | * Default error options used for this object when error mode
124 | * is PEAR_ERROR_TRIGGER.
125 | *
126 | * @var int
127 | * @access private
128 | */
129 | var $_default_error_options = null;
130 |
131 | /**
132 | * Default error handler (callback) for this object, if error mode is
133 | * PEAR_ERROR_CALLBACK.
134 | *
135 | * @var string
136 | * @access private
137 | */
138 | var $_default_error_handler = '';
139 |
140 | /**
141 | * Which class to use for error objects.
142 | *
143 | * @var string
144 | * @access private
145 | */
146 | var $_error_class = 'PEAR_Error';
147 |
148 | /**
149 | * An array of expected errors.
150 | *
151 | * @var array
152 | * @access private
153 | */
154 | var $_expected_errors = array();
155 |
156 | // }}}
157 |
158 | // {{{ constructor
159 |
160 | /**
161 | * Constructor. Registers this object in
162 | * $_PEAR_destructor_object_list for destructor emulation if a
163 | * destructor object exists.
164 | *
165 | * @param string $error_class (optional) which class to use for
166 | * error objects, defaults to PEAR_Error.
167 | * @access public
168 | * @return void
169 | */
170 | function PEAR($error_class = null)
171 | {
172 | $classname = strtolower(get_class($this));
173 | if ($this->_debug) {
174 | print "PEAR constructor called, class=$classname\n";
175 | }
176 | if ($error_class !== null) {
177 | $this->_error_class = $error_class;
178 | }
179 | while ($classname && strcasecmp($classname, "pear")) {
180 | $destructor = "_$classname";
181 | if (method_exists($this, $destructor)) {
182 | global $_PEAR_destructor_object_list;
183 | $_PEAR_destructor_object_list[] = &$this;
184 | if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
185 | register_shutdown_function("_PEAR_call_destructors");
186 | $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
187 | }
188 | break;
189 | } else {
190 | $classname = get_parent_class($classname);
191 | }
192 | }
193 | }
194 |
195 | // }}}
196 | // {{{ destructor
197 |
198 | /**
199 | * Destructor (the emulated type of...). Does nothing right now,
200 | * but is included for forward compatibility, so subclass
201 | * destructors should always call it.
202 | *
203 | * See the note in the class desciption about output from
204 | * destructors.
205 | *
206 | * @access public
207 | * @return void
208 | */
209 | function _PEAR() {
210 | if ($this->_debug) {
211 | printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
212 | }
213 | }
214 |
215 | // }}}
216 | // {{{ getStaticProperty()
217 |
218 | /**
219 | * If you have a class that's mostly/entirely static, and you need static
220 | * properties, you can use this method to simulate them. Eg. in your method(s)
221 | * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
222 | * You MUST use a reference, or they will not persist!
223 | *
224 | * @access public
225 | * @param string $class The calling classname, to prevent clashes
226 | * @param string $var The variable to retrieve.
227 | * @return mixed A reference to the variable. If not set it will be
228 | * auto initialised to NULL.
229 | */
230 | public static function &getStaticProperty($class, $var)
231 | {
232 | static $properties;
233 | if (!isset($properties[$class])) {
234 | $properties[$class] = array();
235 | }
236 | if (!array_key_exists($var, $properties[$class])) {
237 | $properties[$class][$var] = null;
238 | }
239 | return $properties[$class][$var];
240 | }
241 |
242 | // }}}
243 | // {{{ registerShutdownFunc()
244 |
245 | /**
246 | * Use this function to register a shutdown method for static
247 | * classes.
248 | *
249 | * @access public
250 | * @param mixed $func The function name (or array of class/method) to call
251 | * @param mixed $args The arguments to pass to the function
252 | * @return void
253 | */
254 | function registerShutdownFunc($func, $args = array())
255 | {
256 | // if we are called statically, there is a potential
257 | // that no shutdown func is registered. Bug #6445
258 | if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
259 | register_shutdown_function("_PEAR_call_destructors");
260 | $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
261 | }
262 | $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
263 | }
264 |
265 | // }}}
266 | // {{{ isError()
267 |
268 | /**
269 | * Tell whether a value is a PEAR error.
270 | *
271 | * @param mixed $data the value to test
272 | * @param int $code if $data is an error object, return true
273 | * only if $code is a string and
274 | * $obj->getMessage() == $code or
275 | * $code is an integer and $obj->getCode() == $code
276 | * @access public
277 | * @return bool true if parameter is an error
278 | */
279 | public static function isError($data, $code = null)
280 | {
281 | if ($data instanceof PEAR_Error) {
282 | if (is_null($code)) {
283 | return true;
284 | } elseif (is_string($code)) {
285 | return $data->getMessage() == $code;
286 | } else {
287 | return $data->getCode() == $code;
288 | }
289 | }
290 | return false;
291 | }
292 |
293 | // }}}
294 | // {{{ setErrorHandling()
295 |
296 | /**
297 | * Sets how errors generated by this object should be handled.
298 | * Can be invoked both in objects and statically. If called
299 | * statically, setErrorHandling sets the default behaviour for all
300 | * PEAR objects. If called in an object, setErrorHandling sets
301 | * the default behaviour for that object.
302 | *
303 | * @param int $mode
304 | * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
305 | * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
306 | * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
307 | *
308 | * @param mixed $options
309 | * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
310 | * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
311 | *
312 | * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
313 | * to be the callback function or method. A callback
314 | * function is a string with the name of the function, a
315 | * callback method is an array of two elements: the element
316 | * at index 0 is the object, and the element at index 1 is
317 | * the name of the method to call in the object.
318 | *
319 | * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
320 | * a printf format string used when printing the error
321 | * message.
322 | *
323 | * @access public
324 | * @return void
325 | * @see PEAR_ERROR_RETURN
326 | * @see PEAR_ERROR_PRINT
327 | * @see PEAR_ERROR_TRIGGER
328 | * @see PEAR_ERROR_DIE
329 | * @see PEAR_ERROR_CALLBACK
330 | * @see PEAR_ERROR_EXCEPTION
331 | *
332 | * @since PHP 4.0.5
333 | */
334 |
335 | function setErrorHandling($mode = null, $options = null)
336 | {
337 | if (isset($this) && is_a($this, 'PEAR')) {
338 | $setmode = &$this->_default_error_mode;
339 | $setoptions = &$this->_default_error_options;
340 | } else {
341 | $setmode = &$GLOBALS['_PEAR_default_error_mode'];
342 | $setoptions = &$GLOBALS['_PEAR_default_error_options'];
343 | }
344 |
345 | switch ($mode) {
346 | case PEAR_ERROR_EXCEPTION:
347 | case PEAR_ERROR_RETURN:
348 | case PEAR_ERROR_PRINT:
349 | case PEAR_ERROR_TRIGGER:
350 | case PEAR_ERROR_DIE:
351 | case null:
352 | $setmode = $mode;
353 | $setoptions = $options;
354 | break;
355 |
356 | case PEAR_ERROR_CALLBACK:
357 | $setmode = $mode;
358 | // class/object method callback
359 | if (is_callable($options)) {
360 | $setoptions = $options;
361 | } else {
362 | trigger_error("invalid error callback", E_USER_WARNING);
363 | }
364 | break;
365 |
366 | default:
367 | trigger_error("invalid error mode", E_USER_WARNING);
368 | break;
369 | }
370 | }
371 |
372 | // }}}
373 | // {{{ expectError()
374 |
375 | /**
376 | * This method is used to tell which errors you expect to get.
377 | * Expected errors are always returned with error mode
378 | * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
379 | * and this method pushes a new element onto it. The list of
380 | * expected errors are in effect until they are popped off the
381 | * stack with the popExpect() method.
382 | *
383 | * Note that this method can not be called statically
384 | *
385 | * @param mixed $code a single error code or an array of error codes to expect
386 | *
387 | * @return int the new depth of the "expected errors" stack
388 | * @access public
389 | */
390 | function expectError($code = '*')
391 | {
392 | if (is_array($code)) {
393 | array_push($this->_expected_errors, $code);
394 | } else {
395 | array_push($this->_expected_errors, array($code));
396 | }
397 | return sizeof($this->_expected_errors);
398 | }
399 |
400 | // }}}
401 | // {{{ popExpect()
402 |
403 | /**
404 | * This method pops one element off the expected error codes
405 | * stack.
406 | *
407 | * @return array the list of error codes that were popped
408 | */
409 | function popExpect()
410 | {
411 | return array_pop($this->_expected_errors);
412 | }
413 |
414 | // }}}
415 | // {{{ _checkDelExpect()
416 |
417 | /**
418 | * This method checks unsets an error code if available
419 | *
420 | * @param mixed error code
421 | * @return bool true if the error code was unset, false otherwise
422 | * @access private
423 | * @since PHP 4.3.0
424 | */
425 | function _checkDelExpect($error_code)
426 | {
427 | $deleted = false;
428 |
429 | foreach ($this->_expected_errors AS $key => $error_array) {
430 | if (in_array($error_code, $error_array)) {
431 | unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
432 | $deleted = true;
433 | }
434 |
435 | // clean up empty arrays
436 | if (0 == count($this->_expected_errors[$key])) {
437 | unset($this->_expected_errors[$key]);
438 | }
439 | }
440 | return $deleted;
441 | }
442 |
443 | // }}}
444 | // {{{ delExpect()
445 |
446 | /**
447 | * This method deletes all occurences of the specified element from
448 | * the expected error codes stack.
449 | *
450 | * @param mixed $error_code error code that should be deleted
451 | * @return mixed list of error codes that were deleted or error
452 | * @access public
453 | * @since PHP 4.3.0
454 | */
455 | function delExpect($error_code)
456 | {
457 | $deleted = false;
458 |
459 | if ((is_array($error_code) && (0 != count($error_code)))) {
460 | // $error_code is a non-empty array here;
461 | // we walk through it trying to unset all
462 | // values
463 | foreach($error_code as $key => $error) {
464 | if ($this->_checkDelExpect($error)) {
465 | $deleted = true;
466 | } else {
467 | $deleted = false;
468 | }
469 | }
470 | return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
471 | } elseif (!empty($error_code)) {
472 | // $error_code comes alone, trying to unset it
473 | if ($this->_checkDelExpect($error_code)) {
474 | return true;
475 | } else {
476 | return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
477 | }
478 | } else {
479 | // $error_code is empty
480 | return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
481 | }
482 | }
483 |
484 | // }}}
485 | // {{{ raiseError()
486 |
487 | /**
488 | * This method is a wrapper that returns an instance of the
489 | * configured error class with this object's default error
490 | * handling applied. If the $mode and $options parameters are not
491 | * specified, the object's defaults are used.
492 | *
493 | * @param mixed $message a text error message or a PEAR error object
494 | *
495 | * @param int $code a numeric error code (it is up to your class
496 | * to define these if you want to use codes)
497 | *
498 | * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
499 | * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
500 | * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
501 | *
502 | * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
503 | * specifies the PHP-internal error level (one of
504 | * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
505 | * If $mode is PEAR_ERROR_CALLBACK, this
506 | * parameter specifies the callback function or
507 | * method. In other error modes this parameter
508 | * is ignored.
509 | *
510 | * @param string $userinfo If you need to pass along for example debug
511 | * information, this parameter is meant for that.
512 | *
513 | * @param string $error_class The returned error object will be
514 | * instantiated from this class, if specified.
515 | *
516 | * @param bool $skipmsg If true, raiseError will only pass error codes,
517 | * the error message parameter will be dropped.
518 | *
519 | * @access public
520 | * @return object a PEAR error object
521 | * @see PEAR::setErrorHandling
522 | * @since PHP 4.0.5
523 | */
524 | public static function raiseError($message = null,
525 | $code = null,
526 | $mode = null,
527 | $options = null,
528 | $userinfo = null,
529 | $error_class = null,
530 | $skipmsg = false)
531 | {
532 | // The error is yet a PEAR error object
533 | if (is_object($message)) {
534 | $code = $message->getCode();
535 | $userinfo = $message->getUserInfo();
536 | $error_class = $message->getType();
537 | $message->error_message_prefix = '';
538 | $message = $message->getMessage();
539 | }
540 |
541 | if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
542 | if ($exp[0] == "*" ||
543 | (is_int(reset($exp)) && in_array($code, $exp)) ||
544 | (is_string(reset($exp)) && in_array($message, $exp))) {
545 | $mode = PEAR_ERROR_RETURN;
546 | }
547 | }
548 | // No mode given, try global ones
549 | if ($mode === null) {
550 | // Class error handler
551 | if (isset($this) && isset($this->_default_error_mode)) {
552 | $mode = $this->_default_error_mode;
553 | $options = $this->_default_error_options;
554 | // Global error handler
555 | } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
556 | $mode = $GLOBALS['_PEAR_default_error_mode'];
557 | $options = $GLOBALS['_PEAR_default_error_options'];
558 | }
559 | }
560 |
561 | if ($error_class !== null) {
562 | $ec = $error_class;
563 | } elseif (isset($this) && isset($this->_error_class)) {
564 | $ec = $this->_error_class;
565 | } else {
566 | $ec = 'PEAR_Error';
567 | }
568 | if (intval(PHP_VERSION) < 5) {
569 | // little non-eval hack to fix bug #12147
570 | include 'PEAR/FixPHP5PEARWarnings.php';
571 | return $a;
572 | }
573 | if ($skipmsg) {
574 | $a = new $ec($code, $mode, $options, $userinfo);
575 | } else {
576 | $a = new $ec($message, $code, $mode, $options, $userinfo);
577 | }
578 | return $a;
579 | }
580 |
581 | // }}}
582 | // {{{ throwError()
583 |
584 | /**
585 | * Simpler form of raiseError with fewer options. In most cases
586 | * message, code and userinfo are enough.
587 | *
588 | * @param string $message
589 | *
590 | */
591 | function &throwError($message = null,
592 | $code = null,
593 | $userinfo = null)
594 | {
595 | if (isset($this) && is_a($this, 'PEAR')) {
596 | $a = &$this->raiseError($message, $code, null, null, $userinfo);
597 | return $a;
598 | } else {
599 | $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
600 | return $a;
601 | }
602 | }
603 |
604 | // }}}
605 | function staticPushErrorHandling($mode, $options = null)
606 | {
607 | $stack = &$GLOBALS['_PEAR_error_handler_stack'];
608 | $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
609 | $def_options = &$GLOBALS['_PEAR_default_error_options'];
610 | $stack[] = array($def_mode, $def_options);
611 | switch ($mode) {
612 | case PEAR_ERROR_EXCEPTION:
613 | case PEAR_ERROR_RETURN:
614 | case PEAR_ERROR_PRINT:
615 | case PEAR_ERROR_TRIGGER:
616 | case PEAR_ERROR_DIE:
617 | case null:
618 | $def_mode = $mode;
619 | $def_options = $options;
620 | break;
621 |
622 | case PEAR_ERROR_CALLBACK:
623 | $def_mode = $mode;
624 | // class/object method callback
625 | if (is_callable($options)) {
626 | $def_options = $options;
627 | } else {
628 | trigger_error("invalid error callback", E_USER_WARNING);
629 | }
630 | break;
631 |
632 | default:
633 | trigger_error("invalid error mode", E_USER_WARNING);
634 | break;
635 | }
636 | $stack[] = array($mode, $options);
637 | return true;
638 | }
639 |
640 | function staticPopErrorHandling()
641 | {
642 | $stack = &$GLOBALS['_PEAR_error_handler_stack'];
643 | $setmode = &$GLOBALS['_PEAR_default_error_mode'];
644 | $setoptions = &$GLOBALS['_PEAR_default_error_options'];
645 | array_pop($stack);
646 | list($mode, $options) = $stack[sizeof($stack) - 1];
647 | array_pop($stack);
648 | switch ($mode) {
649 | case PEAR_ERROR_EXCEPTION:
650 | case PEAR_ERROR_RETURN:
651 | case PEAR_ERROR_PRINT:
652 | case PEAR_ERROR_TRIGGER:
653 | case PEAR_ERROR_DIE:
654 | case null:
655 | $setmode = $mode;
656 | $setoptions = $options;
657 | break;
658 |
659 | case PEAR_ERROR_CALLBACK:
660 | $setmode = $mode;
661 | // class/object method callback
662 | if (is_callable($options)) {
663 | $setoptions = $options;
664 | } else {
665 | trigger_error("invalid error callback", E_USER_WARNING);
666 | }
667 | break;
668 |
669 | default:
670 | trigger_error("invalid error mode", E_USER_WARNING);
671 | break;
672 | }
673 | return true;
674 | }
675 |
676 | // {{{ pushErrorHandling()
677 |
678 | /**
679 | * Push a new error handler on top of the error handler options stack. With this
680 | * you can easily override the actual error handler for some code and restore
681 | * it later with popErrorHandling.
682 | *
683 | * @param mixed $mode (same as setErrorHandling)
684 | * @param mixed $options (same as setErrorHandling)
685 | *
686 | * @return bool Always true
687 | *
688 | * @see PEAR::setErrorHandling
689 | */
690 | function pushErrorHandling($mode, $options = null)
691 | {
692 | $stack = &$GLOBALS['_PEAR_error_handler_stack'];
693 | if (isset($this) && is_a($this, 'PEAR')) {
694 | $def_mode = &$this->_default_error_mode;
695 | $def_options = &$this->_default_error_options;
696 | } else {
697 | $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
698 | $def_options = &$GLOBALS['_PEAR_default_error_options'];
699 | }
700 | $stack[] = array($def_mode, $def_options);
701 |
702 | if (isset($this) && is_a($this, 'PEAR')) {
703 | $this->setErrorHandling($mode, $options);
704 | } else {
705 | PEAR::setErrorHandling($mode, $options);
706 | }
707 | $stack[] = array($mode, $options);
708 | return true;
709 | }
710 |
711 | // }}}
712 | // {{{ popErrorHandling()
713 |
714 | /**
715 | * Pop the last error handler used
716 | *
717 | * @return bool Always true
718 | *
719 | * @see PEAR::pushErrorHandling
720 | */
721 | function popErrorHandling()
722 | {
723 | $stack = &$GLOBALS['_PEAR_error_handler_stack'];
724 | array_pop($stack);
725 | list($mode, $options) = $stack[sizeof($stack) - 1];
726 | array_pop($stack);
727 | if (isset($this) && is_a($this, 'PEAR')) {
728 | $this->setErrorHandling($mode, $options);
729 | } else {
730 | PEAR::setErrorHandling($mode, $options);
731 | }
732 | return true;
733 | }
734 |
735 | // }}}
736 | // {{{ loadExtension()
737 |
738 | /**
739 | * OS independant PHP extension load. Remember to take care
740 | * on the correct extension name for case sensitive OSes.
741 | *
742 | * @param string $ext The extension name
743 | * @return bool Success or not on the dl() call
744 | */
745 | function loadExtension($ext)
746 | {
747 | if (!extension_loaded($ext)) {
748 | // if either returns true dl() will produce a FATAL error, stop that
749 | if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
750 | return false;
751 | }
752 | if (OS_WINDOWS) {
753 | $suffix = '.dll';
754 | } elseif (PHP_OS == 'HP-UX') {
755 | $suffix = '.sl';
756 | } elseif (PHP_OS == 'AIX') {
757 | $suffix = '.a';
758 | } elseif (PHP_OS == 'OSX') {
759 | $suffix = '.bundle';
760 | } else {
761 | $suffix = '.so';
762 | }
763 | return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
764 | }
765 | return true;
766 | }
767 |
768 | // }}}
769 | }
770 |
771 | // {{{ _PEAR_call_destructors()
772 |
773 | function _PEAR_call_destructors()
774 | {
775 | global $_PEAR_destructor_object_list;
776 | if (is_array($_PEAR_destructor_object_list) &&
777 | sizeof($_PEAR_destructor_object_list))
778 | {
779 | reset($_PEAR_destructor_object_list);
780 | if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
781 | $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
782 | }
783 | while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
784 | $classname = get_class($objref);
785 | while ($classname) {
786 | $destructor = "_$classname";
787 | if (method_exists($objref, $destructor)) {
788 | $objref->$destructor();
789 | break;
790 | } else {
791 | $classname = get_parent_class($classname);
792 | }
793 | }
794 | }
795 | // Empty the object list to ensure that destructors are
796 | // not called more than once.
797 | $_PEAR_destructor_object_list = array();
798 | }
799 |
800 | // Now call the shutdown functions
801 | if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
802 | foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
803 | call_user_func_array($value[0], $value[1]);
804 | }
805 | }
806 | }
807 |
808 | // }}}
809 | /**
810 | * Standard PEAR error class for PHP 4
811 | *
812 | * This class is supserseded by {@link PEAR_Exception} in PHP 5
813 | *
814 | * @category pear
815 | * @package PEAR
816 | * @author Stig Bakken
817 | * @author Tomas V.V. Cox
818 | * @author Gregory Beaver
819 | * @copyright 1997-2006 The PHP Group
820 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
821 | * @version Release: 1.7.2
822 | * @link http://pear.php.net/manual/en/core.pear.pear-error.php
823 | * @see PEAR::raiseError(), PEAR::throwError()
824 | * @since Class available since PHP 4.0.2
825 | */
826 | class PEAR_Error
827 | {
828 | // {{{ properties
829 |
830 | var $error_message_prefix = '';
831 | var $mode = PEAR_ERROR_RETURN;
832 | var $level = E_USER_NOTICE;
833 | var $code = -1;
834 | var $message = '';
835 | var $userinfo = '';
836 | var $backtrace = null;
837 |
838 | // }}}
839 | // {{{ constructor
840 |
841 | /**
842 | * PEAR_Error constructor
843 | *
844 | * @param string $message message
845 | *
846 | * @param int $code (optional) error code
847 | *
848 | * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
849 | * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
850 | * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
851 | *
852 | * @param mixed $options (optional) error level, _OR_ in the case of
853 | * PEAR_ERROR_CALLBACK, the callback function or object/method
854 | * tuple.
855 | *
856 | * @param string $userinfo (optional) additional user/debug info
857 | *
858 | * @access public
859 | *
860 | */
861 | function PEAR_Error($message = 'unknown error', $code = null,
862 | $mode = null, $options = null, $userinfo = null)
863 | {
864 | if ($mode === null) {
865 | $mode = PEAR_ERROR_RETURN;
866 | }
867 | $this->message = $message;
868 | $this->code = $code;
869 | $this->mode = $mode;
870 | $this->userinfo = $userinfo;
871 | if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
872 | $this->backtrace = debug_backtrace();
873 | if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
874 | unset($this->backtrace[0]['object']);
875 | }
876 | }
877 | if ($mode & PEAR_ERROR_CALLBACK) {
878 | $this->level = E_USER_NOTICE;
879 | $this->callback = $options;
880 | } else {
881 | if ($options === null) {
882 | $options = E_USER_NOTICE;
883 | }
884 | $this->level = $options;
885 | $this->callback = null;
886 | }
887 | if ($this->mode & PEAR_ERROR_PRINT) {
888 | if (is_null($options) || is_int($options)) {
889 | $format = "%s";
890 | } else {
891 | $format = $options;
892 | }
893 | printf($format, $this->getMessage());
894 | }
895 | if ($this->mode & PEAR_ERROR_TRIGGER) {
896 | trigger_error($this->getMessage(), $this->level);
897 | }
898 | if ($this->mode & PEAR_ERROR_DIE) {
899 | $msg = $this->getMessage();
900 | if (is_null($options) || is_int($options)) {
901 | $format = "%s";
902 | if (substr($msg, -1) != "\n") {
903 | $msg .= "\n";
904 | }
905 | } else {
906 | $format = $options;
907 | }
908 | die(sprintf($format, $msg));
909 | }
910 | if ($this->mode & PEAR_ERROR_CALLBACK) {
911 | if (is_callable($this->callback)) {
912 | call_user_func($this->callback, $this);
913 | }
914 | }
915 | if ($this->mode & PEAR_ERROR_EXCEPTION) {
916 | trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
917 | eval('$e = new Exception($this->message, $this->code);throw($e);');
918 | }
919 | }
920 |
921 | // }}}
922 | // {{{ getMode()
923 |
924 | /**
925 | * Get the error mode from an error object.
926 | *
927 | * @return int error mode
928 | * @access public
929 | */
930 | function getMode() {
931 | return $this->mode;
932 | }
933 |
934 | // }}}
935 | // {{{ getCallback()
936 |
937 | /**
938 | * Get the callback function/method from an error object.
939 | *
940 | * @return mixed callback function or object/method array
941 | * @access public
942 | */
943 | function getCallback() {
944 | return $this->callback;
945 | }
946 |
947 | // }}}
948 | // {{{ getMessage()
949 |
950 |
951 | /**
952 | * Get the error message from an error object.
953 | *
954 | * @return string full error message
955 | * @access public
956 | */
957 | function getMessage()
958 | {
959 | return ($this->error_message_prefix . $this->message);
960 | }
961 |
962 |
963 | // }}}
964 | // {{{ getCode()
965 |
966 | /**
967 | * Get error code from an error object
968 | *
969 | * @return int error code
970 | * @access public
971 | */
972 | function getCode()
973 | {
974 | return $this->code;
975 | }
976 |
977 | // }}}
978 | // {{{ getType()
979 |
980 | /**
981 | * Get the name of this error/exception.
982 | *
983 | * @return string error/exception name (type)
984 | * @access public
985 | */
986 | function getType()
987 | {
988 | return get_class($this);
989 | }
990 |
991 | // }}}
992 | // {{{ getUserInfo()
993 |
994 | /**
995 | * Get additional user-supplied information.
996 | *
997 | * @return string user-supplied information
998 | * @access public
999 | */
1000 | function getUserInfo()
1001 | {
1002 | return $this->userinfo;
1003 | }
1004 |
1005 | // }}}
1006 | // {{{ getDebugInfo()
1007 |
1008 | /**
1009 | * Get additional debug information supplied by the application.
1010 | *
1011 | * @return string debug information
1012 | * @access public
1013 | */
1014 | function getDebugInfo()
1015 | {
1016 | return $this->getUserInfo();
1017 | }
1018 |
1019 | // }}}
1020 | // {{{ getBacktrace()
1021 |
1022 | /**
1023 | * Get the call backtrace from where the error was generated.
1024 | * Supported with PHP 4.3.0 or newer.
1025 | *
1026 | * @param int $frame (optional) what frame to fetch
1027 | * @return array Backtrace, or NULL if not available.
1028 | * @access public
1029 | */
1030 | function getBacktrace($frame = null)
1031 | {
1032 | if (defined('PEAR_IGNORE_BACKTRACE')) {
1033 | return null;
1034 | }
1035 | if ($frame === null) {
1036 | return $this->backtrace;
1037 | }
1038 | return $this->backtrace[$frame];
1039 | }
1040 |
1041 | // }}}
1042 | // {{{ addUserInfo()
1043 |
1044 | function addUserInfo($info)
1045 | {
1046 | if (empty($this->userinfo)) {
1047 | $this->userinfo = $info;
1048 | } else {
1049 | $this->userinfo .= " ** $info";
1050 | }
1051 | }
1052 |
1053 | // }}}
1054 | // {{{ toString()
1055 | function __toString()
1056 | {
1057 | return $this->getMessage();
1058 | }
1059 | // }}}
1060 | // {{{ toString()
1061 |
1062 | /**
1063 | * Make a string representation of this object.
1064 | *
1065 | * @return string a string with an object summary
1066 | * @access public
1067 | */
1068 | function toString() {
1069 | $modes = array();
1070 | $levels = array(E_USER_NOTICE => 'notice',
1071 | E_USER_WARNING => 'warning',
1072 | E_USER_ERROR => 'error');
1073 | if ($this->mode & PEAR_ERROR_CALLBACK) {
1074 | if (is_array($this->callback)) {
1075 | $callback = (is_object($this->callback[0]) ?
1076 | strtolower(get_class($this->callback[0])) :
1077 | $this->callback[0]) . '::' .
1078 | $this->callback[1];
1079 | } else {
1080 | $callback = $this->callback;
1081 | }
1082 | return sprintf('[%s: message="%s" code=%d mode=callback '.
1083 | 'callback=%s prefix="%s" info="%s"]',
1084 | strtolower(get_class($this)), $this->message, $this->code,
1085 | $callback, $this->error_message_prefix,
1086 | $this->userinfo);
1087 | }
1088 | if ($this->mode & PEAR_ERROR_PRINT) {
1089 | $modes[] = 'print';
1090 | }
1091 | if ($this->mode & PEAR_ERROR_TRIGGER) {
1092 | $modes[] = 'trigger';
1093 | }
1094 | if ($this->mode & PEAR_ERROR_DIE) {
1095 | $modes[] = 'die';
1096 | }
1097 | if ($this->mode & PEAR_ERROR_RETURN) {
1098 | $modes[] = 'return';
1099 | }
1100 | return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
1101 | 'prefix="%s" info="%s"]',
1102 | strtolower(get_class($this)), $this->message, $this->code,
1103 | implode("|", $modes), $levels[$this->level],
1104 | $this->error_message_prefix,
1105 | $this->userinfo);
1106 | }
1107 |
1108 | // }}}
1109 | }
1110 |
1111 | /*
1112 | * Local Variables:
1113 | * mode: php
1114 | * tab-width: 4
1115 | * c-basic-offset: 4
1116 | * End:
1117 | */
1118 | ?>
1119 |
--------------------------------------------------------------------------------
/app/lib/Wiz/SimpleXmlElement.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | class Wiz_Simplexml_Element extends SimpleXMLElement
11 | {
12 |
13 | /**
14 | * Would keep reference to parent node
15 | *
16 | * If SimpleXMLElement would support complicated attributes
17 | *
18 | * @var Wiz_Simplexml_Element
19 | */
20 | protected $_parent = null;
21 |
22 | /**
23 | * For future use
24 | *
25 | * @param Wiz_Simplexml_Element $element
26 | */
27 | public function setParent($element)
28 | {
29 | // $this->_parent = $element;
30 | }
31 |
32 | public function hasChildren()
33 | {
34 | if (!$this->children()) {
35 | return false;
36 | }
37 |
38 | // simplexml bug: @attributes is in children() but invisible in foreach
39 | foreach ($this->children() as $k=>$child) {
40 | return true;
41 | }
42 | return false;
43 | }
44 |
45 | /**
46 | * Returns attribute value by attribute name
47 | *
48 | * @return string
49 | */
50 | public function getAttribute($name){
51 | $attrs = $this->attributes();
52 | return isset($attrs[$name]) ? (string)$attrs[$name] : null;
53 | }
54 |
55 | /**
56 | * Find a descendant of a node by path
57 | *
58 | * @todo Do we need to make it xpath look-a-like?
59 | * @todo Check if we still need all this and revert to plain XPath if this makes any sense
60 | * @todo param string $path Subset of xpath. Example: "child/grand[@attrName='attrValue']/subGrand"
61 | * @param string $path Example: "child/grand@attrName=attrValue/subGrand" (to make it faster without regex)
62 | * @return Wiz_Simplexml_Element
63 | */
64 | public function descend($path)
65 | {
66 | if (is_array($path)) {
67 | $pathArr = $path;
68 | } else {
69 | // Simple exploding by / does not suffice,
70 | // as an attribute value may contain a / inside
71 | // Note that there are three matches for different kinds of attribute values specification
72 | if(strpos($path, "@") === false) {
73 | $pathArr = explode('/', $path);
74 | }
75 | else {
76 | $regex = "#([^@/\\\"]+(?:@[^=/]+=(?:\\\"[^\\\"]*\\\"|[^/]*))?)/?#";
77 | $pathArr = $pathMatches = array();
78 | if(preg_match_all($regex, $path, $pathMatches)) {
79 | $pathArr = $pathMatches[1];
80 | }
81 | }
82 | }
83 | $desc = $this;
84 | foreach ($pathArr as $nodeName) {
85 | if (strpos($nodeName, '@')!==false) {
86 | $a = explode('@', $nodeName);
87 | $b = explode('=', $a[1]);
88 | $nodeName = $a[0];
89 | $attributeName = $b[0];
90 | $attributeValue = $b[1];
91 | //
92 | // Does a very simplistic trimming of attribute value.
93 | //
94 | $attributeValue = trim($attributeValue, '"');
95 | $found = false;
96 | foreach ($desc->$nodeName as $subdesc) {
97 | if ((string)$subdesc[$attributeName]===$attributeValue) {
98 | $found = true;
99 | $desc = $subdesc;
100 | break;
101 | }
102 | }
103 | if (!$found) {
104 | $desc = false;
105 | }
106 | } else {
107 | $desc = $desc->$nodeName;
108 | }
109 | if (!$desc) {
110 | return false;
111 | }
112 | }
113 | return $desc;
114 | }
115 |
116 | /**
117 | * Returns the node and children as an array
118 | *
119 | * @return array|string
120 | */
121 | public function asArray()
122 | {
123 | return $this->_asArray();
124 | }
125 |
126 | /**
127 | * asArray() analog, but without attributes
128 | * @return array|string
129 | */
130 | public function asCanonicalArray()
131 | {
132 | return $this->_asArray(true);
133 | }
134 |
135 | /**
136 | * Returns the node and children as an array
137 | *
138 | * @param bool $isCanonical - whether to ignore attributes
139 | * @return array|string
140 | */
141 | protected function _asArray($isCanonical = false)
142 | {
143 | $result = array();
144 | if (!$isCanonical) {
145 | // add attributes
146 | foreach ($this->attributes() as $attributeName => $attribute) {
147 | if ($attribute) {
148 | $result['@'][$attributeName] = (string)$attribute;
149 | }
150 | }
151 | }
152 | // add children values
153 | if ($this->hasChildren()) {
154 | foreach ($this->children() as $childName => $child) {
155 | $result[$childName] = $child->_asArray($isCanonical);
156 | }
157 | } else {
158 | if (empty($result)) {
159 | // return as string, if nothing was found
160 | $result = (string) $this;
161 | } else {
162 | // value has zero key element
163 | $result[0] = (string) $this;
164 | }
165 | }
166 | return $result;
167 | }
168 |
169 | /**
170 | * Makes nicely formatted XML from the node
171 | *
172 | * @param string $filename
173 | * @param int|boolean $level if false
174 | * @return string
175 | */
176 | public function asNiceXml($filename='', $level=0)
177 | {
178 | if (is_numeric($level)) {
179 | $pad = str_pad('', $level * 4, ' ', STR_PAD_LEFT);
180 | $nl = "\n";
181 | } else {
182 | $pad = '';
183 | $nl = '';
184 | }
185 |
186 | $out = $pad.'<'.$this->getName();
187 |
188 | if ($attributes = $this->attributes()) {
189 | foreach ($attributes as $key=>$value) {
190 | $out .= ' '.$key.'="'.str_replace('"', '\"', (string)$value).'"';
191 | }
192 | }
193 |
194 | if ($this->hasChildren()) {
195 | $out .= '>'.$nl;
196 | foreach ($this->children() as $child) {
197 | $out .= $child->asNiceXml('', is_numeric($level) ? $level+1 : true);
198 | }
199 | $out .= $pad.''.$this->getName().'>'.$nl;
200 | } else {
201 | $value = (string)$this;
202 | if (strlen($value)) {
203 | $out .= '>'.$this->xmlentities($value).''.$this->getName().'>'.$nl;
204 | } else {
205 | $out .= '/>'.$nl;
206 | }
207 | }
208 |
209 | if ((0===$level || false===$level) && !empty($filename)) {
210 | file_put_contents($filename, $out);
211 | }
212 |
213 | return $out;
214 | }
215 |
216 | /**
217 | * Enter description here...
218 | *
219 | * @param int $level
220 | * @return string
221 | */
222 | public function innerXml($level=0)
223 | {
224 | $out = '';
225 | foreach ($this->children() as $child) {
226 | $out .= $child->asNiceXml($level);
227 | }
228 | return $out;
229 | }
230 |
231 | /**
232 | * Converts meaningful xml characters to xml entities
233 | *
234 | * @param string
235 | * @return string
236 | */
237 | public function xmlentities($value = null)
238 | {
239 | if (is_null($value)) {
240 | $value = $this;
241 | }
242 | $value = (string)$value;
243 |
244 | $value = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $value);
245 |
246 | return $value;
247 | }
248 |
249 | /**
250 | * Appends $source to current node
251 | *
252 | * @param Wiz_Simplexml_Element $source
253 | * @return Wiz_Simplexml_Element
254 | */
255 | public function appendChild($source)
256 | {
257 | if ($source->children()) {
258 | /**
259 | * @see http://bugs.php.net/bug.php?id=41867 , fixed in 5.2.4
260 | */
261 | if (version_compare(phpversion(), '5.2.4', '<')===true) {
262 | $name = $source->children()->getName();
263 | }
264 | else {
265 | $name = $source->getName();
266 | }
267 | $child = $this->addChild($name);
268 | } else {
269 | $child = $this->addChild($source->getName(), $this->xmlentities($source));
270 | }
271 | $child->setParent($this);
272 |
273 | $attributes = $source->attributes();
274 | foreach ($attributes as $key=>$value) {
275 | $child->addAttribute($key, $this->xmlentities($value));
276 | }
277 |
278 | foreach ($source->children() as $sourceChild) {
279 | $child->appendChild($sourceChild);
280 | }
281 | return $this;
282 | }
283 |
284 | /**
285 | * Extends current node with xml from $source
286 | *
287 | * If $overwrite is false will merge only missing nodes
288 | * Otherwise will overwrite existing nodes
289 | *
290 | * @param Wiz_Simplexml_Element $source
291 | * @param boolean $overwrite
292 | * @return Wiz_Simplexml_Element
293 | */
294 | public function extend($source, $overwrite=false)
295 | {
296 | if (!$source instanceof Wiz_Simplexml_Element) {
297 | return $this;
298 | }
299 |
300 | foreach ($source->children() as $child) {
301 | $this->extendChild($child, $overwrite);
302 | }
303 |
304 | return $this;
305 | }
306 |
307 | public function extendByFile($url, $overwrite=false) {
308 | try {
309 | $source = simplexml_load_file($url, get_class($this));
310 | $this->extend($source, $overwrite);
311 | }
312 | catch (Exception $e) {
313 | }
314 | return $this;
315 | }
316 |
317 | /**
318 | * Extends one node
319 | *
320 | * @param Wiz_Simplexml_Element $source
321 | * @param boolean $overwrite
322 | * @return Wiz_Simplexml_Element
323 | */
324 | public function extendChild($source, $overwrite=false)
325 | {
326 | // this will be our new target node
327 | $targetChild = null;
328 |
329 | // name of the source node
330 | $sourceName = $source->getName();
331 |
332 | // here we have children of our source node
333 | $sourceChildren = $source->children();
334 |
335 | if (!$source->hasChildren()) {
336 | // handle string node
337 | if (isset($this->$sourceName)) {
338 | // if target already has children return without regard
339 | if ($this->$sourceName->children()) {
340 | return $this;
341 | }
342 | if ($overwrite) {
343 | unset($this->$sourceName);
344 | } else {
345 | return $this;
346 | }
347 | }
348 |
349 | $targetChild = $this->addChild($sourceName, $source->xmlentities());
350 | $targetChild->setParent($this);
351 | foreach ($source->attributes() as $key=>$value) {
352 | $targetChild->addAttribute($key, $this->xmlentities($value));
353 | }
354 | return $this;
355 | }
356 |
357 | if (isset($this->$sourceName)) {
358 | $targetChild = $this->$sourceName;
359 | }
360 |
361 | if (is_null($targetChild)) {
362 | // if child target is not found create new and descend
363 | $targetChild = $this->addChild($sourceName);
364 | $targetChild->setParent($this);
365 | foreach ($source->attributes() as $key=>$value) {
366 | $targetChild->addAttribute($key, $this->xmlentities($value));
367 | }
368 | }
369 |
370 | // finally add our source node children to resulting new target node
371 | foreach ($sourceChildren as $childKey=>$childNode) {
372 | $targetChild->extendChild($childNode, $overwrite);
373 | }
374 |
375 | return $this;
376 | }
377 |
378 | public function setNode($path, $value, $overwrite=true)
379 | {
380 | $arr1 = explode('/', $path);
381 | $arr = array();
382 | foreach ($arr1 as $v) {
383 | if (!empty($v)) $arr[] = $v;
384 | }
385 | $last = sizeof($arr)-1;
386 | $node = $this;
387 | foreach ($arr as $i=>$nodeName) {
388 | if ($last===$i) {
389 |
390 | if (!isset($node->$nodeName) || $overwrite) {
391 | // http://bugs.php.net/bug.php?id=36795
392 | // comment on [8 Feb 8:09pm UTC]
393 | if (isset($node->$nodeName) && (version_compare(phpversion(), '5.2.6', '<')===true)) {
394 | $node->$nodeName = $node->xmlentities($value);
395 | } else {
396 | $node->$nodeName = $value;
397 | }
398 | }
399 | } else {
400 | if (!isset($node->$nodeName)) {
401 | $node = $node->addChild($nodeName);
402 | } else {
403 | $node = $node->$nodeName;
404 | }
405 | }
406 |
407 | }
408 | return $this;
409 | }
410 | }
--------------------------------------------------------------------------------
/app/plugins/301.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | function urlskumapAction($options) {
11 | Wiz::getMagento('');
12 | $output = '';
13 | $products = Mage::getModel('catalog/product')->getCollection()->addStoreFilter();
14 | foreach ($products as $product) {
15 | if (($sku = trim($product->getSku())) == '')
16 | continue;
17 | $output .= trim($product->getSku()).','.$product->getProductUrl().PHP_EOL;
18 | }
19 | if (strpos($options[0], '.') !== FALSE) {
20 | file_put_contents($options[0], $output);
21 | }
22 | else {
23 | echo $output;
24 | }
25 | }
26 |
27 | /**
28 | * Outputs a list of category to URL mappings.
29 | *
30 | * @author Nicholas Vahalik
31 | */
32 | function urlcatmapAction($options) {
33 | Wiz::getMagento('');
34 | $output = '';
35 |
36 | $rootCategory = Mage::getModel('catalog/category')->load(Mage::app()->getStore()->getRootCategoryId());
37 | $categories = Mage::getModel('catalog/category')->getCollection()->addPathFilter($rootCategory->getPath());
38 |
39 | foreach ($categories as $categoryModel) {
40 | $category = Mage::getModel('catalog/category')->load($categoryModel->getId());
41 | $breadcrumb = array();
42 | $data = array();
43 |
44 | $data[] = $category->getName();
45 | $data[] = $category->getUrl();
46 |
47 | $parentCategories = $category->getParentCategories();
48 | foreach ($parentCategories as $pc) {
49 | $breadcrumb[] = $pc->getName();
50 | }
51 |
52 | $data[] = '"'.implode("\t", $breadcrumb).'"';
53 | $output .= implode(',', $data).PHP_EOL;
54 | }
55 |
56 | if (strpos($options[0], '.') !== FALSE) {
57 | file_put_contents($options[0], $output);
58 | }
59 | else {
60 | echo $output;
61 | }
62 | }
63 |
64 | /**
65 | * Generates htaccess 301 redirects for the current magento site. Output is written
66 | * to stdout.
67 | *
68 | * Usage: wiz 301-htgen
69 | *
70 | * CSV File will be a two-column CSV file in the following format:
71 | * /old/path/to/product1.html,SKU1
72 | * /old/path/to/product2.html,SKU2
73 | *
74 | * @param URL to SKU CSV File.
75 | * @return void
76 | * @author Nicholas Vahalik
77 | */
78 | function htgenAction($options) {
79 | $filename = realpath($options[0]);
80 | if (!file_exists($filename)) {
81 | throw new Exception('Need a file to generate 301 mappings.');
82 | }
83 | else {
84 | file_put_contents('php://stderr', 'Reading current mappings from '.$filename.PHP_EOL);
85 | }
86 |
87 | Wiz::getMagento('store');
88 |
89 | $file_contents = file_get_contents($filename);
90 | $lines = explode(PHP_EOL, $file_contents);
91 | $redirectFormat = 'redirect 301 %s %s'.PHP_EOL;
92 | $output = $errors = '';
93 |
94 | $model = Mage::getModel('catalog/product');
95 | $baseUrl = Mage::getBaseUrl();
96 | $done = 0;
97 |
98 | foreach ($lines as $line) {
99 | $done++;
100 | list($url, $sku) = explode(', ', $line);
101 | $sku = strtoupper(trim($sku));
102 | $productId = $model->getIdBySku($sku);
103 | if ($productId === FALSE) {
104 | $errors .= 'Product not found for SKU# '.$sku.PHP_EOL;
105 | }
106 | $product = Mage::getModel('catalog/product')->load($productId);
107 | $output .= sprintf($redirectFormat, $url, str_replace($baseUrl, '/', $product->getProductUrl()));
108 | }
109 |
110 | echo $output.PHP_EOL;
111 |
112 | file_put_contents('php://stderr', 'Mapped '.$done.' records.'.PHP_EOL);
113 |
114 | if ($errors != '') {
115 | $errors = '========================================'.PHP_EOL
116 | .'== Errors =='.PHP_EOL
117 | .'========================================'.PHP_EOL
118 | .$errors.PHP_EOL;
119 | file_put_contents('php://stderr', $errors);
120 | }
121 | }
122 |
123 | /**
124 | * Converts a Google Sitemap XML file to a CSV File.
125 | *
126 | * @param string $options
127 | * @return void
128 | * @author Nicholas Vahalik
129 | */
130 | public function xmlsm2csvAction($options) {
131 | $settings['path-only'] = Wiz::getWiz()->getArg('path-only');
132 |
133 | $filename = array_shift($options);
134 |
135 | switch (strtolower(substr($filename, -3))) {
136 | case 'xml':
137 | $xml = simplexml_load_file($filename);
138 | if ($xml->getName() != 'urlset') {
139 | throw new Exception('This does not look like an XML sitemap.');
140 | }
141 | $output = fopen('php://temp', 'rw');
142 | foreach ($xml->url as $node) {
143 | if ($settings['path-only']) {
144 | $pathinfo = parse_url((string)$node->loc);
145 | $url = $pathinfo['path'];
146 | }
147 | else {
148 | $url = (string)$node->loc;
149 | }
150 | fputcsv($output, array($url));
151 | }
152 | rewind($output);
153 | while ($stuff = fgets($output, 1024)) {
154 | echo $stuff;
155 | }
156 | break;
157 | default:
158 | throw new Exception('Invalid file format.');
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/app/plugins/Admin.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Admin Plugin for Wiz
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | Class Wiz_Plugin_Admin extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Creates an administrative user. Attempts to use the posix user information if
30 | * it is available.
31 | *
32 | * @return array Assocative values to be used when creating the admin account.
33 | * @author Nicholas Vahalik
34 | **/
35 | function _prefillUserData($options) {
36 |
37 | // Prepopulate so E_STRICT doesn't complain on production servers.
38 | $returnArray = array(
39 | 'login' => '',
40 | 'firstName' => '',
41 | 'lastName' => '',
42 | 'emailAddress' => '',
43 | 'password' => ''
44 | );
45 |
46 | if (count($options) == 5) {
47 | $returnArray['login'] = array_shift($options);
48 | $returnArray['firstName'] = array_shift($options);
49 | $returnArray['lastName'] = array_shift($options);
50 | $returnArray['emailAddress'] = array_shift($options);
51 | $returnArray['password'] = array_shift($options);
52 | }
53 |
54 | return $returnArray;
55 | }
56 |
57 | /**
58 | * Disable an administrative user.
59 | *
60 | * @param Username (optional)
61 | * @author Nicholas Vahalik
62 | */
63 | function disableAction($options) {
64 | $this->changeUserStatus($options, FALSE);
65 | }
66 |
67 | /**
68 | * Enable an administrative user.
69 | *
70 | * @param Username (optional)
71 | * @author Nicholas Vahalik
72 | */
73 | function enableAction($options) {
74 | $this->changeUserStatus($options, TRUE);
75 | }
76 |
77 | function changeUserStatus($options, $status) {
78 | $username = '';
79 |
80 | switch (count($options)) {
81 | case 1:
82 | $username = array_pop($options);
83 | default:
84 | }
85 |
86 | // Asks for what we don't have.
87 | while ($username == '') {
88 | printf('Login: ');
89 | $username = trim(fgets(STDIN));
90 | }
91 |
92 | Wiz::getMagento();
93 |
94 | $adminUser = Mage::getModel('admin/user')->loadByUsername($username);
95 |
96 | if (!$adminUser->getId()) {
97 | throw new Exception(sprintf('Unable to find user "%s"', $username));
98 | }
99 |
100 | $adminUser
101 | ->setIsActive($status)
102 | ->save();
103 |
104 | $output = array(array('Login' => $username, 'Status' => $status ? 'Active' : 'Inactive'));
105 | echo Wiz::tableOutput($output);
106 | }
107 |
108 | /**
109 | * Lists the backend users in Magento.
110 | *
111 | * @author Nicholas Vahalik
112 | */
113 | function listAction() {
114 | $output = array();
115 |
116 | Wiz::getMagento();
117 |
118 | $userCollection = Mage::getModel('admin/user')->getCollection();
119 |
120 | foreach ($userCollection as $user) {
121 | $output[] = array(
122 | 'Id' => $user->getId(),
123 | 'Username' => $user->getUsername(),
124 | 'Email' => $user->getEmail(),
125 | 'Status' => $user->getIsActive() ? 'Active' : 'Inactive',
126 | );
127 | }
128 | echo Wiz::tableOutput($output);
129 | }
130 |
131 | /**
132 | * Resets an admin user's password. If you do not pass the parameters,
133 | * you will be prompted for them.
134 | *
135 | * Options:
136 | * --send-email Will send the user an e-mail about their new
137 | * password.
138 | *
139 | * --random Will generate a random password.
140 | *
141 | * --show Will show the password saved to the user.
142 | *
143 | * @param Username (optional)
144 | * @param Password (optional)
145 | * @author Nicholas Vahalik
146 | */
147 | function resetpassAction($options) {
148 | $username = $password = '';
149 |
150 | foreach ($options as $option) {
151 | if (strpos(trim($option), '--') !== 0) {
152 | $realParams[] = $option;
153 | }
154 | }
155 |
156 | // Load up what we have.
157 | switch (count($realParams)) {
158 | case 2:
159 | $password = array_pop($realParams);
160 | case 1:
161 | $username = array_pop($realParams);
162 | default:
163 | }
164 |
165 | // Asks for what we don't have.
166 | while ($username == '') {
167 | printf('Login: ');
168 | $username = trim(fgets(STDIN));
169 | }
170 |
171 | while ($password == '' && !Wiz::getWiz()->getArg('random')) {
172 | printf('New Password: ');
173 | $password = trim(fgets(STDIN));
174 | };
175 |
176 | Wiz::getMagento();
177 |
178 | if (Wiz::getWiz()->getArg('random')) {
179 | $password = Mage::helper('core')->getRandomString(10);
180 | }
181 |
182 | $adminUser = Mage::getModel('admin/user')->loadByUsername($username);
183 |
184 | if (!$adminUser->getId()) {
185 | throw new Exception(sprintf('Unable to find user "%s"', $username));
186 | }
187 |
188 | $adminUser
189 | ->setPassword($password)
190 | ->save();
191 |
192 | if (Wiz::getWiz()->getArg('send-email')) {
193 | $adminUser->setPlainPassword($password);
194 | $adminUser->sendNewPasswordEmail();
195 | }
196 |
197 | if (Wiz::getWiz()->getArg('show')) {
198 | printf('Password for user "%s" has been changed to "%s".' . PHP_EOL, $username, $password);
199 | }
200 | else {
201 | printf('Password for user "%s" has been updated.' . PHP_EOL, $username);
202 | }
203 | }
204 |
205 | /**
206 | * Creates an admin user in the Magento backend.
207 | *
208 | * If you pass no parameters, it attempts to use posix data to pre-fill the fields
209 | * and will prompt you to confirm. You can also pass it the following parameters
210 | * in order and it will create a user without prompting.
211 | *
212 | * admin-createadmin
213 | *
214 | * The password will be MD5-hashed for you when the user is created.
215 | *
216 | * @param create user options
217 | * @author Nicholas Vahalik
218 | */
219 | function createadminAction($options) {
220 | $defaults = $this->_prefillUserData($options);
221 |
222 | if (count($options) != 5) {
223 | do {
224 | printf('Login [%s]: ', $defaults['login']);
225 | $login = (($input = trim(fgets(STDIN))) != '' ? $input : $defaults['login']);
226 | } while ($login == '');
227 |
228 | do {
229 | printf('First name [%s]: ', $defaults['firstName']);
230 | $firstName = ($input = trim(fgets(STDIN))) != '' ? $input : $defaults['firstName'];
231 | } while ($firstName == '');
232 |
233 | do {
234 | printf('Last name [%s]: ', $defaults['lastName']);
235 | $lastName = ($input = trim(fgets(STDIN))) != '' ? $input : $defaults['lastName'];
236 | } while ($lastName == '');
237 |
238 | do {
239 | printf('E-mail address: ');
240 | $emailAddress = trim(fgets(STDIN));
241 | } while ($emailAddress == '');
242 |
243 | do {
244 | printf('Password: ');
245 | $password = trim(fgets(STDIN));
246 | } while ($password == '');
247 | }
248 | else {
249 | extract($defaults);
250 | }
251 |
252 | Wiz::getMagento();
253 |
254 | $versionInfo = Mage::getVersionInfo();
255 |
256 | try {
257 | // Create the user
258 | $userModel = Mage::getModel('admin/user')
259 | ->setUsername($login)
260 | ->setFirstname($firstName)
261 | ->setLastname($lastName)
262 | ->setEmail($emailAddress)
263 | ->setPassword($password)
264 | ->setIsActive(true)
265 | ->save();
266 |
267 | // Load the role collection
268 | $collection = Mage::getResourceModel('admin/role_collection');
269 | // Only load the roles, not the relationships
270 | $collection->setRolesFilter();
271 |
272 | // Find the administrative role.
273 | foreach ($collection as $role) {
274 | if (($versionInfo['major'] == 1 && ($versionInfo['minor'] > 2 && $versionInfo['minor'] < 6)
275 | && $role->getGwsIsAll() == 1) || $role->getRoleName() == 'Administrators') {
276 | $userRoles[] = $role->getId();
277 | }
278 | }
279 |
280 | // Set up the role relationship
281 | $userModel->setRoleIds($userRoles)
282 | ->setRoleUserId($userModel->getUserId())
283 | ->saveRelations();
284 |
285 | echo "Created new user '$login' with password '$password'.".PHP_EOL;
286 | }
287 | catch (Exception $e) {
288 | throw $e;
289 | }
290 | }
291 |
292 | /**
293 | * Sets or displays the admin session timeout value.
294 | *
295 | * Usage:
296 | * wiz admin-timeout
297 | *
298 | * If is not provided, it displays the value fof the admin session
299 | * timeout. Otherwise, it sets the admin session timeout value to the provided
300 | * value. Possible values:
301 | *
302 | * s - Sets the timeout to be the value. Default if no multiplier is
303 | * specified.
304 | * m - Sets the timeout to be the number of minutes specified. (e.g. 30m)
305 | * h - Sets the timeout to be the number of hours specified. (e.g. 8h)
306 | * d - Sets the timeout to be the number of days specified. (e.g. 2d)
307 | *
308 | * @author Nicholas Vahalik
309 | */
310 | public function timeoutAction($options) {
311 | $time = array_pop($options);
312 | Wiz::getMagento();
313 |
314 | if ($time != '') {
315 | // Common multipliers.
316 | $multiplier = array('s' => 1, 'm' => 60, 'h' => 3600, 'd' => 86400);
317 |
318 | // Grab the components of the time.
319 | preg_match('#(\d+)(m|h|d)?#i', $time, $matches);
320 |
321 | $mult = $matches[2] != '' ? $matches[2] : 's';
322 | $value = $matches[1] != '' ? $matches[1] : 0;
323 |
324 | // If we got passed some weird multiplier, bail out.
325 | if (!array_key_exists($mult, $multiplier)) {
326 | throw new Exception("Invalid time specifier: '$mult'.");
327 | }
328 |
329 | $timeInSeconds = (int)$value * $multiplier[$mult];
330 |
331 | // Kick back anything that is less than 60 seconds, since the admin would.
332 | if ($timeInSeconds < 60) {
333 | throw new Exception('Values less than 60 seconds are ignored.');
334 | }
335 |
336 | // Save our value and then remove the cache.
337 | Mage::getConfig()->saveConfig('admin/security/session_cookie_lifetime', $timeInSeconds);
338 | Mage::getConfig()->removeCache();
339 |
340 | // We do this here because below doesn't run correctly until the next config load.
341 | $output = array(array('Config Value' => 'admin/security/session_cookie_lifetime', 'Value' => $timeInSeconds));
342 | }
343 | else {
344 | // Give 'em the value.
345 | $output = array(array('Config Value' => 'admin/security/session_cookie_lifetime', 'Value' => (int)Mage::getStoreConfig('admin/security/session_cookie_lifetime')));
346 | }
347 |
348 | echo Wiz::tableOutput($output);
349 | }
350 |
351 | public function _recurseXmlWalkResources($item, $path = '', $all = false) {
352 | $results = array();
353 |
354 | foreach ($item->children() as $itemName => $child) {
355 | if ('children' == $itemName) {
356 | $results = array_merge($results, $this->_recurseXmlWalkResources($child, $path, $all));
357 | }
358 | else if ('title' == $itemName && $path != '') {
359 | $results[] = array($path, (string)$child);
360 | }
361 | else {
362 | $results = array_merge($results, $this->_recurseXmlWalkResources($child, $path . ($path != '' ? '/' : '') . (string)$itemName, $all));
363 | }
364 | }
365 | return $results;
366 | }
367 |
368 | public function _sortAclEntries($a, $b) {
369 | return strcmp($a['Path'], $b['Path']);
370 | }
371 |
372 |
373 | /**
374 | * Displays a full list of resources that are defined by modules in Magento.
375 | *
376 | * @param string $options
377 | * @return void
378 | * @author Nicholas Vahalik
379 | */
380 | public function resourcesAction($options) {
381 | $formattedOutput = $output = array();
382 |
383 | Wiz::getMagento();
384 | $aclResources = Mage::getModel('admin/config')->getAdminhtmlConfig()->getNode("acl/resources");
385 | $output = $this->_recurseXmlWalkResources($aclResources->admin);
386 |
387 | foreach ($output as $data) {
388 | $formattedOutput[] = array('Path' => $data[0], 'Title' => $data[1]);
389 | }
390 |
391 | usort($formattedOutput, array($this, '_sortAclEntries'));
392 |
393 | echo Wiz::tableOutput($formattedOutput);
394 | }
395 |
396 | }
397 |
--------------------------------------------------------------------------------
/app/plugins/Cache.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Cache Plugin for Wiz
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | Class Wiz_Plugin_Cache extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Clear the Magento caches. Same processes used by the Administrative backend.
30 | *
31 | * If called as "wiz cache-clear" then we will clear the
32 | *
33 | * @author Nicholas Vahalik
34 | */
35 | function clearAction($options) {
36 | Wiz::getMagento();
37 |
38 | if (count($options) == 0) {
39 | $options[] = 'default';
40 | }
41 |
42 | $types = array_keys($this->_getAllMagentoCacheTypes());
43 |
44 | if (count($options) == 1 && !in_array($options[0], $types)) {
45 | switch ($options[0]) {
46 | case 'invalidated':
47 | $this->_cleanCachesById(array_keys(Mage::app()->getCacheInstance()->getInvalidatedTypes()));
48 | break;
49 | case 'system':
50 | $this->_cleanSystem();
51 | break;
52 | case 'js':
53 | case 'css':
54 | case 'jscss':
55 | $this->_cleanMedia();
56 | break;
57 | case 'images':
58 | $this->_cleanImages();
59 | break;
60 | case 'all':
61 | $this->_cleanSystem();
62 | $this->_cleanMedia();
63 | $this->_cleanImages();
64 | $this->_cleanAll();
65 | break;
66 | case 'default':
67 | $this->_cleanAll();
68 | break;
69 | default:
70 | }
71 | }
72 | else {
73 | $this->_cleanCachesById($options);
74 | }
75 | }
76 |
77 | function _cleanCachesById($options) {
78 | $caches = $this->_getAllMagentoCacheTypes();
79 | $cachesCleaned = array();
80 |
81 | foreach ($options as $type) {
82 | try {
83 | Mage::app()->getCacheInstance()->cleanType($type);
84 | $cachesCleaned[] = $caches[$type]->getCacheType();
85 | }
86 | catch (Exception $e) {
87 | echo 'Failed to clear cache: ' . $type . PHP_EOL;
88 | }
89 | }
90 |
91 | if (count($cachesCleaned) > 0) {
92 | echo 'The following caches have been cleaned: ' . implode(', ', $cachesCleaned) . PHP_EOL;
93 | }
94 | }
95 |
96 | function _getAllMagentoCacheTypes() {
97 | Wiz::getMagento();
98 | return Mage::app()->getCacheInstance()->getTypes();
99 | }
100 |
101 | /**
102 | * Enables all caches if "all" or no params are passed. Otherwise it will enable
103 | * the specified caches.
104 | *
105 | * @param "all" to enable all caches, or a list of cache ids (see cache-status)
106 | * @author Nicholas Vahalik
107 | */
108 | function enableAction($options) {
109 | $caches = $this->_getAllMagentoCacheTypes();
110 |
111 | $didAllCaches = FALSE;
112 |
113 | if (count($options) == 0 || (count($options) == 1 && $options[0] == 'all')) {
114 | foreach ($caches as $cache) {
115 | $cacheCodesToEnable[] = $cache->getId();
116 | $cacheNamesToEnable[] = $cache->getCacheType();
117 | }
118 | $didAllCaches = TRUE;
119 | }
120 | else {
121 | while (($cacheName = array_shift($options)) != '') {
122 | if ($cache = $caches[$cacheName]) {
123 | $cacheCodesToEnable[] = $cacheName;
124 | $cacheNamesToEnable[] = $cache->getCacheType();
125 | }
126 | }
127 | }
128 |
129 | $allTypes = Mage::app()->useCache();
130 |
131 | $updatedTypes = 0;
132 | foreach ($cacheCodesToEnable as $code) {
133 | if (empty($allTypes[$code])) {
134 | $allTypes[$code] = 1;
135 | $updatedTypes++;
136 | }
137 | }
138 |
139 | if ($updatedTypes > 0) {
140 | Mage::app()->saveUseCache($allTypes);
141 | if ($didAllCaches) {
142 | echo 'All caches are now enabled.'.PHP_EOL;
143 | }
144 | else {
145 | echo 'The following cache(s) were enable: '.implode(', ', $cacheNamesToEnable).PHP_EOL;
146 | }
147 | }
148 | else {
149 | echo 'Nothing was done. Likely they were already enabled.'.PHP_EOL;
150 | }
151 | }
152 |
153 | /**
154 | * Disables caches by name.
155 | *
156 | * @param One or more caches, separated by a space.
157 | * @author Nicholas Vahalik
158 | */
159 | function disableAction($options) {
160 | $caches = $this->_getAllMagentoCacheTypes();
161 |
162 | $didAllCaches = FALSE;
163 |
164 | if (count($options) == 0 || (count($options) == 1 && $options[0] == 'all')) {
165 | foreach ($caches as $cache) {
166 | $cacheCodesToEnable[] = $cache->getId();
167 | $cacheNamesToEnable[] = $cache->getCacheType();
168 | }
169 | $didAllCaches = TRUE;
170 | }
171 | else {
172 | while (($cacheName = array_shift($options)) != '') {
173 | if ($cache = $caches[$cacheName]) {
174 | $cacheCodesToEnable[] = $cacheName;
175 | $cacheNamesToEnable[] = $cache->getCacheType();
176 | }
177 | }
178 | }
179 |
180 | $allTypes = Mage::app()->useCache();
181 |
182 | $updatedTypes = 0;
183 | foreach ($cacheCodesToEnable as $code) {
184 | if (!empty($allTypes[$code])) {
185 | $allTypes[$code] = 0;
186 | $updatedTypes++;
187 | }
188 | Mage::app()->getCacheInstance()->cleanType($code);
189 | }
190 |
191 | if ($updatedTypes > 0) {
192 | Mage::app()->saveUseCache($allTypes);
193 | if ($didAllCaches) {
194 | echo 'All caches are now disabled.'.PHP_EOL;
195 | }
196 | else {
197 | echo 'The following cache(s) were disabled: '.implode(', ', $cacheNamesToEnable).PHP_EOL;
198 | }
199 | }
200 | else {
201 | echo 'Nothing was done. Likely they were already disabled.'.PHP_EOL;
202 | }
203 | }
204 |
205 |
206 | /**
207 | * Returns the status of all or named caches.
208 | *
209 | * @author Nicholas Vahalik
210 | */
211 | function statusAction() {
212 | $types = $this->_getAllMagentoCacheTypes();
213 | $invalidatedTypes = Mage::app()->getCacheInstance()->getInvalidatedTypes();
214 |
215 | foreach ($types as $cache) {
216 | $rows[] = array(
217 | 'Type' => $cache->getCacheType(),
218 | 'Id' => $cache->getId(),
219 | 'Status' => isset($invalidatedTypes[$cache->getId()]) ? 'Invalidated' : ($cache->getStatus() ? 'Enabled' : 'Disabled'),
220 | );
221 | }
222 | echo Wiz::tableOutput($rows);
223 | }
224 |
225 | public function _cleanAll() {
226 | Mage::dispatchEvent('adminhtml_cache_flush_all');
227 | Mage::app()->getCacheInstance()->flush();
228 | echo 'The cache storage has been flushed.' . PHP_EOL;
229 | }
230 |
231 | public function _cleanSystem() {
232 | Mage::app()->cleanCache();
233 | Mage::dispatchEvent('adminhtml_cache_flush_system');
234 | echo 'The Magento cache storage has been flushed.' . PHP_EOL;
235 | }
236 |
237 | public function _cleanMedia() {
238 | try {
239 | Mage::getModel('core/design_package')->cleanMergedJsCss();
240 | Mage::dispatchEvent('clean_media_cache_after');
241 | echo 'The JavaScript/CSS cache has been cleaned.' . PHP_EOL;
242 | }
243 | catch (Exception $e) {
244 | echo $e->getMessage() . PHP_EOL;
245 | }
246 | }
247 |
248 | /**
249 | * Clean JS/css files cache
250 | */
251 | public function _cleanImages()
252 | {
253 | try {
254 | Mage::getModel('catalog/product_image')->clearCache();
255 | Mage::dispatchEvent('clean_catalog_images_cache_after');
256 | echo 'The image cache was cleaned.' . PHP_EOL;
257 | }
258 | catch (Exception $e) {
259 | echo $e->getMessage() . PHP_EOL;
260 | }
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/app/plugins/Config.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Configuration Plugin for Wiz
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | class Wiz_Plugin_Config extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Returns the value stored in Magento for the given config path.
30 | *
31 | * @param Configuration path.
32 | * @author Nicholas Vahalik
33 | */
34 | public function getAction($options) {
35 | // Mage_Core_Model_Config_Element
36 | $result = Wiz::getMagento()->getConfig()->getNode($options[0]);
37 | // we'll either get a false or a Mage_Core_Model_Config_Element object
38 | $value = $message = null;
39 | if (is_object($result)) {
40 | if ($result->hasChildren()) {
41 | $childArray = array_keys($result->asArray());
42 | $value = '['.implode(', ', $childArray).']';
43 | }
44 | else {
45 | if ((string)$result == '') {
46 | $value = '';
47 | }
48 | else {
49 | $value = $result;
50 | }
51 | }
52 | echo $options[0] . ($value ? ' = ' . $value : ' ' . $message).PHP_EOL;
53 | }
54 | elseif ($result === FALSE) {
55 | echo 'Configuration path "' . $options[0] . '" not found.'.PHP_EOL;
56 | }
57 | }
58 |
59 | /**
60 | * Retrieve a single store configuration node path.
61 | *
62 | * Example: config-storget sales_email/order/enabled
63 | * This will return the value in the configuration if the order e-mails are enabled.
64 | *
65 | * Options:
66 | * --all Returns the value for all stores in the Magento installation.
67 | *
68 | * @param Node path string.
69 | * @author Nicholas Vahalik
70 | */
71 | public function storegetAction($options) {
72 |
73 | $stores = $output = array();
74 |
75 | Wiz::getMagento();
76 |
77 | if (Wiz::getWiz()->getArg('all')) {
78 | $storeCollection = Mage::getModel('core/store')->getCollection();
79 | foreach ($storeCollection as $store) {
80 | $stores[] = $store->getCode();
81 | }
82 | }
83 | elseif (count($options) > 1) {
84 | $stores = array(array_shift($options));
85 | }
86 | else {
87 | $stores = array('default');
88 | }
89 |
90 | $path = array_shift($options);
91 |
92 | foreach ($stores as $store) {
93 | $output[] = array('Store Id' => $store, $path => Mage::getStoreConfig($path, $store));
94 | // echo "($store) $path" . ' = ' . Mage::getStoreConfig($path, $store);// Wiz::getMagento()->
95 | }
96 | echo Wiz::tableOutput($output);
97 | echo PHP_EOL;
98 | }
99 |
100 | /**
101 | * Performs an Xpath query over the Magento configuration structure and returns the
102 | * results as text selectors. This should allow you to quickly find anything inside
103 | * of the configuration provided you know the node name you want. The results will
104 | * have the entire hierarchy displayed so you'll know the exact location inside of
105 | * the document. For instance, to display the version of every module on the system,
106 | * you could run: config-xpath //version and it will return every node named version
107 | * anywhere in the config. You might get a lot of results using this command, but
108 | * just remember that Magento's config is HUGE.
109 | *
110 | * @param Xpath string to search. For more information:
111 | * @see http://www.w3schools.com/xpath/xpath_syntax.asp
112 | * @author Nicholas Vahalik
113 | */
114 | public function xpathAction($options) {
115 | Wiz::getMagento();
116 | $xpathResults = Mage::getConfig()->getXpath($options[0]);
117 | // We get an array of results back.
118 | foreach ($xpathResults as $result) {
119 | $parentArray = array();
120 | $parent = $result;
121 | while (($parent = $parent->getParent()) != NULL) {
122 | $parentArray[] = $parent->getName();
123 | }
124 | $parentArray = array_reverse($parentArray);
125 | $this->_recurseXpathOutput($parentArray, $result);
126 | }
127 | }
128 |
129 | private function _recurseXpathOutput($parents, $xmlelement) {
130 | array_push($parents, $xmlelement->getName());
131 | if ($xmlelement->hasChildren()) {
132 | foreach ($xmlelement->children() as $child) {
133 | $this->_recurseXpathOutput($parents, $child);
134 | }
135 | }
136 | else {
137 | echo implode('/', $parents).' = '.(string)$xmlelement.PHP_EOL;
138 | }
139 | array_pop($parents);
140 | }
141 |
142 | /**
143 | * Returns the entire Magento config as nicely formatted XML to stdout.
144 | * Options:
145 | * --ugly (optional) Makes the output ugly (no tabs or newlines)
146 | *
147 | * --system Returns the modules configuration (system.xml)
148 | *
149 | * --indent Number of spaces to use to indent the XML. The
150 | * default is 3.
151 | *
152 | * @return The Magento Configuration as as nicely printed XML File.
153 | * @author Nicholas Vahalik
154 | */
155 | public function asxmlAction() {
156 | Wiz::getMagento();
157 |
158 | if (Wiz::getWiz()->getArg('system')) {
159 | $xml = Mage::getConfig()->loadModulesConfiguration('system.xml');
160 | }
161 | else {
162 | $xml = Mage::getConfig();
163 | }
164 |
165 | if (!Wiz::getWiz()->getArg('ugly')) {
166 | $output = $xml->getNode()->asNiceXml('');
167 |
168 | // Update with our indentation if so desired.
169 | if (Wiz::getWiz()->getArg('indent') !== false) {
170 | $output = preg_replace_callback('#^(\s+)#m', array($this, '_replaceSpaces'), $output);
171 | }
172 | }
173 | else {
174 | $output = $xml->getNode()->asXml();
175 | }
176 |
177 | echo $output;
178 | echo PHP_EOL;
179 | }
180 |
181 | /**
182 | * Replace the standard 3 spaces asXml products with whatever we want.
183 | *
184 | * @param string $matches
185 | * @return void
186 | * @author Nicholas Vahalik
187 | */
188 | protected function _replaceSpaces($matches) {
189 | $newSpaces = (int)Wiz::getWiz()->getArg('indent');
190 | return str_repeat(' ', (strlen($matches[1]) / 3) * $newSpaces);
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/app/plugins/Cron.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | class Wiz_Plugin_Cron extends Wiz_Plugin_Abstract
22 | {
23 | /**
24 | * Returns a list of registered crontab jobs.
25 | *
26 | * @author Nicholas Vahalik
27 | **/
28 | public function jobsAction() {
29 | $modelMapping = array();
30 | Wiz::getMagento();
31 |
32 | $modelMapping = $this->getCrontabJobs();
33 |
34 | echo Wiz::tableOutput($modelMapping);
35 | }
36 |
37 | /**
38 | * Lists the event listeners that will execute when cron runs.
39 | *
40 | * @author Nicholas Vahalik
41 | */
42 | public function listenersAction() {
43 | $modelMapping = array();
44 | Wiz::getMagento();
45 |
46 | $modelMapping = $this->getCrontabEvents();
47 |
48 | echo Wiz::tableOutput($modelMapping);
49 | }
50 |
51 | /**
52 | * Runs the cron.
53 | *
54 | * @author Nicholas Vahalik
55 | */
56 | public function runAction($options) {
57 | Wiz::getMagento();
58 |
59 | Mage::app('admin')->setUseSessionInUrl(false);
60 |
61 | try {
62 | Mage::getConfig()->init()->loadEventObservers('crontab');
63 | Mage::app()->addEventArea('crontab');
64 | Mage::dispatchEvent('default');
65 | } catch (Exception $e) {
66 | throw $e;
67 | }
68 | }
69 |
70 | /**
71 | * returns a list of observers from the configuration XML from
72 | * a config path.
73 | *
74 | * @author Nicholas Vahalik
75 | */
76 | function getCrontabEvents() {
77 | $config = Mage::getConfig();
78 | foreach ($config->getNode("crontab/events")->children() as $childName => $observerInfo) {
79 | foreach ($observerInfo->observers->children() as $parent => $data) {
80 | $modelMapping[] = array(
81 | 'Name' => $childName,
82 | 'ID' => $parent,
83 | 'Class::Method' => $data->class . '::' . (string)$data->method,
84 | );
85 | }
86 | }
87 | return $modelMapping;
88 | }
89 |
90 | /**
91 | * returns a list of observers from the configuration XML from
92 | * a config path.
93 | *
94 | * @author Nicholas Vahalik
95 | */
96 | function getCrontabJobs() {
97 | $config = Mage::getConfig();
98 |
99 | foreach (array('crontab/jobs', 'default/crontab/jobs') as $path) {
100 | foreach ($config->getNode($path)->children() as $childName => $observerInfo) {
101 | $cronConfig = (string)$observerInfo->schedule->config_path ? (string)$observerInfo->schedule->config_path : (string)$observerInfo->schedule->cron_expr;
102 | $modelMapping[] = array(
103 | 'Name' => $childName,
104 | 'Schedule' => $cronConfig ? $cronConfig : '',
105 | 'Run' => $observerInfo->run->model,
106 | );
107 | }
108 | }
109 |
110 | return $modelMapping;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/app/plugins/Devel.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | class Wiz_Plugin_Devel extends Wiz_Plugin_Abstract {
22 |
23 | /**
24 | * Enables, disables, or displays the value of template hints.
25 | *
26 | * To show: wiz devel-showhints
27 | *
28 | * To enable: wiz devel-showhints
29 | *
30 | * To disable: wiz devel-showhints
31 | *
32 | * Note: this will not affect sites if the template hints are overriden via the system
33 | * config in the dashboard... for now.
34 | *
35 | * @author Nicholas Vahalik
36 | **/
37 | public function showhintsAction($options) {
38 | /*
39 | * Per #7, if client restrictions are enabled, template hints won't work.
40 | * I'm not sure if it is a good idea to simply just disable the restrictions,
41 | * but we could alert the poor soul that they are set.
42 | */
43 |
44 | Wiz::getMagento();
45 | $value = Mage::getStoreConfig('dev/restrict/allow_ips');
46 |
47 | if ($value != NULL) {
48 | echo 'Developer restrictions are enabled. This value has no effect.' . PHP_EOL;
49 | }
50 |
51 | $path = 'dev/debug/template_hints';
52 | $storeCode = Wiz::getStoreCode();
53 | $websiteCode = Wiz::getWebsiteCode();
54 |
55 | $scopeId = Mage::app()->getStore($storeCode)->getStoreId();
56 | $this->toggleConfigValue($options, array('dev/debug/template_hints', 'dev/debug/template_hints_blocks'), 'stores', $scopeId);
57 |
58 | $scopeId = Mage::app()->getWebsite($websiteCode)->getWebsiteId();
59 | $this->toggleConfigValue($options, array('dev/debug/template_hints', 'dev/debug/template_hints_blocks'), 'websites', $scopeId);
60 | }
61 |
62 | /**
63 | * Enables, disables, or displays the status of logging in Magento.
64 | *
65 | * To show: wiz devel-logging
66 | *
67 | * To enable: wiz devel-logging
68 | *
69 | * To disable: wiz devel-logging
70 | *
71 | * @author Nicholas Vahalik
72 | **/
73 | public function loggingAction($options) {
74 | $this->toggleConfigValue($options, 'dev/log/active');
75 | }
76 |
77 | /**
78 | * Enables, disables, or displays the value of symlinks allowed for templates.
79 | *
80 | * To show: wiz devel-allowsymlinks
81 | *
82 | * To enable: wiz devel-allowsymlinks
83 | *
84 | * To disable: wiz devel-allowsymlinks
85 | *
86 | * Only compatible with Magento 1.5.1.0+
87 | *
88 | * @author Nicholas Vahalik
89 | **/
90 | public function allowsymlinksAction($options) {
91 | Wiz::getMagento();
92 | $this->toggleConfigValue($options, Mage_Core_Block_Template::XML_PATH_TEMPLATE_ALLOW_SYMLINK);
93 | }
94 |
95 | /**
96 | * Dumps a set of useful devel configuration values.
97 | *
98 | * @author Nicholas Vahalik
99 | */
100 | public function configAction($options) {
101 | Wiz::getMagento();
102 | $values =
103 | array('dev/debug/profiler',
104 | 'dev/js/merge_files',
105 | 'dev/css/merge_css_files',
106 | 'dev/log/active',
107 | 'dev/debug/template_hints',
108 | 'dev/debug/template_hints_blocks');
109 |
110 | /**
111 | * @todo Refactor this to look at values on a Magento version basis. Not by trial and error.
112 | */
113 | if (defined('Mage_Core_Block_Template::XML_PATH_TEMPLATE_ALLOW_SYMLINK')) {
114 | $values[] = constant('Mage_Core_Block_Template::XML_PATH_TEMPLATE_ALLOW_SYMLINK');
115 | }
116 |
117 | $this->toggleConfigValue(array(),
118 | $values);
119 | }
120 |
121 | /**
122 | * Enables, disables, or displays the status of the profiler.
123 | *
124 | * To show: wiz devel-profiler
125 | *
126 | * To enable: wiz devel-profiler
127 | *
128 | * To disable: wiz devel-profiler
129 | *
130 | * @author Nicholas Vahalik
131 | **/
132 | public function profilerAction($options) {
133 | $this->toggleConfigValue($options, 'dev/debug/profiler');
134 | }
135 |
136 | /**
137 | * Enables, disables, or displays the status of JS Merging.
138 | *
139 | * To show: wiz devel-mergejs
140 | *
141 | * To enable: wiz devel-mergejs
142 | *
143 | * To disable: wiz devel-mergejs
144 | *
145 | * @author Nicholas Vahalik
146 | **/
147 | public function mergejsAction($options) {
148 | $this->toggleConfigValue($options, 'dev/js/merge_files');
149 | }
150 |
151 | /**
152 | * Enables, disables, or displays the status of CSS Merging.
153 | *
154 | * To show: wiz devel-mergecss
155 | *
156 | * To enable: wiz devel-mergecss
157 | *
158 | * To disable: wiz devel-mergecss
159 | *
160 | * @author Nicholas Vahalik
161 | **/
162 | public function mergecssAction($options) {
163 | $this->toggleConfigValue($options, 'dev/css/merge_css_files');
164 | }
165 |
166 | /**
167 | * Generic function to handle enabling, disabling or showing the value of one or
168 | * more configuration paths.
169 | *
170 | * @param array $options
171 | * @param array|string Configuration path or paths as an array.
172 | * @author Nicholas Vahalik
173 | */
174 | private function toggleConfigValue($options, $values, $scope = 'default', $scopeId = 0) {
175 | if (!is_array($values)) {
176 | $values = array($values);
177 | }
178 |
179 | // Display the current values.
180 | $output = array();
181 | Wiz::getMagento();
182 | $showValue = NULL;
183 |
184 | if (count($options) > 0) {
185 | if (in_array(strtolower($options[0]), array('false', '0', 'no', 'nah'))) {
186 | $showValue = 0;
187 | }
188 | else if (in_array(strtolower($options[0]), array('true', '1', 'yes', 'totally'))) {
189 | $showValue = 1;
190 | }
191 | else {
192 | // @todo - Exception
193 | echo 'Invalid option: ' . $options[0] . PHP_EOL;
194 | }
195 | }
196 |
197 | foreach ($values as $value) {
198 | if ($showValue !== NULL) {
199 | Mage::getConfig()->saveConfig($value, $showValue, $scope, $scopeId);
200 | }
201 | else {
202 | $output[] = array(
203 | 'Path' => $value,
204 | 'Value' => (int)Mage::getConfig()->getNode($value, 'default') == 1 ? 'Yes' : 'No'
205 | );
206 | }
207 | }
208 |
209 | if ($showValue !== NULL) {
210 | Mage::getConfig()->removeCache();
211 | }
212 |
213 | if ($output) {
214 | echo Wiz::tableOutput($output);
215 | }
216 | }
217 |
218 | /**
219 | * Returns a list of registered event observers.
220 | *
221 | * @author Nicholas Vahalik
222 | **/
223 | public function listenersAction() {
224 | $modelMapping = array();
225 | Wiz::getMagento();
226 | $wiz = Wiz::getWiz();
227 |
228 | $modelMapping = array_merge($modelMapping, $this->getObserversForPath('global/events'));
229 | $modelMapping = array_merge($modelMapping, $this->getObserversForPath('frontend/events'));
230 | $modelMapping = array_merge($modelMapping, $this->getObserversForPath('adminhtml/events'));
231 |
232 | echo Wiz::tableOutput($modelMapping);
233 | }
234 |
235 | /**
236 | * returns a list of observers from the configuration XML from
237 | * a config path.
238 | *
239 | * @author Nicholas Vahalik
240 | */
241 | function getObserversForPath($path) {
242 | $config = Mage::getConfig();
243 | foreach ($config->getNode($path)->children() as $parent => $children) {
244 | foreach ($children->children() as $childName => $observerInfo) {
245 | if ((string)$childName !== 'observers') continue;
246 |
247 | foreach($observerInfo as $observerId => $info) {
248 | $modelMapping[] = array(
249 | 'Dispatched event' => $parent,
250 | 'Module' => $observerId,
251 | 'Method' => $info->class . '::' . $info->method
252 | );
253 | }
254 | }
255 | }
256 | return $modelMapping;
257 | }
258 |
259 | /**
260 | * Returns a list of model names to class maps. This will also call out rewritten
261 | * classes so you can see what type of object you will get when you call
262 | * Mage::getModel(_something_).
263 | *
264 | * +------------+-------------------+
265 | * | Model Name | PHP Class |
266 | * +------------+-------------------+
267 | * | varien/* | Varien_* |
268 | * | core/* | Mage_Core_Model_* |
269 | * | ... | |
270 | * +------------+-------------------+
271 | *
272 | * Options:
273 | * --all (shows everything, default)
274 | * --models (shows only models, not resource models)
275 | * --resources (shows only resource models, not models)
276 | *
277 | * @author Nicholas Vahalik
278 | **/
279 | public function modelsAction() {
280 | Wiz::getMagento();
281 | $modelMapping = array();
282 |
283 | $config = Mage::getConfig();
284 |
285 | $showModels = Wiz::getWiz()->getArg('models');
286 | $showResources = Wiz::getWiz()->getArg('resources');
287 |
288 | if (Wiz::getWiz()->getArg('all') || (!$showModels && !$showResources)) {
289 | $showResources = $showModels = true;
290 | }
291 |
292 | foreach ($config->getNode('global/models')->children() as $parent => $children) {
293 | if (substr($parent, -7) == '_mysql4' && !$showResources || substr($parent, -7) != '_mysql4' && !$showModels)
294 | continue;
295 | foreach ($children->children() as $className => $classData) {
296 | switch ($className) {
297 | case 'class':
298 | $modelMapping[] = array(
299 | 'Model Name' => $parent . '/*',
300 | 'PHP Class' => (string)$classData.'_*',
301 | );
302 | break;
303 | case 'rewrite':
304 | foreach ($classData->children() as $rewriteName => $rewriteData) {
305 | $modelMapping[] = array(
306 | 'Model Name' => $parent . '/' . $rewriteName,
307 | 'PHP Class' => (string)$rewriteData,
308 | );
309 | }
310 | default:
311 | break;
312 | }
313 | }
314 | }
315 |
316 | echo Wiz::tableOutput($modelMapping);
317 | }
318 |
319 | /**
320 | * Attempts to output a list of dispatched Magento Events. Currently, it iterates
321 | * recursively over the app/ directory and looks for instances where Mage::dispatchEvent
322 | * is called. It then outputs the first parameter as the "event." Some events have
323 | * variables inside of them (like EAV product events and some controller events).
324 | *
325 | * @return void
326 | * @author Nicholas Vahalik
327 | */
328 | public function eventsAction() {
329 | Wiz::getMagento();
330 | $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(Wiz::getMagentoRoot().DIRECTORY_SEPARATOR.'app'));
331 | foreach ($iterator as $file) {
332 | if (preg_match('#.php$#', $file->getFilename()))
333 | $phpFiles[] = $file->getRealpath();
334 | }
335 | $baseClasses = get_declared_classes();
336 |
337 | foreach ($phpFiles as $fileName) {
338 | $matches = array();
339 | include $fileName;
340 | // echo get_include_path().PHP_EOL;
341 | $extraClasses = get_declared_classes();
342 | // var_dump(array_diff($extraClasses, $baseClasses));
343 | $fileSource = file_get_contents($fileName);
344 | preg_match_all('#Mage::dispatchEvent\((.*)\);#m', $fileSource, $matches);
345 | if (count($matches) > 1 && count($matches[1]) > 1) {
346 | foreach ($matches[1] as $match) {
347 | if (strpos($match, ',') !== FALSE) {
348 | $stuff = explode(',', $match);
349 | $eventName = trim($stuff[0]);
350 | }
351 | else {
352 | $eventName = $match;
353 | }
354 | if (substr($stuff[0], 0, 1) == "'" || substr($stuff[0], 0, 1) == '"') {
355 | $eventName = substr(trim($stuff[0]), 1, -1);
356 | }
357 | $events[] = $eventName;
358 | }
359 | }
360 | }
361 | $events = array_unique($events);
362 | sort($events);
363 | foreach ($events as $eventName) {
364 | $eventOutput[] = array('Event Name' => $eventName);
365 | }
366 | echo Wiz::tableOutput($eventOutput);
367 | }
368 | }
369 |
--------------------------------------------------------------------------------
/app/plugins/Encrypt.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) 2011 Classy Llama Studios
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Encryption Plugin for Wiz
23 | *
24 | * @author Ben Robie
25 | */
26 | Class Wiz_Plugin_Encrypt extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Creates a new encryption key and returns it to the screen
30 | *
31 | * Command: wiz encrypt-resetKey
32 | *
33 | * @author Ben Robie
34 | */
35 | function resetKeyAction() {
36 | Wiz::getMagento();
37 |
38 | if (Mage::getConfig()->getModuleConfig('Enterprise_Pci')){
39 | $file = Mage::getBaseDir('etc') . DS . 'local.xml';
40 | if (!is_writeable($file)) {
41 | throw new Exception('File %s is not writeable.', realpath($file));
42 | }
43 | $contents = file_get_contents($file);
44 | if (null === $key) {
45 | $key = md5(time());
46 | }
47 | $encryptor = clone Mage::helper('core')->getEncryptor();
48 | $encryptor->setNewKey($key);
49 | $contents = preg_replace('/<\!\[CDATA\[(.+?)\]\]><\/key>/s',
50 | 'exportKeys() . ']]>', $contents
51 | );
52 |
53 | file_put_contents($file, $contents);
54 |
55 | Mage::app()->cleanCache();
56 |
57 | echo "\nPlease refer to the application's local.xml file for your new key\n";
58 | } else {
59 | echo 'This version of Magento is not Enterprise' . "\n";
60 |
61 | }
62 | }
63 |
64 | /**
65 | * Resets the encrypted configurations as well as all of the encrypted data in the other
66 | * tables you define.
67 | *
68 | * Command: wiz encrypt-resetData "sales/quote_payment|payment_id|cc_number_enc" "sales/quote_payment|payment_id|cc_cid_enc" "sales/order_payment|entity_id|cc_number_enc"
69 | * The pipe delimeted fields are:
70 | * table alias
71 | * primary key
72 | * encrypted column
73 | *
74 | * @author Ben Robie
75 | */
76 | function resetDataAction($options) {
77 | Wiz::getMagento();
78 | if (Mage::getConfig()->getModuleConfig('Enterprise_Pci')){
79 | require 'enterprise/Enterprise.php';
80 |
81 | $changeEncryption = new Encryption_Change($options);
82 | $changeEncryption->echoConfigPaths();
83 | $changeEncryption->reEncryptDatabaseValues(false);
84 |
85 | } else {
86 | echo 'This version of Magento is not Enterprise' . "\n";
87 | }
88 |
89 | }
90 |
91 |
92 | /**
93 | * Encrypts and stores a given value into the core_config_data table. After re-encryption is done
94 | * you can test that it worked with the "wiz encrypt-decryptTestValue" command.
95 | *
96 | * Command: wiz encrypt-encryptTestValue valuetoencrypt
97 | *
98 | * @author Ben Robie
99 | */
100 | function encryptTestValueAction($options) {
101 | Wiz::getMagento();
102 | $encryptedValue = Mage::helper('core')->encrypt($options[0]);
103 | $config = Mage::getResourceModel('core/config');
104 | $config->saveConfig('wiz/encrypt/test', $encryptedValue, 'default', 0);
105 | Mage::app()->cleanCache();
106 | }
107 |
108 | /**
109 | * Decrypts and echos out the encrypted value sent in by the "wiz encrypt-encryptTestValue" command.
110 | *
111 | * Command: wiz encrypt-decryptTestValue
112 | *
113 | * @author Ben Robie
114 | */
115 | function decryptTestValueAction($options) {
116 | Wiz::getMagento();
117 | $encryptedValue = Mage::getStoreConfig('wiz/encrypt/test');
118 | $decryptedValue = Mage::helper('core')->decrypt($encryptedValue);
119 | $output[] = array('Descripted Value' => $decryptedValue);
120 | echo Wiz::tableOutput($output);
121 | }
122 |
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/app/plugins/Indexer.php:
--------------------------------------------------------------------------------
1 | _getIndexer()->getProcessesCollection();
27 | foreach ($collection as $process) {
28 | $processes[] = $process;
29 | }
30 | } else if (!empty($string)) {
31 | $codes = explode(',', $string);
32 | foreach ($codes as $code) {
33 | $process = $this->_getIndexer()->getProcessByCode(trim($code));
34 | if (!$process) {
35 | echo 'Warning: Unknown indexer with code ' . trim($code) . "\n";
36 | } else {
37 | $processes[] = $process;
38 | }
39 | }
40 | }
41 | return $processes;
42 | }
43 |
44 | /**
45 | * Displays the status of the specified indexing processes.
46 | * If no processes are specified, all will be shown.
47 | *
48 | * @return status of index processes
49 | * @author Nicholas Vahalik
50 | */
51 | public function statusAction($options) {
52 | Wiz::getMagento();
53 |
54 | $processes = $this->_parseIndexerString(count($options) == 0 ? 'all' : implode(',', $options));
55 |
56 | foreach ($processes as $process) {
57 | $row = array();
58 | /* @var $process Mage_Index_Model_Process */
59 |
60 | $status = 'Unknown';
61 | switch ($process->getStatus()) {
62 | case Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX:
63 | $status = 'Require Reindex';
64 | break;
65 |
66 | case Mage_Index_Model_Process::STATUS_RUNNING:
67 | $status = 'Processing';
68 | break;
69 |
70 | case Mage_Index_Model_Process::STATUS_PENDING:
71 | $status = 'Ready';
72 | break;
73 | }
74 |
75 | $mode = 'Unknown';
76 | switch ($process->getMode()) {
77 | case Mage_Index_Model_Process::MODE_REAL_TIME:
78 | $mode = 'Update on Save';
79 | break;
80 | case Mage_Index_Model_Process::MODE_MANUAL:
81 | $mode = 'Manual Update';
82 | break;
83 | }
84 |
85 | $row['Name (code)'] = $process->getIndexer()->getName().' ('.$process->getIndexerCode().')';
86 | $row['Status'] = $status;
87 | $row['Mode'] = $mode;
88 |
89 | $rows[] = $row;
90 | }
91 | echo Wiz::tableOutput($rows);
92 | }
93 |
94 | /**
95 | * Reindexes the specified processes.
96 | *
97 | * @param processes to reindex
98 | * @author Nicholas Vahalik
99 | */
100 | public function reindexAction($options) {
101 | Wiz::getMagento();
102 | $processes = $this->_parseIndexerString(implode(',', $options));
103 |
104 | if (count($processes) == 0) {
105 | echo 'Please specify a process to reindex. Either "all" or run indexer-status for list.' . PHP_EOL;
106 | }
107 |
108 | foreach ($processes as $process) {
109 | /* @var $process Mage_Index_Model_Process */
110 | try {
111 | echo 'Reindexing '.$process->getIndexer()->getName().'...';
112 | $process->reindexEverything();
113 | echo 'done.'.PHP_EOL;
114 | } catch (Mage_Core_Exception $e) {
115 | echo 'exception.'.PHP_EOL;
116 | echo $e->getMessage() . PHP_EOL;
117 | } catch (Exception $e) {
118 | echo 'exception.'.PHP_EOL;
119 | echo $process->getIndexer()->getName() . " index process unknown error:\n";
120 | echo $e . PHP_EOL;
121 | }
122 | }
123 | }
124 |
125 | private function _setMode($processes, $mode) {
126 | $updated = array();
127 |
128 | foreach ($processes as $process) {
129 | /* @var $process Mage_Index_Model_Process */
130 | try {
131 | $process->setMode($mode)->save();
132 | $updated[] = $process->getIndexer()->getName();
133 | } catch (Mage_Core_Exception $e) {
134 | echo $e->getMessage() . PHP_EOL;
135 | } catch (Exception $e) {
136 | echo $process->getIndexer()->getName() . " index process unknown error:\n";
137 | echo $e . PHP_EOL;
138 | }
139 | }
140 | return $updated;
141 | }
142 |
143 | /**
144 | * Changes the status of the indexing processes to "Update on Save".
145 | * If no processes are specified, all processes will be set.
146 | *
147 | * @param processes to index
148 | * @author Nicholas Vahalik
149 | */
150 | public function realtimeAction($options) {
151 | Wiz::getMagento();
152 | $processes = $this->_parseIndexerString(count($options) == 0 ? 'all' : implode(',', $options));
153 | $updated = $this->_setMode($processes, Mage_Index_Model_Process::MODE_REAL_TIME);
154 | echo 'Index' . (count($updated) > 1 ? 'es' : '') . ' set to Update on Save: ' . implode(', ', $updated) . PHP_EOL;
155 | }
156 |
157 | /**
158 | * Changes the status of the indexing processes to "Manual".
159 | * If no processes are specified, all processes will be set.
160 | *
161 | * @param processes to index
162 | * @author Nicholas Vahalik
163 | */
164 | public function manualAction($options) {
165 | Wiz::getMagento();
166 | $processes = $this->_parseIndexerString(count($options) == 0 ? 'all' : implode(',', $options));
167 | $updated = $this->_setMode($processes, Mage_Index_Model_Process::MODE_MANUAL);
168 | echo 'Index' . (count($updated) > 1 ? 'es' : '') . ' set to Manual: ' . implode(', ', $updated) . PHP_EOL;
169 | }
170 | }
--------------------------------------------------------------------------------
/app/plugins/Log.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Log Plugin for Wiz - Code mostly borrowed from Magento's own shell scripts.
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | Class Wiz_Plugin_Log extends Wiz_Plugin_Abstract {
27 | /**
28 | * Retrieve Log instance
29 | *
30 | * @return Mage_Log_Model_Log
31 | */
32 | protected function _getLog() {
33 | if (is_null($this->_log)) {
34 | $this->_log = Mage::getModel('log/log');
35 | }
36 | return $this->_log;
37 | }
38 |
39 | /**
40 | * Convert count to human view
41 | *
42 | * @param int $number
43 | * @return string
44 | */
45 | protected function _humanCount($number) {
46 | if ($number < 1000) {
47 | return $number;
48 | } else if ($number >= 1000 && $number < 1000000) {
49 | return sprintf('%.2fK', $number / 1000);
50 | } else if ($number >= 1000000 && $number < 1000000000) {
51 | return sprintf('%.2fM', $number / 1000000);
52 | } else {
53 | return sprintf('%.2fB', $number / 1000000000);
54 | }
55 | }
56 |
57 | /**
58 | * Convert size to human view
59 | *
60 | * @param int $number
61 | * @return string
62 | */
63 | protected function _humanSize($number) {
64 | if ($number < 1000) {
65 | return sprintf('%d b', $number);
66 | } else if ($number >= 1000 && $number < 1000000) {
67 | return sprintf('%.2fKb', $number / 1000);
68 | } else if ($number >= 1000000 && $number < 1000000000) {
69 | return sprintf('%.2fMb', $number / 1000000);
70 | } else {
71 | return sprintf('%.2fGb', $number / 1000000000);
72 | }
73 | }
74 |
75 | /**
76 | * Displays statistics for each log table.
77 | *
78 | * Adapted from the log.php that ships with Magento.
79 | *
80 | * @author Nicholas Vahalik
81 | */
82 | public function statusAction() {
83 | Wiz::getMagento();
84 | $resource = $this->_getLog()->getResource();
85 | $adapter = $resource->getReadConnection();
86 |
87 | // log tables
88 | $tables = array(
89 | $resource->getTable('log/customer'),
90 | $resource->getTable('log/visitor'),
91 | $resource->getTable('log/visitor_info'),
92 | $resource->getTable('log/url_table'),
93 | $resource->getTable('log/url_info_table'),
94 | $resource->getTable('log/quote_table'),
95 |
96 | $resource->getTable('reports/viewed_product_index'),
97 | $resource->getTable('reports/compared_product_index'),
98 | $resource->getTable('reports/event'),
99 |
100 | $resource->getTable('catalog/compare_item'),
101 | );
102 |
103 | $rows = 0;
104 | $dataLength = 0;
105 | $indexLength = 0;
106 | $rowData = array();
107 |
108 | foreach ($tables as $table) {
109 | $query = $adapter->quoteInto('SHOW TABLE STATUS LIKE ?', $table);
110 | $status = $adapter->fetchRow($query);
111 |
112 | if (!$status) {
113 | continue;
114 | }
115 |
116 | $rows += $status['Rows'];
117 | $dataLength += $status['Data_length'];
118 | $indexLength += $status['Index_length'];
119 |
120 | $rowData[] = array(
121 | 'Table Name' => $table,
122 | 'Rows' => $this->_humanCount($status['Rows']),
123 | 'Data Size' => $this->_humanSize($status['Data_length']),
124 | 'Index Size' => $this->_humanSize($status['Index_length'])
125 | );
126 | }
127 |
128 | $rowData[] = '-';
129 |
130 | $rowData[] = array(
131 | 'Table Name' => 'Totals',
132 | 'Rows' => $this->_humanCount($rows),
133 | 'Data Size' => $this->_humanSize($dataLength),
134 | 'Index Size' => $this->_humanSize($indexLength)
135 | );
136 |
137 | echo Wiz::tableOutput($rowData);
138 | }
139 |
140 | /**
141 | * Cleans Magento's database logs. Uses Magento's global settings.
142 | *
143 | * Adapted from the log.php that ships with Magento.
144 | *
145 | * @author Nicholas Vahalik
146 | */
147 | public function cleanAction() {
148 | Wiz::getMagento('');
149 | $this->_getLog()->clean();
150 | $savedDays = Mage::getStoreConfig(Mage_Log_Model_Log::XML_LOG_CLEAN_DAYS);
151 | echo "Log cleaned. Log days saved: $savedDays".PHP_EOL;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/app/plugins/MC.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Magento Connect Plugin for Wiz
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | class Wiz_Plugin_MC extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Downloads a Magento Connect package.
30 | *
31 | * @param Magento Connect 1.0 or 2.0 Key
32 | * @author Nicholas Vahalik
33 | **/
34 | public function dlAction($options) {
35 | $options = $this->_getFixedOptions($options);
36 | if (count($options) == 0) {
37 | throw new Exception('Please supply a Magento Connect 1.0 or 2.0 key.');
38 | }
39 | $key = $options[0];
40 | $selectedVersion = 'latest';
41 | $selectedBranch = 'stable';
42 |
43 | if (strpos($key, 'connect20') !== FALSE) {
44 | $extensionKey = substr($key, strrpos($key, '/') + 1);
45 |
46 | if (($releases = $this->_getReleaseInformation($key)) !== FALSE) {
47 | $latestRelease = array_pop($releases);
48 | $fileSource = $key . '/' . $latestRelease['v'] . '/' . $extensionKey . '-' . $latestRelease['v'] . '.tgz';
49 | $fileDestination = $extensionKey . '-' . $latestRelease['v'] . '.tgz';
50 | $this->downloadFile($fileSource, $fileDestination);
51 | }
52 | else {
53 | throw new Exception('Unable to find release information. Did you pass the right URL?');
54 | }
55 | }
56 | else {
57 | throw new Exception('Only support MC 2.0 keys at this time. Sorry!');
58 | }
59 | }
60 |
61 | /**
62 | * Get the versions that are available on Magento connect for a given Magento Connect key.
63 | *
64 | * @param Magento Connect 1.0 or 2.0 Key.
65 | * @author Nicholas Vahalik
66 | */
67 | public function versionsAction($options) {
68 | $options = $this->_getFixedOptions($options);
69 | if (count($options) == 0) {
70 | throw new Exception('Please supply a Magento Connect 1.0 or 2.0 key.');
71 | }
72 |
73 | $key = $options[0];
74 |
75 | if (strpos($key, 'connect20') !== FALSE) {
76 | if (($releases = $this->_getReleaseInformation($key)) !== FALSE) {
77 | $releases = array_reverse($releases);
78 | foreach ($releases as $d => $a) {
79 | $releases[$d]['Version'] = $a['v'];
80 | $releases[$d]['Status'] = $a['s'];
81 | $releases[$d]['Date'] = $a['d'];
82 | unset($releases[$d]['v']);
83 | unset($releases[$d]['d']);
84 | unset($releases[$d]['s']);
85 | }
86 | echo Wiz::tableOutput($releases);
87 | }
88 | else {
89 | throw new Exception('Unable to find release information. Did you pass the right URL?');
90 | }
91 | }
92 | else {
93 | throw new Exception('Only support MC 2.0 keys at this time. Sorry!');
94 | }
95 | }
96 |
97 | public function _getReleaseInformation($key) {
98 | if (($content = file_get_contents($key . '/releases.xml')) !== FALSE) {
99 | $releaseXmlData = simplexml_load_string($content);
100 | foreach ($releaseXmlData->r as $entry) {
101 | $releases[] = (array)$entry;
102 | }
103 |
104 | usort($releases, array($this, '_sortReleases'));
105 |
106 | return $releases;
107 | }
108 |
109 | return FALSE;
110 | }
111 |
112 | private function _sortReleases($r1, $r2) {
113 | return $r1['d'] > $r2['d'];
114 | }
115 |
116 | private function downloadFile($source, $destination) {
117 | $data = null;
118 | $chars = array('-', '\\', '|', '/');
119 | $totalChars = count($chars);
120 | $iteration = $downloadedSoFar = $removableChars = 0;
121 |
122 | $fileSize = $this->_getDownloadSize($source);
123 |
124 | printf('Downloading %s...' . PHP_EOL, $source);
125 | $fileDownloadHandler = fopen($source, 'rb');
126 |
127 | if (!$fileDownloadHandler) {
128 | return FALSE;
129 | }
130 |
131 | while (!feof($fileDownloadHandler)) {
132 | $downloadedSoFar = strlen($data);
133 | echo str_repeat("\x08", $removableChars);
134 | if ($fileSize) {
135 | $removableChars = printf("%s %d%%", $chars[$iteration++ % $totalChars], ($downloadedSoFar / $fileSize) * 100);
136 | }
137 | else {
138 | $removableChars = printf("%s %.2fMB downloaded", $chars[$iteration++ % $totalChars], $downloadedSoFar / 1024 / 1024);
139 | }
140 | $data .= fread($fileDownloadHandler, 64000);
141 | }
142 |
143 | echo str_repeat("\x08", $removableChars);
144 | file_put_contents($destination, $data);
145 |
146 | print('done.' . PHP_EOL);
147 | return true;
148 | }
149 |
150 | private function _getDownloadSize($httpFile) {
151 | $headers = @get_headers($httpFile);
152 | foreach ($headers as $header) {
153 | if (substr($header, 0, 14) == 'Content-Length') {
154 | return (int)substr($header, 16);
155 | }
156 | }
157 | return 0;
158 | }
159 |
160 | private function _getFixedOptions($options){
161 | if(
162 | is_array($options) &&
163 | isset($options[0]) &&
164 | strpos($options[0], 'http') !== FALSE &&
165 | isset($options[1]) &&
166 | strpos($options[1], '//') !== FALSE
167 | ){
168 | return array(0=>$options[0] . ':' . $options[1]);
169 | }else{
170 | return $options;
171 | }
172 | }
173 | }
--------------------------------------------------------------------------------
/app/plugins/Magento.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * Magento information class.
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | Class Wiz_Plugin_Magento extends Wiz_Plugin_Abstract {
27 |
28 | /**
29 | * Returns the version of Magento that Wiz is currently pointing to.
30 | *
31 | * @author Nicholas Vahalik
32 | */
33 | function versionAction() {
34 | Wiz::getMagento();
35 | echo Mage::getVersion().PHP_EOL;
36 | }
37 |
38 | /**
39 | * Executes PHP file after bootstrapping Magento.
40 | *
41 | * You can optionally specify the store under which to execute the script by passing
42 | * --store .
43 | *
44 | * You can optionally specify to display Varien_Profiler data by passing --profile.
45 | *
46 | * @param filename
47 | * @author Nicholas Vahalik
48 | */
49 | function scriptAction($options) {
50 | if (count($options) < 1) {
51 | echo 'Please enter a script to execute.'.PHP_EOL;
52 | return FALSE;
53 | }
54 | elseif (!is_readable($options[0])) {
55 | echo 'Please enter a valid filename to execute.'.PHP_EOL;
56 | return FALSE;
57 | }
58 | else {
59 | $path = realpath($options[0]);
60 | Wiz::getMagento();
61 |
62 | // We have to check the settings AFTER we bootstrap Magento so that we can use the Mage class.
63 | if (Wiz::getWiz()->getArg('profile')) {
64 | if (!Mage::getStoreConfig('dev/debug/profiler') || !Mage::helper('core')->isDevAllowed()) {
65 | echo 'Please turn on the Varien_Profiler by executing the "devel-profiler yes" command'.PHP_EOL;;
66 | return FALSE;
67 | } else {
68 | $profiling = true;
69 | }
70 | }
71 |
72 | include $path;
73 |
74 | if ($profiling) {
75 | $this->_flushProfileData();
76 | }
77 | }
78 | }
79 |
80 | /**
81 | * Shuts down Magento by creating the Maintenance flag.
82 | *
83 | * @author Nicholas Vahalik
84 | */
85 | function shutdownAction() {
86 | if (($magentoRoot = Wiz::getMagentoRoot()) === FALSE) {
87 | throw new Exception('Unable to find Magento.');
88 | }
89 |
90 | $maintenanceFile = $magentoRoot . WIZ_DS . 'maintenance.flag';
91 |
92 | if (file_exists($maintenanceFile)) {
93 | echo 'Maintenance file already exists.' . PHP_EOL;
94 | return;
95 | }
96 |
97 | if (!is_writable($magentoRoot)) {
98 | throw new Exception('Cannot create maintenance flag file. Is the directory writable?');
99 | }
100 |
101 | touch($maintenanceFile);
102 |
103 | echo 'Magento maintenance flag has been created.' . PHP_EOL;
104 | }
105 |
106 | /**
107 | * Displays the Varien_Profiler data to the screen. If it is not enabled, it will
108 | * indicate that it is disabled.
109 | *
110 | * @author Ben Robie
111 | **/
112 | function _flushProfileData(){
113 |
114 | $timers = Varien_Profiler::getTimers();
115 |
116 | foreach ($timers as $name=>$timer) {
117 | $sum = Varien_Profiler::fetch($name,'sum');
118 | $count = Varien_Profiler::fetch($name,'count');
119 | $realmem = Varien_Profiler::fetch($name,'realmem');
120 | $emalloc = Varien_Profiler::fetch($name,'emalloc');
121 | if ($sum<.0010 && $count<10 && $emalloc<10000) {
122 | continue;
123 | }
124 |
125 | $output[] = array(
126 | 'Code Profiler' => $name,
127 | 'Time' => $sum,
128 | 'Cnt' => (string) $count,
129 | 'Emalloc' => (string) number_format($emalloc),
130 | 'RealMem' => (string) number_format($realmem),
131 | );
132 |
133 |
134 | }
135 | echo Wiz::tableOutput($output);
136 | }
137 |
138 | /**
139 | * Removes the maintenance flag, allowing Magento to run.
140 | *
141 | * @author Nicholas Vahalik
142 | */
143 | function startAction() {
144 | if (($magentoRoot = Wiz::getMagentoRoot()) === FALSE) {
145 | throw new Exception('Unable to find Magento.');
146 | }
147 |
148 | $maintenanceFile = $magentoRoot . WIZ_DS . 'maintenance.flag';
149 |
150 | if (!file_exists($maintenanceFile)) {
151 | echo 'Maintenance file does not exist.' . PHP_EOL;
152 | return;
153 | }
154 |
155 | if (!is_writable($maintenanceFile)) {
156 | throw new Exception('Cannot remove maintenance flag file. Is the directory writable?');
157 | }
158 |
159 | unlink($maintenanceFile);
160 |
161 | echo 'Magento maintenance flag has been removed.' . PHP_EOL;
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/app/plugins/Module.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | class Wiz_Plugin_Module extends Wiz_Plugin_Abstract {
22 |
23 | /**
24 | * Lists all of the modules that are currently installed on the Magento installation,
25 | * the version in their xml file, the version of the setup resource in the database,
26 | * their code pool, and what their active flag is.
27 | *
28 | * @author Nicholas Vahalik
29 | */
30 | public static function listAction() {
31 | Wiz::getMagento();
32 | $modules = (array)Mage::getConfig()->getNode('modules')->children();
33 | $moduleList = array();
34 |
35 | $coreResource = Mage::getSingleton('core/resource');
36 | $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
37 | $select = $connection->select()->from($coreResource->getTableName('core/resource'), array('code' , 'version'));
38 |
39 | $result = $connection->fetchPairs($select);
40 |
41 | foreach(Mage::getConfig()->getNode('global/resources')->children() as $resourceData) {
42 | $resourceMappings[(string)$resourceData->setup->module] = $resourceData->getName();
43 | }
44 |
45 | foreach ($modules as $moduleName => $moduleData) {
46 | $flag = strtolower(Mage::getConfig()->getNode('advanced/modules_disable_output/' . $moduleName, 'default'));
47 |
48 | $cachedValue = '';
49 | if (isset($resourceMappings[$moduleName])) {
50 | $cachedValue = $resourceMappings[$moduleName];
51 | }
52 | $moduleList[] = array(
53 | 'Module Name' => $moduleName,
54 | 'Version (xml)' => (string)$moduleData->version,
55 | 'Version (db)' => $cachedValue != '' ? (string) $result[$cachedValue] : 'n/a',
56 | 'Active' => $moduleData->active ? 'Active' : 'Disabled',
57 | 'Output' => !empty($flag) && 'false' !== $flag ? 'Disabled' : 'Enabled',
58 | 'Code Pool' => $moduleData->codePool,
59 | );
60 | }
61 |
62 | echo Wiz::tableOutput($moduleList);
63 | }
64 |
65 | /**
66 | * Enables a module. You can pass a module name or a list of module names seperated
67 | * by spaces.
68 | *
69 | * Usage: wiz module-enable NS_ModuleName NS_ModuleName2
70 | *
71 | * @param List of modules to enable seperated by spaces.
72 | * @author Nicholas Vahalik
73 | */
74 | public static function enableAction($options) {
75 | if (count($options) < 1) {
76 | throw new Exception('Please provide the names of modules to enable.');
77 | }
78 | $modulesEnabled = $modulesAlreadyEnabled = array();
79 | Wiz::getMagento();
80 | $modules = (array)Mage::getConfig()->getNode('modules')->children();
81 |
82 | foreach ($options as $moduleName) {
83 | foreach ($modules as $systemModuleName => $moduleData) {
84 | if (strtolower($moduleName) == strtolower($systemModuleName)) {
85 | $filesToCheck[] = BP . DS . 'app' . DS . 'etc' . DS . 'modules' . DS . $systemModuleName . '.xml';
86 |
87 | if (!file_exists($filesToCheck[0])) {
88 | $filesToCheck += glob(BP . DS . 'app' . DS . 'etc' . DS . 'modules' . DS . substr($systemModuleName, 0, strpos($systemModuleName, '_') + 1) . '*');
89 | }
90 |
91 | $file = array_shift($filesToCheck);
92 |
93 | do {
94 | $configFile = simplexml_load_file($file);
95 | if ($configFile->modules->{$systemModuleName}->active == 'true') {
96 | $modulesAlreadyEnabled[] = $systemModuleName;
97 | }
98 | else {
99 | $configFile->modules->{$systemModuleName}->active = 'true';
100 | $configFile->asXml($file);
101 | $modulesEnabled[] = $systemModuleName;
102 | }
103 | } while (($file = array_shift($filesToCheck)) != NULL);
104 |
105 | break;
106 | }
107 | }
108 | }
109 |
110 | if (count($modulesEnabled) > 0) {
111 | echo 'Module(s) enabled: '.implode(', ', $modulesEnabled). PHP_EOL;
112 | Mage::getConfig()->removeCache();
113 | }
114 |
115 | if (count($modulesAlreadyEnabled)) {
116 | echo 'Module(s) already enabled: '.implode(', ', $modulesAlreadyEnabled). PHP_EOL;
117 | }
118 | }
119 |
120 | /**
121 | * You can pass a module name or a list of module names seperated
122 | * by spaces.
123 | *
124 | * Usage: wiz module-disable NS_ModuleName1 NS_ModuleName2
125 | *
126 | * Please note: modules with dependencies will not be disabled unless all of the
127 | * dependencies are disabled first. Modules with loaded dependencies will not be
128 | * disabled until those dependencies themselves are disabled.
129 | *
130 | * @param List of modules to disable seperated by spaces.
131 | * @author Nicholas Vahalik
132 | */
133 | public static function disableAction($options) {
134 | if (count($options) < 1) {
135 | echo 'Please provide modules names to disable.'.PHP_EOL;
136 | }
137 | $modulesDisabled = $modulesAlreadyDisabled = $filesToCheck = array();
138 | Wiz::getMagento();
139 | $disabled = $alreadyDisabled = FALSE;
140 | $modules = (array)Mage::getConfig()->getNode('modules')->children();
141 |
142 | foreach ($modules as $moduleName => $moduleData) {
143 | if ($moduleData->depends) {
144 | foreach (array_keys((array)$moduleData->depends) as $depModule) {
145 | $depends[$depModule][] = $moduleName;
146 | }
147 | }
148 | }
149 |
150 | foreach ($options as $moduleName) {
151 | $filesToCheck = array();
152 |
153 | foreach ($modules as $systemModuleName => $moduleData) {
154 | if (strtolower($moduleName) == strtolower($systemModuleName)) {
155 |
156 | if (array_key_exists($systemModuleName, $depends) and count($depends[$systemModuleName]) > 0) {
157 | echo 'Skipping ' . $systemModuleName . ' due to dependencies: ' . implode(', ', $depends[$systemModuleName]).PHP_EOL;
158 | break;
159 | }
160 |
161 | $filesToCheck[] = BP . DS . 'app' . DS . 'etc' . DS . 'modules' . DS . $systemModuleName . '.xml';
162 |
163 | if (!file_exists($filesToCheck[0])) {
164 | $filesToCheck += glob(BP . DS . 'app' . DS . 'etc' . DS . 'modules' . DS . substr($systemModuleName, 0, strpos($systemModuleName, '_') + 1) . '*');
165 | }
166 |
167 | $file = array_shift($filesToCheck);
168 |
169 | do {
170 | $configFile = simplexml_load_file($file);
171 | if ($configFile->modules->{$systemModuleName}->active == 'false') {
172 | $modulesAlreadyDisabled[] = $systemModuleName;
173 | break 2;
174 | }
175 | else {
176 | $configFile->modules->{$systemModuleName}->active = 'false';
177 | $configFile->asXml($file);
178 | $modulesDisabled[] = $systemModuleName;
179 | break 2;
180 | }
181 | } while (($file = array_shift($filesToCheck)) != NULL);
182 |
183 | break 2;
184 | }
185 | }
186 | }
187 |
188 | if (count($modulesDisabled) > 0) {
189 | echo 'Module(s) disabled: '.implode(', ', $modulesDisabled). PHP_EOL;
190 | Mage::getConfig()->removeCache();
191 | }
192 |
193 | if (count($modulesAlreadyDisabled)) {
194 | echo 'Module(s) already disabled: '.implode(', ', $modulesAlreadyDisabled). PHP_EOL;
195 | }
196 | }
197 |
198 | /**
199 | * Enables output for a module. This performs the same task as the Disable Module
200 | * Output page in the Magento backend.
201 | *
202 | * @author Nicholas Vahalik
203 | */
204 | public static function enableoutputAction($options) {
205 | if (count($options) < 1) {
206 | echo 'Please provide modules names to enable output on.'.PHP_EOL;
207 | }
208 | $modulesEnabled = $modulesAlreadyEnabled = array();
209 |
210 | Wiz::getMagento();
211 |
212 | $modules = (array)Mage::getConfig()->getNode('modules')->children();
213 |
214 | foreach ($options as $moduleName) {
215 | foreach ($modules as $systemModuleName => $moduleData) {
216 | if (strtolower($moduleName) == strtolower($systemModuleName)) {
217 | $flag = strtolower(Mage::getConfig()->getNode('advanced/modules_disable_output/' . $systemModuleName, 'default'));
218 | if (!empty($flag) && 'false' !== $flag) {
219 | Mage::getConfig()->saveConfig('advanced/modules_disable_output/' . $systemModuleName, FALSE);
220 | $modulesEnabled[] = $systemModuleName;
221 | }
222 | else {
223 | $modulesAlreadyEnabled[] = $systemModuleName;
224 | }
225 | break;
226 | }
227 | }
228 | }
229 |
230 | if (count($modulesEnabled) > 0) {
231 | echo 'Module(s) output enabled: '.implode(', ', $modulesEnabled). PHP_EOL;
232 | Mage::getConfig()->removeCache();
233 | }
234 |
235 | if (count($modulesAlreadyEnabled)) {
236 | echo 'Module(s) output already enabled: '.implode(', ', $modulesAlreadyEnabled). PHP_EOL;
237 | }
238 | }
239 |
240 | /**
241 | * Disables output for a module. This performs the same task as the Disable Module
242 | * Output page in the Magento backend.
243 | *
244 | * @author Nicholas Vahalik
245 | */
246 | public static function disableoutputAction($options) {
247 | if (count($options) < 1) {
248 | echo 'Please provide modules names to enable.'.PHP_EOL;
249 | }
250 | $modulesDisable = $modulesAlreadyDisabled = array();
251 | Wiz::getMagento();
252 | $modules = (array)Mage::getConfig()->getNode('modules')->children();
253 |
254 | foreach ($options as $moduleName) {
255 | foreach ($modules as $systemModuleName => $moduleData) {
256 | if (strtolower($moduleName) == strtolower($systemModuleName)) {
257 | $flag = strtolower(Mage::getConfig()->getNode('advanced/modules_disable_output/' . $systemModuleName, 'default'));
258 | if (empty($flag) || 'false' === $flag) {
259 | Mage::getConfig()->saveConfig('advanced/modules_disable_output/' . $systemModuleName, TRUE);
260 | // self::changeModuleOutput($systemModuleName, 'disabled');
261 | $modulesDisabled[] = $systemModuleName;
262 | }
263 | else {
264 | $modulesAlreadyDisabled[] = $systemModuleName;
265 | }
266 | break;
267 | }
268 | }
269 | }
270 |
271 | if (count($modulesDisabled) > 0) {
272 | echo 'Module(s) disabled: '.implode(', ', $modulesDisabled). PHP_EOL;
273 | Mage::getConfig()->removeCache();
274 | }
275 |
276 | if (count($modulesAlreadyDisabled)) {
277 | echo 'Module(s) already disabled: '.implode(', ', $modulesAlreadyDisabled). PHP_EOL;
278 | }
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/app/plugins/Sql.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * SQL Plugin for Wiz
23 | *
24 | * @author Nicholas Vahalik
25 | */
26 | class Wiz_Plugin_Sql extends Wiz_Plugin_Abstract {
27 |
28 | private function _getDbConfig($config = 'core') {
29 | Wiz::getMagento();
30 | $resources = Mage::getSingleton('core/resource');
31 | $connection = $resources->getConnection('core');
32 | $config = $connection->getConfig();
33 | return $config;
34 | }
35 |
36 | /**
37 | * Returns information about the database resource connection.
38 | *
39 | * @param database connection to use (default: 'core')
40 | * @author Nicholas Vahalik
41 | */
42 | public function infoAction($options) {
43 | $config = $this->_getDbConfig();
44 | foreach ($config as $key => $value) {
45 | if (!$value) continue;
46 | if (is_array($value)) {
47 | $value = var_export($value, TRUE);
48 | }
49 | echo $key . ' = '. $value.PHP_EOL;
50 | }
51 | echo 'MySQL command line: '."mysql -u{$config['username']} -p{$config['password']}".( $config['port'] ? " -P{$config['port']}" : '')." -h{$config['host']} {$config['dbname']}".PHP_EOL;
52 | }
53 |
54 | /**
55 | * Opens up a shell command directly to the the database server.
56 | *
57 | * @param string $options
58 | * @author Nicholas Vahalik
59 | */
60 | public function cliAction($options) {
61 | $config = $this->_getDbConfig();
62 | proc_close(proc_open("mysql -u{$config['username']} -p{$config['password']}".( $config['port'] ? " -P{$config['port']}" : '')." -h{$config['host']} {$config['dbname']}", array(0 => STDIN, 1 => STDOUT, 2 => STDERR), $pipes));
63 | }
64 |
65 | /**
66 | * Executes a query against the database. You must enclose the query in single-quotes.
67 | * You can optionally specify MySQL's batch mode by adding the word batch after the
68 | * query. Ensure not to add a semi-colon after the end of the query otherwise it
69 | * will think you meant to end the bash command.
70 | *
71 | * Example: sql-exec 'select * from core_resource' batch
72 | *
73 | * @param SQL Query
74 | * @param batch (optionally specifies batch mode)
75 | * @author Nicholas Vahalik
76 | */
77 | public function execAction($options) {
78 | $query = mysql_real_escape_string(array_shift($options));
79 | $config = $this->_getDbConfig();
80 | if (count($options) > 0 && $options[0] == 'batch') {
81 | $batch = '--batch';
82 | }
83 | proc_close(proc_open("mysql $batch -u{$config['username']} -p{$config['password']} -P{$config['port']} -h{$config['host']} {$config['dbname']} -e \"$query\"", array(0 => STDIN, 1 => STDOUT, 2 => STDERR), $pipes));
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/plugins/Store.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | class Wiz_Plugin_Store extends Wiz_Plugin_Abstract {
22 |
23 | /**
24 | * Lists all of the stores, store codes, and websites on the magento installation.
25 | *
26 | * @author Nicholas Vahalik
27 | */
28 | public static function listAction() {
29 | Wiz::getMagento();
30 | $storeCollection = Mage::getModel('core/store')->getCollection();
31 | foreach ($storeCollection as $store) {
32 | $rows[] = array(
33 | 'Website (Id)' => $store->getWebsite()->getCode().' ('.$store->getWebsiteId().')'. ($store->getWebsite()->getIsDefault() ? /*" \033[1;37;40m*/' default'/*\033[0m" */: ''),
34 | 'Group (Id)' => $store->getGroup()->getName().' ('.$store->getGroup()->getId().')',
35 | 'Code (Id)' => $store->getName() . ' ('.$store->getCode().')',
36 | 'Active' => $store->getIsActive(),
37 | );
38 | }
39 | echo Wiz::tableOutput($rows);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/plugins/enterprise/Enterprise.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) 2011 Classy Llama Studios
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | /**
22 | * An extention to the Enterprise_Pci_Model_Resource_Key_Change class that allows for the re-encryption
23 | * of more than just the one table listed in Enterprise_Pci_Model_Resource_Key_Change.
24 | *
25 | * @author Ben Robie
26 | */
27 |
28 | class Encryption_Change extends Enterprise_Pci_Model_Resource_Key_Change {
29 |
30 | protected $options = array();
31 |
32 | public function __construct($options){
33 | parent::__construct();
34 | $this->options = $options;
35 | }
36 |
37 | /**
38 | * Gather saved credit card numbers (or other encrypted data) from the given tables
39 | * and re-encrypt them.
40 | *
41 | * @author Ben Robie
42 | */
43 | protected function _reEncryptCreditCardNumbers() {
44 | $output = array();
45 |
46 | foreach($this->options as $index => $info) {
47 | $tableInfo = explode('|', $info);
48 | $table = $this->getTable($tableInfo[0]);
49 | $select = $this->_getWriteAdapter()->select()->from($table, array(
50 | $tableInfo[1],
51 | $tableInfo[2] ));
52 |
53 | $attributeValues = $this->_getWriteAdapter()->fetchPairs($select);
54 | $counts = array();
55 | $count = 0;
56 | foreach($attributeValues as $valueId=>$value) {
57 | if ($value){
58 | $count++;
59 | $this->_getWriteAdapter()->update($table, array(
60 | $tableInfo[2] => $this->_encryptor->encrypt($this->_encryptor->decrypt($value)) ), array(
61 | $tableInfo[1] . ' = ?' => (int) $valueId ));
62 | }
63 | }
64 | $output[] = array('table' => $table, 'column'=> $tableInfo[2], 'count'=> $count);
65 | }
66 | // Re-Encrypt the test config if it is there.
67 | $encryptedValue = Mage::getStoreConfig('wiz/encrypt/test');
68 | $reEncryptedValue = $this->_encryptor->encrypt($this->_encryptor->decrypt($encryptedValue));
69 | $config = Mage::getResourceModel('core/config');
70 | $config->saveConfig('wiz/encrypt/test', $reEncryptedValue, 'default', 0);
71 |
72 | echo Wiz::tableOutput($output);
73 | }
74 |
75 | /**
76 | * Prints out all of the config paths that are marked as encrypted
77 | *
78 | * @author Ben Robie
79 | */
80 | public function echoConfigPaths(){
81 | $output = array();
82 | $paths = Mage::getSingleton('adminhtml/config')->getEncryptedNodeEntriesPaths();
83 | foreach ($paths as $path){
84 | $output[] = array('core_config_data path' => $path);
85 | }
86 | echo Wiz::tableOutput($output);
87 |
88 | }
89 | }
--------------------------------------------------------------------------------
/wiz:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ##
3 | # Wiz
4 | #
5 | # NOTICE OF LICENSE
6 | #
7 | # This source file is subject to the Open Software License (OSL 3.0)
8 | # http://opensource.org/licenses/osl-3.0.php
9 | #
10 | # DISCLAIMER
11 | #
12 | # This program is provided to you AS-IS. There is no warranty. It has not been
13 | # certified for any particular purpose.
14 | #
15 | # @copyright Copyright (c) 2012 by Classy Llama Studios, LLC
16 | # @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17 | ##
18 |
19 | WIZ_PATH="$0";
20 | if [[ -L "$WIZ_PATH" ]]; then
21 | WIZ_PATH="`readlink -n $WIZ_PATH`";
22 | fi
23 |
24 | WIZ_DIR="`dirname $WIZ_PATH`";
25 | WIZ_PHP_VERSION="5.2";
26 |
27 | # If no valid PHP executable has been set in WIZ_PHP_PATH, iterate PATH looking for one
28 | if [ ! -x "$WIZ_PHP_PATH" ] || [ "`$WIZ_PHP_PATH -r "echo (int) version_compare(PHP_VERSION, '$WIZ_PHP_VERSION', '>=');"`" == "0" ]; then
29 | IFS=:
30 | for i in $PATH; do
31 | if [ -x "$i/php" ]; then
32 | WIZ_PHP_VALID=`$i/php -r "echo (int) version_compare(PHP_VERSION, '$WIZ_PHP_VERSION', '>=');"`
33 | if [ "$WIZ_PHP_VALID" == "1" ]; then
34 | WIZ_PHP_PATH="$i/php"
35 | break;
36 | fi
37 | fi
38 | done
39 | fi
40 |
41 | # Validate that we have a valid executable file on our hands and that one has been found.
42 | if [ ! -x "$WIZ_PHP_PATH" ]; then
43 | echo "ERROR: Could not find a PHP executable >= $WIZ_PHP_VERSION. Please set WIZ_PHP_PATH to a valid PHP executable binary and try again."
44 | exit;
45 | fi
46 |
47 | # Begin tool execution
48 | $WIZ_PHP_PATH -f "$WIZ_DIR/wiz.php" $@
49 |
--------------------------------------------------------------------------------
/wiz.bash_completion.sh:
--------------------------------------------------------------------------------
1 | # Usage:
2 | # Put the following in ~/.bash_completion
3 | # or add the line below to your .profile/.bashrc/.bash_profile and enjoy:
4 | # source $WIZ_HOME/wiz.bash_completion.sh
5 |
6 | _wiz() {
7 | local cur prev opts
8 | COMPREPLY=()
9 | cur="${COMP_WORDS[COMP_CWORD]}"
10 | prev="${COMP_WORDS[COMP_CWORD-1]}"
11 | if [ $COMP_CWORD -eq 1 ]; then prev='wiz'; fi
12 | case "${prev}" in
13 | wiz)
14 | opts="301-urlskumap 301-urlcatmap 301-htgen 301-xmlsm2csv admin-disable admin-enable admin-list admin-resetpass admin-createadmin admin-timeout admin-resources cache-clear cache-enable cache-disable cache-status config-get config-storeget config-xpath config-asxml cron-jobs cron-listeners cron-run devel-showhints devel-logging devel-allowsymlinks devel-config devel-profiler devel-mergejs devel-mergecss devel-listeners devel-models devel-events indexer-status indexer-reindex indexer-realtime indexer-manual log-status log-clean magento-version magento-script magento-shutdown magento-start mc-dl mc-versions module-list module-enable module-disable module-enableoutput module-disableoutput sql-info sql-cli sql-exec store-list command-list help"
15 | opts="${opts} --store --website --batch"
16 | ;;
17 | magento-script)
18 | opts="$(ls *.php)"
19 | ;;
20 | module-disable | module-enable | module-disableoutput | module-enableoutput)
21 | opts="$(_wiz_mage_exts)"
22 | ;;
23 | admin-disable)
24 | opts="$(wiz admin-list --batch | grep -E ',Active$' | cut -f 2 -d ',' | tr '\n' ' ')"
25 | ;;
26 | admin-enable)
27 | opts="$(wiz admin-list --batch | grep -E ',Inactive$' | cut -f 2 -d ',' | tr '\n' ' ')"
28 | ;;
29 | admin-resetpass)
30 | opts="$(wiz admin-list --batch | cut -f 2 -d ',' | tr '\n' ' ')"
31 | ;;
32 | cache-clear)
33 | opts="$(wiz cache-status --batch | tail -n +2 | cut -f 2 -d ',' | tr '\n' ' ')"
34 | ;;
35 | cache-disable)
36 | opts="$(wiz cache-status --batch | grep -E ',Enabled$' | cut -f 2 -d ',' | tr '\n' ' ')"
37 | ;;
38 | cache-enable)
39 | opts="$(wiz cache-status --batch | grep -E ',Disabled$' | cut -f 2 -d ',' | tr '\n' ' ')"
40 | ;;
41 | devel-showhints | devel-logging | devel-allowsymlinks | devel-config | devel-profiler | devel-mergejs | devel-mergecss)
42 | opts="totally yes 1 true nah no 0 false"
43 | ;;
44 | indexer-reindex)
45 | opts="$(wiz indexer-status --batch | tail -n +2 | sed -e 's/.*(\(.*\)).*/\1/g' | tr '\n' ' ')"
46 | ;;
47 | indexer-realtime)
48 | opts="$(wiz indexer-status --batch | grep -E ',"Manual Update"$' | sed -e 's/.*(\(.*\)).*/\1/g' | tr '\n' ' ')"
49 | ;;
50 | indexer-manual)
51 | opts="$(wiz indexer-status --batch | grep -E ',"Update on Save"$' | sed -e 's/.*(\(.*\)).*/\1/g' | tr '\n' ' ')"
52 | ;;
53 | esac
54 |
55 | case "${prev}" in
56 | admin-list | module-list | admin-resources | cache-status | config-xpath | cron-jobs | cron-listeners | devel-config | devel-listeners | devel-models | indexer-status | store-list)
57 | opts="${opts} --batch"
58 | esac
59 |
60 | COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
61 | return 0
62 | }
63 |
64 | _wiz_mage_exts() {
65 | echo "$(wiz module-list --batch | tail -n +2 | cut -f 1 -d , | tr '\n' ' ')"
66 | }
67 |
68 | complete -F _wiz wiz
69 |
--------------------------------------------------------------------------------
/wiz.php:
--------------------------------------------------------------------------------
1 |
17 | * @copyright Copyright (c) by 2012 Classy Llama Studios, LLC
18 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19 | */
20 |
21 | include 'app/Wiz.php';
22 |
23 | $wiz = Wiz::getWiz();
24 | $wiz->run();
25 |
--------------------------------------------------------------------------------