Instantly share code, notes, and snippets.

Embed
What would you like to do?
modCli; using MODX on the commandline.

modCLI

modCLI is a wrapper for the MODX Revolution Processors, allowing you to pretty much do anything from the commandline that you would normally do within the manager.

To use modCLI, simply download the modcli.php file and put it in the MODX_BASE_PATH of your installation. Next open up the console or terminal, and start firing some commands at it.

Syntax

php modcli.php processor [field=value [field=value]..]

The processor needs to be a valid processor in your core/model/modx/processors/ directory, minus the extension. Specifying field=value pairs will pass these on as properties to the processor, just like using AJAX in the manager would.

By specifying the "debug" keyword anywhere in the command, you will get to see a bit more of information. By specifying a processors_path=/absolute/path/to/processors/ you can override the path to look in for processors, for example to hit up a processor belonging to a different package.

Examples

Create a new resource with a pagetitle and content under resource 6.

php modcli.php resource/create pagetitle=Awesome! parent=6 content=Awesomer!
# Running modCLI 0.1.0-pl in modcli.php
# Processor: resource/create
# Properties: 
#    pagetitle       => Awesome! 
#    parent          => 6 
#    content         => Awesomer! 

> Object retrieved: 
>    id              => 20

Create a new resource with a pagetitle and content under resource 6, this time with debug enabled.

php modcli.php resource/create pagetitle=Awesome! parent=6 content=Awesomer! debug
# Running modCLI 0.1.0-pl in modcli.php
# Debug is enabled.
# Processor: resource/create
# Properties: 
#    pagetitle       => Awesome! 
#    parent          => 6 
#    content         => Awesomer! 

> Raw response: Array
(
    [success] => 1
    [message] => 
    [total] => 0
    [errors] => Array
        (
        )

    [object] => Array
        (
            [id] => 21
        )

)

> Response type: get 
> Object retrieved: 
>    id              => 21
```

List the packages in the manager, starting at #2 and only returning one result.

    php modcli.php workspace/packages/getlist limit=1 start=2
    

Running modCLI 0.1.0-pl in modcli.php

Processor: workspace/packages/getlist

Properties:

limit => 1

start => 2

Amount of Results: 8 Result 1: signature => login-1.8.1-pl created => Sep 07, 2012 12:59 AM updated => Sep 07, 2012 01:01 AM installed => Sep 07, 2012 01:01 AM state => 0 workspace => 1 provider => 0 disabled => source => login-1.8.1-pl.transport.zip manifest => package_name => login version_major => 1 version_minor => 8 version_patch => 1 release => pl release_index => 0 provider_name => name => login version => 1.8.1 iconaction => icon-uninstall textaction => Uninstall readme => --------------------
Snippet: Login
--------------------
Version: 1.7
Sin... updateable =>



## Limitations, bugs & other things
Currently, the properties only support a single word (every space denotes a next field). Multi-word properties are on the roadmap but need to be implemented..

### Using PHP on the commandline when running MAMP (Mac)
When using modCLI on Mac running MAMP, you may get weird errors about PDO::CONNECT and what not with a number of processors. 
This is because it is using the Mac-included PHP binary, and not the one from MAMP. To get past this issue, add the following
lines to your ~/.bash_profile (Of course updating the path depending on your version of both MAMP and PHP):

    alias mphp='/Applications/MAMP/bin/php/php5.4.4/bin/php'
    
and restarting your terminal or typing `. ~/.bash_profile` to load in the new configuration.

After you did that you can start using the `mphp` command instead of `php` in the above examples, which should then work. 
You can test if the binary is properly loaded with `mphp --version`. 
<?php
/**
* modCLI is a command line interface for MODX Revolution Processors.
*
* It enables you to run any core or third party processor from the command line, passing it options as you go along.
*
* @author Mark Hamstra <hello@markhamstra.com>
* @version 0.1.1-pl, 2013-07-26
* @license GPL v2
*/
// Make sure we're on the command line.
if (realpath($_SERVER['argv'][0]) != __FILE__)
{
die('This is CLI script! You can not run it from the web!');
}
define('MODCLI_VERSION','0.1.0-pl');
/**
* Format keys (passed by reference) padded to $padLength with spaces and ellepsis.
* @param $key
* @param int $padLength
*/
function formatKey(&$key, $padLength = 15) {
if (strlen($key) > 15) $key = substr($key, 0, 13) . "..";
$key = str_pad($key, 15);
}
/**
* Format values (passed by reference) limited to $maxLength characters, with a $prefix and $prePad amount of spaces.
* @param $value
* @param int $maxLength
* @param string $prefix
* @param int $prePad
* @param bool $preBreakIfMultiline
*/
function formatValue(&$value, $maxLength = 200, $prefix = '>', $prePad = 6, $preBreakIfMultiline = true) {
if (strlen($value) > $maxLength) {
$value = substr($value, 0, $maxLength - 3) . "...";
}
$value = str_replace("\n", "\n" . $prefix . str_repeat(' ', $prePad), $value);
if ($preBreakIfMultiline && substr_count($value, "\n") > 0) {
$value = "\n" . $prefix . str_repeat(' ', $prePad) . $value;
}
}
// include modX
define('MODX_API_MODE', true);
require_once(dirname(__FILE__) . '/index.php');
$modx= new modX();
$modx->initialize('mgr');
$modx->getService('error','error.modError', '', '');
/* Ensure log entries are echo-ed straight to the console */
$modx->setLogTarget('ECHO');
$modx->setLogLevel(modX::LOG_LEVEL_INFO);
// Get the cli options
$scriptProperties = array();
$processor = $argv[1];
parse_str(implode('&', array_slice($argv, 2)), $scriptProperties);
$debug = (in_array('debug', $argv));
// Show some infos.
echo "# Running modCLI ".MODCLI_VERSION." in {$argv[0]}\n";
if ($debug) {
echo "# Debug is enabled.\n";
}
// Make sure we have a processor to call, otherwise display a bit of help.
if (empty($processor) || in_array($processor, array('--help', '-help', '-h', '-?'))) {
echo "modCLI Usage: \n\tphp {$argv[0]} <processor> [[field=value] [field=value] ...]
\t\t where <processor> is a valid core processor.\n\n";
exit(1);
}
// Show processor name to user.
echo "# Processor: {$processor}\n";
// Allow overriding of the processors_path; this allows running 3rd party processors too.
$options = array();
if (isset($scriptProperties['processors_path']) && !empty($scriptProperties['processors_path'])) {
$options['processors_path'] = $scriptProperties['processors_path'];
echo "# Processor Path: {$options['processors_path']} \n";
}
// Show the properties we are passing (if any).
if (!empty($scriptProperties)) {
echo "# Properties: \n";
foreach ($scriptProperties as $key => $value) {
// Get rid of some unneeded properties
if (in_array($key, array('processors_path', 'debug'))) {
unset($scriptProperties[$key]);
continue;
}
formatKey($key);
formatValue($value, 200, '#');
// Show the property on screen.
echo "# {$key} => {$value} \n";
}
}
echo "\n";
// Run the processor.
$result = $modx->runProcessor($processor, $scriptProperties, $options);
// If the $result is a modProcessorResponse, it was a valid processor. Otherwise not so much.
if ($result instanceof modProcessorResponse) {
// Get the raw response
$response = $result->getResponse();
// If it's not an array yet, it may be a JSON collection. Try that.
if (!is_array($response)) {
$responseFromJSON = $modx->fromJSON($response);
if ($responseFromJSON !== false) {
$response = $responseFromJSON;
}
}
if ($debug) {
echo "> Raw response: " . print_r($response, true) . "\n";
}
// Dealing with a "get" processor.
if ($result->hasObject()) {
if ($debug) echo "> Response type: get \n";
// Get the returned object.
$object = $result->getObject();
echo "> Object retrieved: \n";
// Output object properties
foreach ($object as $key => $value) {
formatKey($key);
formatValue($value, 200, '>', 8);
echo "> {$key} => {$value}\n";
}
}
// Dealing with a "getlist" processor
elseif (isset($response['total']) && is_numeric($response['total']) && isset($response['results'])) {
if ($debug) echo "> Response type: getlist \n";
echo "> Amount of Results: {$response['total']} \n";
foreach ($response['results'] as $idx => $item) {
// Increase idx by 1 to make it more human-like.
$idx++;
echo "> Result {$idx}:\n";
foreach ($item as $key => $value) {
// Nicely format the key.
formatKey($key);
formatValue($value, 100, '>', 8);
echo "> {$key} => {$value}\n";
}
}
}
// Dealing with a more "do-y" kind of processor with success or error
else {
if ($debug) echo "> Response type: do-y stuff \n";
if ($result->isError()) {
echo "Uh oh, something went wrong. \n";
// Show errors if we have them.
$fieldErrors = $result->getAllErrors();
if (!empty($fieldErrors)) {
echo "Errors:\n";
foreach ($fieldErrors as $error) {
echo " {$error} \n";
}
}
echo "\n";
exit(1);
}
}
} else {
echo "Error: Processor not found. \n\n";
exit (1);
}
echo "\n";
exit(0);
@carnevlu

This comment has been minimized.

carnevlu commented Nov 29, 2016

Hi @Mark-H now that define('MODX_API_MODE', true); is deprecated, how archive the same behaviour without login?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment