'drush_patterns_enable', 'description' => 'Enable the specified pattern name', 'examples' => array( 'drush patterns enable pattern_name [first-update|always|update|first|never]' => 'Enable the pattern specified by pattern id or pattern name' ), 'arguments' => array( 'id' => 'A pattern id or name', ), 'drupal dependencies' => array('patterns', 'token'), 'core' => array('6'), ); $items['patterns-import'] = array( 'callback' => 'drush_patterns_import', 'description' => 'Import the specified pattern file.', 'examples' => array( 'drush patterns import path/to/patterns/file.[xml/yaml]' => 'Import the specified pattern file.', 'drush patterns import path/to/pattern/file.[xml/yaml] pattern_name' => 'Import the specified pattern file and give it a machine readable name' ), 'arguments' => array( 'pattern_file' => 'The path to a pattern file, beginning from the Drupal base directory', 'pattern_name' => 'Enter a pattern name if you wish to override the title field entered in a pattern.' ), 'drupal dependencies' => array('patterns', 'token'), 'core' => array('6'), ); $items['patterns-run'] = array( 'callback' => 'drush_patterns_run', 'description' => 'Import and enable the specified pattern file', 'examples' => array( 'drush patterns run path/to/patterns/file.[xml/yaml]' => 'Import and enable the specified pattern file', 'drush patterns import path/to/pattern/file.[xml/yaml] pattern_name' => 'Import and enable the specified pattern file and give it a machine readable name' ), 'arguments' => array( 'pattern_file' => 'The path to a pattern file', 'pattern_name' => 'An optional machine-readable pattern name to override the one automatically generated from the title field of the pattern' ), 'drupal dependencies' => array('patterns', 'token'), 'core' => array('6'), ); $items['patterns-list'] = array( 'callback' => 'drush_patterns_list', 'description' => "List all available patterns." ); $items['patterns-info'] = array( 'callback' => 'drush_patterns_info', 'description' => "Show all info on a given pattern.", 'arguments' => array( 'id' => "The pattern id or name of the pattern for which to show info.", ) ); //NOT CLEANED YET $items['patterns-form-helper'] = array( 'description' => 'Enable/disable patterns form helper', 'arguments' => array( 'action' => "Valid values: enable, disable.", ) ); $items['patterns-allow-publish'] = array( 'description' => 'Enable/disable patterns publishing', 'arguments' => array( 'action' => "Valid values: enable, disable.", ) ); $items['patterns-paths'] = array( 'description' => "List all paths patterns will be looked for", ); $items['patterns-publish'] = array( 'description' => "Publish a pattern.", 'arguments' => array( 'pid' => "The ID of the pattern to publish.", ) ); $items['patterns-unpublish'] = array( 'description' => "Unpublish a pattern.", 'arguments' => array( 'pid' => "The ID of the pattern to unpublish.", ) ); return $items; } /** * Imports, Enables, and Runs the specified pattern file * @param string pattern file pathname * @param string optional machine readable pattern name */ function drush_patterns_run($pattern_file, $pattern_name='') { /** Since I want to be able to specify a file name in my interface, in * order to use the patterns_get_pattern() logic as is, I need to * standardize on pattern name, and fire off this "redundant" query to do * so. I'm trading off efficiency for ensuring future compatibility with * patterns module.*/ $name = db_result(db_query("SELECT name FROM {patterns} WHERE `file` LIKE '%s'", "%$pattern_file")); $result = FALSE; $subpattern_mode = 'always';//is this right? if (!$name) { if (drush_confirm(dt("Pattern '$pattern_file' has not been imported. Do you want to import it now? "))) { $name = drush_patterns_import($pattern_file); } } if ($name) { $result = drush_patterns_enable($name, $subpattern_mode); } if (!$result) { drush_set_error(dt("Failed to run pattern '$name' from pattern file '$pattern_file'")); return FALSE; } return TRUE; } /** * Imports the specified patterns file * @param string path to the patterns file * @param string optional machine readable name for the pattern you are importing * @return mixed bool|string FALSE upon failure; the name of the imported * pattern upon success */ function drush_patterns_import($pattern_file, $pattern_name='') { static $patterns_dir = NULL; drush_print(dt("Importing new pattern file '$pattern_file'")); if (!file_exists($pattern_file)) { drush_set_error(dt("File '$pattern_file' does not exist.")); return FALSE; } $form_state = array(); $form_state['values'] = array(); $pattern_path_info = pathinfo($pattern_file); $result = TRUE; $err_msg = ''; if ($pattern_path_info['extension']=='yaml') { //only do this lookup once, and only if someone passes yaml if (is_null($patterns_dir)) { $patterns_dir = drupal_get_path('module', 'patterns'); } //@todo hardcoded, make this definable require_once "$patterns_dir/spyc/spyc.php"; $Data = Spyc::YAMLLoad($pattern_file); if (!$Data) { drush_set_error(dt("Yaml pattern file '$pattern_file' is unreadable.")); $result = FALSE; } else { $xml = drush_patterns_arr_to_xml($Data, 'pattern'); } } else { //assume xml $xml = file_get_contents($pattern_file); if (!$xml) { drush_set_error(dt("XML pattern file '$pattern_file' is unreadable.")); $result = FALSE; } } if (!$result) { drush_set_error(dt("Failed to import '$pattern_file'.")); return FALSE; } $xmldoc = new DOMDocument(); $xmldoc->formatOutput = TRUE; $xmldoc->loadXML($xml); $pattern_source = $xmldoc->saveXML(); if (empty($pattern_name)) { $xpath = new DOMXpath($xmldoc); $query = 'info/title'; $entries = $xpath->query($query);//returns DOMNodeList foreach($entries as $entry) { $title = $entry->textContent; } /** * convert pattern title to machine readable identifier * would rather do this all in one go, but I can't seem to make the order * of the replacements work right. */ $pattern_name = preg_replace(array('/^_/', '/[^a-zA-Z0-9\s_]+/'), '', $title); $pattern_name = preg_replace('/\s+/', '_', $pattern_name); } $form_state['post'] = TRUE; $form_state['values']['xmlsource'] = $pattern_source; $form_state['values']['xmlname'] = $pattern_name; $return = $pattern_name; //Ok. so let's use the patterns API for executing this ad hoc form. patterns_execute_action('patterns_import_source', $form_state, array()); $errors = form_get_errors(); if ($errors) { $output = ''; while(list($field, $err) = each($errors)) { $output .= "[$field]:\t$err\n"; } drush_set_error(dt($output)); $return = FALSE; } $msgs = drupal_get_messages(); if ($msgs) { $output = ''; while(list($type, $ms) = each($msgs)) { $output .= "[$type]:\n\t". implode("\n", $ms) ."\n\n"; } drush_print(dt($output)); } //give back the name of the pattern upon success, FALSE on errors return $return; } /** * Enables the specified pattern * @param string $id pattern name or pattern id * @param string $subpattern_mode Choice of first-update, always, update, * first, never. Default is first-update. * * @todo Currently the function will barge through and run all sub-patterns by * default. will want to revisit this and perhaps implement a second parameter * to handle whether to do so or not. */ function drush_patterns_enable($id, $subpattern_mode='first-update') { drush_print(dt("Enabling pattern '$id'")); $pattern = patterns_get_pattern($id); if (!$pattern) { drush_set_error(dt("Cannot enable pattern '$id' as it could not be found in the list of registered patterns. Did you import it first?")); return FALSE; } /** defaulting to batch mode & always running subpatterns * run-subpatterns choices are: 'first-update' => t('only if disabled or if updated since last run (recommended)'), 'always' => t('always'), 'update' => t('only if updated since last run'), 'first' => t('only if disabled'), 'never' => t("don't run sub-patterns at all"), @todo make these constants define() statements in patterns.module */ $result = patterns_execute_pattern($pattern, array('run-subpatterns'=>$subpattern_mode, 'pid'=>$pattern->pid, 'confirm'=>1, 'op'=>'Confirm', 'submit'=>'Confirm')); if (!$result) { drush_set_error(dt("Enabling pattern '$pattern->pid:$pattern->name' failed")); return FALSE; } drush_print(dt("Success! Enabled pattern '$pattern->pid:$pattern->name'")); return TRUE; } /** * patterns list command callback. */ function drush_patterns_list() { $patterns = patterns_get_patterns(); $pipe = array(); $rows[] = array(dt('Id'), dt('Name'), dt('Title'), dt('Status'), dt('Version')); foreach($patterns as $pid => $pattern) { $rows[] = array($pattern->pid, $pattern->name, $pattern->title, $pattern->status, $pattern->info['version']); $pipe[] = "$pattern->title"; } drush_print_table($rows, TRUE); drush_print_pipe(implode(' ', $pipe)); } /** * patterns list command callback. * @param mixed int|string $id The pattern id or name of the pattern */ function drush_patterns_info($id) { $pattern = patterns_get_pattern($id); if (!$pattern) { drush_set_error(dt("There is no pattern registered with id or name '$id'")); return FALSE; } $info = ""; $info .= sprintf(" %-18s: %s\n", 'PID', $pattern->pid); $info .= sprintf(" %-18s: %s\n", 'Name', $pattern->name); $info .= sprintf(" %-18s: %s\n", 'File', $pattern->file); $info .= sprintf(" %-18s: %s\n", 'Status', $pattern->status); $info .= sprintf(" %-18s: %s\n", 'Public', $pattern->public); $info .= sprintf(" %-18s: %s\n", 'Updated', $pattern->updated); $info .= sprintf(" %-18s: %s\n", 'Enabled', $pattern->enabled); if (is_array($pattern->pattern['info'])) { foreach ($pattern->pattern['info'] as $key => $value) { $info .= sprintf(" %-18s: %s\n", ucfirst($key), $value); } } if (is_array($pattern->pattern['modules'])) $info .= sprintf(" %-18s: %s\n", 'Modules', implode(', ', $pattern->pattern['modules'])); drush_print($info); } /** * Spit and tape version of an an array to xml converter specifically for yaml * to xml pattern conversion */ function drush_patterns_arr_to_xml($data, $rootNodeName = 'root', $xml = NULL) { static $i = 0; $i++; if ($xml == null) { switch($rootNodeName) { case 'pattern': $encoding = 'ISO-8859-1'; break; default: $encoding = 'utf-8'; break; } $xml = simplexml_load_string("<$rootNodeName />"); } // loop through the data passed in. foreach($data as $key => $value) { // no numeric keys in our xml please! $unknown = FALSE; if (is_numeric($key)) { $unknown = TRUE; if (is_array($value)) { $first_child_key = key($value); $first_child_val = current($value); if ($first_child_key=='tag') { $key = $first_child_val; array_shift($value);//get rid of it. $unknown = FALSE; } } } // replace anything not alpha numeric $key = preg_replace('/[^a-z_]/i', '', $key); if ($unknown) { // make string key... $key = "unknownNode_". (string) $key; } // if there is another array found recursively call this function if (is_array($value)) { $node = $xml->addChild($key); //exception for modules listing if ($key=='modules') { //error_log("$i: we are where we want to be: ". current($value)); reset($value); while(list($key, $val) = each($value)) { //error_log("adding module $val as child"); $node->addChild('module', $val); } } else { // recursive call. drush_patterns_arr_to_xml($value, $rootNodeName, $node); } } else { // add single node. $xml->addChild($key, $value); } } // pass back as string. or simple xml object if you want! return $xml->asXML(); } //NOT CLEANED UP YET /** * patterns list command callback. */ function drush_patterns_patterns_form_helper($action) { if ($action=='enable') { variable_set('patterns_form_helper', TRUE); } else { variable_set('patterns_form_helper', FALSE); } } /** * patterns list command callback. */ function drush_patterns_patterns_allow_publish($action) { if ($action == 'enable') variable_set('patterns_allow_publish', TRUE); else variable_set('patterns_allow_publish', FALSE); } /** * patterns list command callback. */ function drush_patterns_patterns_paths() { $paths = patterns_paths(); drush_print("Paths to look for patterns:"); foreach ($paths as $path) drush_print("- $path", 4); drush_print_pipe(implode(', ', $paths)); } /** * patterns publish command callback. */ function drush_patterns_patterns_publish($pid) { if (is_numeric($pid)) { $result = db_query("UPDATE {patterns} SET public = 1 WHERE pid = %d", $pid); } } /** * patterns unpublish command callback. */ function drush_patterns_patterns_unpublish($pid) { if (is_numeric($pid)) { $result = db_query("UPDATE {patterns} SET public = 0 WHERE pid = %d", $pid); } } /** * patterns import command callback. */ function drush_patterns_patterns_import($uri) { drush_print(dt('Not implemented yet')); }