composer_manager.module in Composer Manager 7
Same filename and directory in other branches
Provides consolidated management of third-party Composer-compatible packages required by contributed modules.
File
composer_manager.moduleView source
<?php
/**
* @file
* Provides consolidated management of third-party Composer-compatible packages
* required by contributed modules.
*/
/**
* Implements hook_boot().
*/
function composer_manager_boot() {
try {
composer_manager_register_autoloader();
} catch (\RuntimeException $e) {
if (!drupal_is_cli()) {
watchdog_exception('composer_manager', $e);
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function composer_manager_module_implements_alter(&$implementations, $hook) {
// We want to place composer_manager first for boot to ensure that the
// autoloader is registered before other modules.
if ($hook == 'boot' && isset($implementations['composer_manager'])) {
$impl = $implementations['composer_manager'];
unset($implementations['composer_manager']);
$implementations = array(
'composer_manager' => $impl,
) + $implementations;
}
}
/**
* Implements hook_menu().
*/
function composer_manager_menu() {
$items = array();
$items['admin/config/system/composer-manager'] = array(
'title' => 'Composer Manager',
'description' => 'View the status of packages managed by Composer and configure the location of the composer.json file and verdor directory.',
'page callback' => 'composer_manager_packages_page',
'access arguments' => array(
'administer site configuration',
),
'file' => 'composer_manager.admin.inc',
);
$items['admin/config/system/composer-manager/packages'] = array(
'title' => 'Packages',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/config/system/composer-manager/settings'] = array(
'title' => 'Settings',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'composer_manager_settings_form',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'composer_manager.admin.inc',
'type' => MENU_LOCAL_TASK,
);
return $items;
}
/**
* Implements hook_modules_enabled().
*
* @see composer_manager_write_if_changed()
*/
function composer_manager_modules_enabled($modules) {
composer_manager_write_if_changed($modules);
}
/**
* Implements hook_modules_disabled().
*
* @see composer_manager_write_if_changed()
*/
function composer_manager_modules_disabled($modules) {
composer_manager_write_if_changed($modules);
}
/**
* Writes the composer.json file if one of the enabled / disabled modules
* has a composer.json file.
*
* This is a primitive check to ensure that the composer.json file is built only
* when it has changes. A static boolean is also set flagging whether one or
* more modules being acted on contains a composer.json file, which is used in
* Drush hooks.
*
* @param array $modules
* The enabled / disabled modules being scanned for a composer.json file.
*/
function composer_manager_write_if_changed(array $modules) {
$changed =& drupal_static(__FUNCTION__, FALSE);
if (variable_get('composer_manager_autobuild_file', 1)) {
if (composer_manager_packages_have_changed($modules)) {
$changed = TRUE;
composer_manager_write_file();
}
}
}
/**
* Returns TRUE if at least one passed modules has a composer.json file or
* implements hook_composer_json_alter(). These conditions indicate that the
* consolidated composer.json file has likely changed.
*
* @param array $modules
* The list of modules being scanned for composer.json files, usually a list
* of modules that were installed or uninstalled.
*
* @return bool
*/
function composer_manager_packages_have_changed(array $modules) {
foreach ($modules as $module) {
// Check if the module has a composer.json file.
$module_path = drupal_get_path('module', $module);
if (file_exists($module_path . '/composer.json')) {
return TRUE;
}
// Check if the module implements hook_composer_json_alter().
if (module_hook($module, 'composer_json_alter')) {
return TRUE;
}
}
return FALSE;
}
/**
* Returns TRUE if at least one module has a composer.json file.
*
* @param array $modules
* An array of modules being checked.
*
* @return boolean
*
* @deprecated since 7.x-1.6 https://www.drupal.org/node/2297413
*
* @see composer_manager_packages_have_changed()
*/
function composer_manager_has_composer_file(array $modules) {
foreach ($modules as $module) {
$module_path = drupal_get_path('module', $module);
if (file_exists($module_path . '/composer.json')) {
return TRUE;
}
}
return FALSE;
}
/**
* Registers the autoloader for all third-party packages.
*
* @return \Composer\Autoload\ClassLoader()
* The ClassLoader instance.
*/
function composer_manager_register_autoloader() {
static $registered = FALSE;
$autoloader = composer_manager_vendor_dir() . '/autoload.php';
if (!$registered) {
if (!file_exists($autoloader)) {
$message = t('Autoloader not found: @file', array(
'@file' => $autoloader,
));
throw new \RuntimeException($message);
}
$registered = TRUE;
}
return require $autoloader;
}
/**
* Writes the consolidated composer.json file for all modules that require
* third-party packages managed by Composer.
*
* @return bool
*/
function composer_manager_write_file() {
// Ensure only one process runs at a time. 10 seconds is more than enough.
// It is rare that a conflict will happen, and it isn't mission critical that
// we wait for the lock to release and regenerate the file again.
if (!lock_acquire(__FUNCTION__, 10)) {
return FALSE;
}
require_once __DIR__ . '/composer_manager.writer.inc';
try {
$data = composer_manager_fetch_data();
$json = composer_manager_build_json($data);
if ($json) {
$dir_uri = composer_manager_file_dir();
composer_manager_put_file($dir_uri, $json);
}
$success = TRUE;
} catch (\RuntimeException $e) {
$success = FALSE;
if (user_access('administer site configuration')) {
drupal_set_message(t('Error writing composer.json file'), 'error');
}
watchdog_exception('composer_manager', $e);
}
lock_release(__FUNCTION__);
return $success;
}
/**
* Returns the path to the vendor directory.
*
* @return string
*/
function composer_manager_vendor_dir() {
// Don't break sites that upgraded from <= 7.x-1.0-beta5.
composer_manager_beta5_compatibility();
$vendor_dir = variable_get('composer_manager_vendor_dir', 'sites/all/vendor');
$is_absolute = 0 === strpos($vendor_dir, '/');
if (!$is_absolute) {
$vendor_dir = DRUPAL_ROOT . '/' . $vendor_dir;
}
return $vendor_dir;
}
/**
* Ensures that sites don't break after upgrading from <= 7.x-1.0-beta5.
*
* In versions <= 7.x-1.0-beta5, the default vendor directory was defined as
* "sites/all/libraries/composer'". In versions > 7.x-1.0-beta5, the default
* vendor directory is "sites/all/vendor". This check ensures that the vendor
* directory doesn't unexpectedly change for people who upgraded the module from
* an earlier version and haven't changed any of the default settings.
*
* Composer Manager explicitly sets the "composer_manager_vendor_dir" to
* "sites/all/vendor" during installation, so we know that the module was
* upgraded if the variable isn't set.
*/
function composer_manager_beta5_compatibility() {
if (NULL === ($default = variable_get('composer_manager_vendor_dir', NULL))) {
// Set the variable to the old default so it doesn't change unexpectedly.
variable_set('composer_manager_vendor_dir', 'sites/all/libraries/composer');
}
}
/**
* Return the URI to the composer.lock file.
*
* @return string|bool
* The URI to the composer.lock file, usually in public://. Returns FALSE if
* the lock file cannot be read.
*/
function composer_manager_lock_file() {
$dir_uri = composer_manager_file_dir();
$lock_file = $dir_uri . '/composer.lock';
// Make sure we can read composer.lock and it's valid.
if (file_exists($lock_file) && is_readable($lock_file)) {
$json = file_get_contents($lock_file);
$decoded = drupal_json_decode($json);
if (!is_array($decoded)) {
return FALSE;
}
}
else {
return FALSE;
}
return $lock_file;
}
/**
* Returns the realpath to the Composer file directory.
*
* @return string
*
* @throws \RuntimeException
*/
function composer_manager_file_dir() {
module_load_include('inc', 'composer_manager', 'composer_manager.writer');
$scheme = file_default_scheme();
// Composer can only be run on a locally mounted file system. If the scheme is
// set to something different like S3, we fall back to the public scheme.
if (!in_array($scheme, array(
'public',
'private',
))) {
$scheme = 'public';
}
$dir_uri = variable_get('composer_manager_file_dir', $scheme . '://composer');
composer_manager_prepare_directory($dir_uri);
if (!($realpath = drupal_realpath($dir_uri))) {
throw new \RuntimeException(t('Error resolving directory: @dir', array(
'@dir' => $dir_uri,
)));
}
return $realpath;
}
Functions
Name | Description |
---|---|
composer_manager_beta5_compatibility | Ensures that sites don't break after upgrading from <= 7.x-1.0-beta5. |
composer_manager_boot | Implements hook_boot(). |
composer_manager_file_dir | Returns the realpath to the Composer file directory. |
composer_manager_has_composer_file Deprecated | Returns TRUE if at least one module has a composer.json file. |
composer_manager_lock_file | Return the URI to the composer.lock file. |
composer_manager_menu | Implements hook_menu(). |
composer_manager_modules_disabled | Implements hook_modules_disabled(). |
composer_manager_modules_enabled | Implements hook_modules_enabled(). |
composer_manager_module_implements_alter | Implements hook_module_implements_alter(). |
composer_manager_packages_have_changed | Returns TRUE if at least one passed modules has a composer.json file or implements hook_composer_json_alter(). These conditions indicate that the consolidated composer.json file has likely changed. |
composer_manager_register_autoloader | Registers the autoloader for all third-party packages. |
composer_manager_vendor_dir | Returns the path to the vendor directory. |
composer_manager_write_file | Writes the consolidated composer.json file for all modules that require third-party packages managed by Composer. |
composer_manager_write_if_changed | Writes the composer.json file if one of the enabled / disabled modules has a composer.json file. |