Skip to content

Commit

Permalink
More work on drux
Browse files Browse the repository at this point in the history
  • Loading branch information
donquixote committed Dec 5, 2013
1 parent 760f998 commit 8a8e388
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 12 deletions.
101 changes: 97 additions & 4 deletions drux.drush.inc
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
<?php

/**
* Autoload callback.
*
* @param string $class
*/
function _drux_autoload($class) {
if (1
&& 'drux_' === substr($class, 0, 5)
&& FALSE === strpos($class, '\\')
) {
require_once __DIR__ . '/lib/' . str_replace('_', '/', substr($class, 5)) . '.php';
}
}

if (!function_exists('xautoload')) {
spl_autoload_register('_drux_autoload');
}

/**
* Implements hook_drush_command().
*/
function drux_drush_command() {
$items['drux-enable-dependencies'] = array(
'description' => 'Download and enable dependencies of existing modules.',
'aliases' => array('dep-en'),
);
$items['drux-list-dependencies'] = array(
'description' => 'Download and enable dependencies of existing modules.',
'aliases' => array('dep'),
);
Expand All @@ -16,16 +37,56 @@ function drux_drush_command() {
),
'aliases' => array('obs'),
);
$items['drux-generate'] = array(
'description' => 'Generate a list of dependencies[] = .. to copy+paste into a module info file.',
'arguments' => array(
'modules' => 'List of modules to seed the dependencies.',
),
'aliases' => array('obs-gen'),
);
return $items;
}


function drush_drux_list_dependencies() {

$extinfo = new drux_ExtensionInfo();
$enabled = $extinfo->enabledKeys();
$enabled = array_combine($enabled, $enabled);
$toBeEnabled = array();
foreach ($enabled as $module) {
$dependencies = $extinfo->moduleDirectDependencies($module);
if (!is_array($dependencies)) {
continue;
}
foreach ($dependencies as $dependency_data) {
if (!$extinfo->dependencySatisfied($dependency_data)) {
$name = $dependency_data['name'];
$toBeEnabled[$name][$module] = $module;
}
}
}
if (empty($toBeEnabled)) {
drush_log(dt("All required extensions are already enabled."), 'ok');
}
else {
$rows = $extinfo->modulesTableRows(array_keys($toBeEnabled));
foreach ($toBeEnabled as $module => $requiredBy) {
$requiredByText = implode(', ', $requiredBy);
$rows[$module][] = $requiredByText;
}
array_unshift($rows, array('Extension', 'Human name', 'Type', 'Required by'));
drush_print_table($rows, TRUE);
}
}


function drush_drux_enable_dependencies() {

// xautoload should find that..
$extinfo = new drux_ExtensionInfo();
$tracker = new drux_DependencyTracker($extinfo);
$tracker->requireModules($extinfo->enabledKeys());
$tracker->requireModules($extinfo->enabledKeys(), '(currently enabled)');

while ($tracker->nModulesToDownload()) {
$continue = $tracker->reportToBeEnabled();
Expand Down Expand Up @@ -67,10 +128,36 @@ function drush_drux_find_obsolete() {
// xautoload should find that..
$extinfo = new drux_ExtensionInfo();
$tracker = new drux_DependencyTracker($extinfo);
$tracker->requireModules($args);
$tracker->requireModules($args, '(drush obs)');
$obsolete = $tracker->obsoleteModules();
if (empty($obsolete)) {
drush_log(dt("All enabled modules are direct or indirect dependencies of the modules you specified."), 'ok');
}
else {
$rows = $extinfo->modulesTableRows($obsolete);
array_unshift($rows, array('Module', 'Human name'));
drush_print_table($rows, TRUE);
}
}


function drush_drux_generate() {

$args = drux_parse_arguments(func_get_args());

// xautoload should find that..
$extinfo = new drux_ExtensionInfo();
$tracker = new drux_DependencyTracker($extinfo);
$tracker->requireModules($args, '(drush obs-gen)');
$obsolete = $tracker->obsoleteModules();
$rows = $extinfo->modulesTableRows($obsolete);
drush_print_table($rows, array('Module', 'Human name'));
if (empty($obsolete)) {
drush_log(dt("All enabled modules are direct or indirect dependencies of the modules you specified."), 'ok');
}
else {
foreach ($obsolete as $module) {
drush_print('dependencies[] = ' . $module);
}
}
}


Expand All @@ -79,8 +166,14 @@ function drush_drux_find_obsolete() {
*
* Return an array of arguments off a space and/or comma separated values. It also
* lowercase arguments and optionally convert dashes to underscores.
*
* @param string[] $args
* @param bool $dashes_to_underscores
* @param bool $lowercase
* @return string[]
*/
function drux_parse_arguments($args, $dashes_to_underscores = TRUE, $lowercase = TRUE) {
// @todo Is this really needed? The $args already is an array.
$arguments = _convert_csv_to_array($args);
foreach ($arguments as $key => $argument) {
$argument = ($dashes_to_underscores) ? strtr($argument, '-', '_') : $argument;
Expand Down
30 changes: 27 additions & 3 deletions lib/DependencyTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,36 @@

class drux_DependencyTracker {

/**
* @var drux_ExtensionInfo
*/
protected $extinfo;

protected $en = array();
protected $dl = array();
protected $visited = array();
protected $obsolete = array();

/**
* @param drux_ExtensionInfo $extensionInfo
*/
function __construct($extensionInfo) {
$this->extinfo = $extensionInfo;
$enabled = $extensionInfo->enabledKeys();
$this->obsolete = array_combine($enabled, $enabled);
$this->requireModules($extensionInfo->drupalRequiredModules());
$this->requireModules($extensionInfo->drupalRequiredModules(), '(drupal core)');
}

function requireModules($modules, $required_by = '(drupal core)') {
/**
* Require modules and recursively require their dependencies.
* If a module is not downloaded yet, the dependencies cannot be determined,
* but the module will be added to the $this->dl list.
*
* @param string[] $modules
* Module names of modules to require.
* @param string $required_by
*/
function requireModules($modules, $required_by) {
foreach ($modules as $module) {
if (!isset($this->visited[$module])) {
$this->visited[$module] = $module;
Expand All @@ -37,6 +53,10 @@ function nModulesToEnable() {
return count($this->en);
}

function modulesToEnable() {
return $this->en;
}

function obsoleteModules() {
return $this->obsolete;
}
Expand Down Expand Up @@ -159,9 +179,13 @@ function refresh() {
$this->dl = array();
$this->en = array();
$this->visited = array();
$this->requireModules($missing);
$this->requireModules($missing, '(missing)');
}

/**
* @param $module
* @param $required_by
*/
protected function _requireModule($module, $required_by) {
$status = $this->extinfo->moduleStatus($module);
if (!isset($status)) {
Expand Down
95 changes: 90 additions & 5 deletions lib/ExtensionInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
*/
class drux_ExtensionInfo {

/**
* @var stdClass[]
*/
protected $extensionInfo;

function __construct() {
Expand All @@ -18,10 +21,21 @@ function refresh() {
$this->extensionInfo = drush_get_extensions();
}

function enabledKeys() {
/**
* @param bool $include_profiles
* If TRUE, install profiles will be included in the listing.
* If FALSE, install profiles will be excluded.
*
* @return string[]
* Enabled modules.
*/
function enabledKeys($include_profiles = FALSE) {
$result = array();
foreach ($this->extensionInfo as $key => $info) {
if ($info->status) {
if (1
&& !empty($info->status)
&& ($include_profiles || '.profile' !== substr($info->filename, -8))
) {
$result[] = $key;
}
}
Expand All @@ -46,16 +60,39 @@ function modulesTableRows($modules) {
return $rows;
}

function drupalRequiredModules() {
/**
* Modules where the module info says they are required.
* This is usually only the required core modules, and the active install
* profile.
*
* @param bool $include_profiles
* If TRUE, install profiles will be included in the listing.
* If FALSE, install profiles will be excluded.
*
* @return string[]
* Required modules, such as 'system'.
*/
function drupalRequiredModules($include_profiles = FALSE) {
$result = array();
foreach ($this->extensionInfo as $module => $info) {
if (!empty($info->info['required'])) {
if (1
&& !empty($info->info['required'])
&& ($include_profiles || '.profile' !== substr($info->filename, -8))
) {
$result[$module] = $module;
}
}
return $result;
}

/**
* Get the dependencies of a given module.
*
* @param string $module
* The module name to start from.
* @return string[]|NULL
* An array of module names, or NULL if we don't have that information.
*/
function moduleDependencies($module) {
if (!isset($this->extensionInfo[$module])) {
return NULL;
Expand All @@ -64,10 +101,58 @@ function moduleDependencies($module) {
return array();
}
else {
// return $this->extensionInfo[$module]->info['dependencies'];
return array_keys($this->extensionInfo[$module]->requires);
}
}

/**
* Get the dependencies of a given module.
*
* @param string $module
* The module name to start from.
* @return string[]|NULL
* An array of module names, or NULL if we don't have that information.
*/
function moduleDirectDependencies($module) {
if (!isset($this->extensionInfo[$module])) {
return NULL;
}
$info = $this->extensionInfo[$module];
if (!isset($info->requires)) {
return array();
}
if (!is_array($info->info['dependencies'])) {
return array();
}
$deps = array();
foreach ($info->info['dependencies'] as $dependency) {
$dependency_data = drupal_parse_dependency($dependency);
$deps[] = $dependency_data;
}
return $deps;
}

/**
* Check if the module required in $dependency_data is enabled and has the
* correct version.
*
* @param array $dependency_data
*
* @return bool
*/
function dependencySatisfied($dependency_data) {
$name = $dependency_data['name'];
if (!isset($this->extensionInfo[$name])) {
return FALSE;
}
$info = $this->extensionInfo[$name];
if (empty($info->status)) {
return FALSE;
}
return TRUE;
}

function moduleRequiredBy($module) {
if (!isset($this->extensionInfo[$module])) {
return NULL;
Expand Down Expand Up @@ -113,7 +198,7 @@ function downloadProjects($projects) {

function enableExtensions($modules) {
drush_module_enable($modules);
drush_system_modules_form_submit(pm_module_list());
// drush_system_modules_form_submit(pm_module_list());
$this->refresh();
$result = array(array(), array());
foreach ($modules as $module) {
Expand Down

0 comments on commit 8a8e388

Please sign in to comment.