diff --git a/libraries.admin.inc b/libraries.admin.inc new file mode 100644 index 0000000..8fa920d --- /dev/null +++ b/libraries.admin.inc @@ -0,0 +1,353 @@ + $info) { + $libraries[$name] = libraries_detect($name); + } + ksort($libraries); + + foreach ($libraries as $machine_name => $library) { + $actions = array(); + + if ($library['vendor url']) { + $actions[] = l('Homepage', $library['vendor url']); + } + if ($library['download url']) { + $actions[] = l('Download', $library['download url']); + } + + switch ($library['info type']) { + case 'module': + $provider = 'Module'; + $provider_info = system_get_info('module', $library['module']); + $name = sprintf('%s (%s)', $provider_info['name'], $library['module']); + break; + + case 'theme': + // @todo: verify this. + $provider = 'Theme'; + $provider_info = system_get_info('theme', $library['theme']); + $name = sprintf('%s (%s)', $provider_info['name'], $library['theme']); + break; + + case 'info file': + $provider = 'Info file'; + $provider_info = array('name' => $library['info file']); + $name = $library['info file']; + break; + } + + $rows[] = array( + 'data' => array( + l($library['name'], 'admin/reports/libraries/' . $machine_name), + ($library['installed'] ? t('OK') : drupal_ucfirst($library['error'])), + (isset($library['version']) ? $library['version'] : ''), + $provider . '
' . $name, + implode(' | ', $actions), + ), + 'class' => ($library['installed'] ? array('ok') : array('error')), + ); + } + + $form['libraries']['list'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('There are currently no libraries installed'), + ); + + return $form; +} + +/** + * Form generation callback for the status overview for a single library. + * + * This is a form instead of a page to allow easier extending in contributed + * modules. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A keyed array containing the current state of the form. + * @param string $name + * The name of the library to return the status report for. + * + * @return array|null + * The form array for the status form or NULL if the library was not found. + * + * @todo Add some var_export($library)-style output + */ +function libraries_admin_library_status_form(array $form, array &$form_state, $library) { + drupal_set_title(t('Status report for library %library', array('%library' => $library['name'])), PASS_THROUGH); + + if (isset($library['info type'])) { + switch ($library['info type']) { + case 'module': + $provider = 'Module'; + $provider_info = system_get_info('module', $library['module']); + $name = sprintf('%s (%s)', $provider_info['name'], $library['module']); + break; + + case 'theme': + // @todo: verify this. + $provider = 'Theme'; + $provider_info = system_get_info('theme', $library['theme']); + $name = sprintf('%s (%s)', $provider_info['name'], $library['theme']); + break; + + case 'info file': + $provider = 'Info file'; + $provider_info = array('name' => $library['info file']); + $name = $library['info file']; + break; + } + } + + if ($library['installed']) { + $rows = array(); + drupal_set_message(t('The %name library is installed correctly.', array('%name' => $library['name']))); + $header = array(array('data' => '' . t('General information') . '', 'colspan' => 2, 'class' => 'table-heading', 'no_striping' => TRUE)); + + $rows[] = array('' . t('Provider') . '', sprintf('%s %s', $provider, $name)); + $rows[] = array('' . t('Name') . '', check_plain($library['name'])); + $rows[] = array('' . t('Machine name') . '', check_plain($library['machine name'])); + + if ($library['vendor url']) { + $rows[] = array('' . t('Vendor URL') . '', l($library['vendor url'], $library['vendor url'])); + } + + if ($library['download url']) { + $rows[] = array('' . t('Download URL') . '', l($library['download url'], $library['download url'])); + } + + $rows[] = array('' . t('Location') . '', $library['library path']); + $rows[] = array('' . t('Version') . '', $library['version']); + + if (!empty($library['variants'])) { + $rows[] = array('' . t('Variants') . '', implode(', ', array_keys($library['variants']))); + } + + $form['status']['overview'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + } + else { + drupal_set_message($library['error message'], 'error'); + + switch ($library['error']) { + case 'not found': + $form['status']['not_found']['instruction']['#markup'] = t('Follow these steps to install the library:'); + $items = array(); + // 1. Download the library. + // If no supported versions are specified, the latest version is + // recommended. + if (empty($library['versions'])) { + $items[] = t('Download the latest version of the library here.', array( + '@download-url' => $library['download url'], + )); + } + // Otherwise, the latest supported version is recommended. + else { + $versions = array_keys($library['versions']); + usort($versions, 'version_compare'); + $versions = array_reverse($versions); + $version = $versions[0]; + $items[] = t('Download version %version of the library here.', array( + '%version' => $version, + '@download-url' => $library['download url'], + )); + } + // 2. Unpack it. + $items[] = t('If the library is an archive, i.e. if the file ending is for example .tar.gz or .zip, unpack it.'); + // 3. Create the libraries folder. + $items[] = t('In the %library-directory directory of your Drupal installation create a %library directory.', array( + '%library-directory' => 'sites/all/libraries', + '%library' => $library['machine name'], + )); + // 4. Upload it. + // If the library has variant-independent files, give the user the + // location of an example file to check his filesystem against. + list($filepath, $file) = libraries_get_example_filepath($library); + if ($filepath !== FALSE) { + $items[] = t('Upload the whole library (which can consist of multiple directories) into the newly created %library-path directory. For example, the %file file, should be located at following filepath: %filepath', array( + '%library-path' => 'sites/all/libraries/' . $library['machine name'], + '%file' => $file, + '%filepath' => $filepath, + )); + } + else { + $items[] = t('Upload the whole library (which can consist of multiple directories) into the newly created %library-path directory.', array( + '%library-path' => 'sites/all/libraries/' . $library['machine name'], + )); + } + // 5. Reload. + $items[] = t('Reload the page. If successful, you should see status information about this library.'); + + $form['status']['not_found']['steps'] = array( + '#theme' => 'item_list', + '#items' => $items, + '#type' => 'ol' + ); + break; + + case 'not detected': + // Re-check location. + // If the library has variant-independent files, give the user the + // location of an example file to check his filesystem against. + list($filepath, $file) = libraries_get_example_filepath($library); + if ($filepath !== FALSE) { + $form['status']['not_detected']['instruction']['#markup'] = t('Check that the whole library is located at %library-path. For example, the %file file, should be located at following filepath: %filepath', array( + '%library-path' => $library['library path'], + '%file' => $file, + '%filepath' => $filepath, + )) . '
'; + } + else { + $form['status']['not_detected']['instruction']['#markup'] = t('Check that the whole library is located at %library-path.', array( + '%library-path' => $library['library path'], + )) . '
'; + } + // If the library information was provided by a module, contact the maintainer. + // @todo Add support for themes by accessing $library['info type'] + if (!empty($library['module'])) { + $form['status']['not_detected']['help']['#markup'] = t('If yes, the library information is corrupted. Contact the maintainer of the %module module with the following information:', array( + '%module' => $provider_info['name'], + )) . '
'; + } + // Otherwise contact the author of the info file. + elseif (!empty($library['info file'])) { + $form['status']['not_detected']['help']['#markup'] = t("If yes, the library's info file (%info-file) is corrupted. Contact the author of this file with the following information:", array( + '%info-file' => $library['info file'], + )) . '
'; + } + break; + + case 'not supported': + // Either download a different version of the library... + $versions = array_keys($library['versions']); + usort($versions, 'version_compare'); + $versions = array_reverse($versions); + $version = $versions[0]; + $form['status']['not_supported']['instruction']['#markup'] = t('Please install version %version of the library by following the following steps:', array( + '%version' => $version, + )); + // 1. Delete the old library. + $items[] = t('Delete the entire contents of the %library-path directory.', array( + '%library-path' => $library['library path'], + )); + // 2. Download the new library. + $items[] = t('Download version %version of the library here.', array( + '%version' => $version, + '@download-url' => $library['download url'], + )); + // 3. Unpack it. + $items[] = t('If the library is an archive, i.e. if the file ending is for example .tar.gz or .zip, unpack it.'); + // 4. Upload the new library. + // If the library has variant-independent files, give the user the + // location of an example file to check his filesystem against. + list($filepath, $file) = libraries_get_example_filepath($library); + if ($filepath !== FALSE) { + $items[] = t('Upload the new files into the %library-path directory. For example, the %file file, should be located at following filepath: %filepath', array( + '%library-path' => $library['library path'], + '%file' => $file, + '%filepath' => $filepath, + )); + } + else { + $items[] = t('Upload the new files into the %library-path directory.', array( + '%library-path' => $library['library path'], + )); + } + // 5. Reload. + $items[] = t('Reload the page. If successful, you should see status information about this library.'); + $form['status']['not_supported']['steps'] = array( + '#theme' => 'item_list', + '#items' => $items, + '#type' => 'ol', + ); + // ...or contact the maintainer of the library information. + // If the library information was provided by a module, contact the maintainer. + // @todo Add support for themes by accessing $library['info type'] + if (!empty($library['module'])) { + $form['status']['not_supported']['help']['#markup'] = t('If you are bound to the current version of the library, ask the maintainer of the %module module to provide support for version %version.', array( + // @todo Use the human-readable module name instead. + '%module' => $provider_info['name'], + '%version' => $library['version'], + )) . '
'; + } + // Otherwise contact the author of the info file. + elseif (!empty($library['info file'])) { + $form['status']['not_supported']['help']['#markup'] = t("If you are bound to the current version of the library, ask the author of this library's info file (%info-file) to provide support for version %version", array( + '%info-file' => $library['info file'], + '%version' => $library['version'], + )) . '
'; + } + break; + + case 'missing dependency': + $form['status']['missing_dependency']['instruction']['#markup'] = t('There a missing dependency in your configuration that prevent this library to work properly.') . '
'; + break; + + case 'incompatible dependency': + $form['status']['incompatible_dependency']['instruction']['#markup'] = t('There an incompatible dependency in your configuration that prevent this library to work properly.') . '
'; + break; + } + } + + return $form; +} + +/** + * Returns an example file path and file name from a library, if possible. + * + * The result of this function can help users to verify that they have uploaded + * the library to the correct location. + * + * @param array $library + * A library information array. + * + * @return array + * A list containing the example filepath and the example filename. If no + * example file was found, both entries will be FALSE. + */ +function libraries_get_example_filepath(array $library) { + $filepath = FALSE; + $file = FALSE; + foreach (array('js', 'css', 'php') as $type) { + if (!empty($library['files'][$type])) { + $files = array_keys($library['files'][$type]); + $filepath = $files[0]; + $parts = array_reverse(explode('/', $filepath)); + $file = $parts[0]; + $filepath = (!empty($library['path']) ? $library['path'] . '/' . $filepath : $filepath); + $filepath = 'sites/all/libraries/' . $library['machine name'] . '/' . $filepath; + } + } + return array($filepath, $file); +} diff --git a/libraries.module b/libraries.module index 503c001..d4f4f8e 100644 --- a/libraries.module +++ b/libraries.module @@ -33,7 +33,7 @@ function libraries_flush_caches() { * @param $base_path * Whether to prefix the resulting path with base_path(). * - * @return + * @return string * The path to the specified library or FALSE if the library wasn't found. * * @ingroup libraries @@ -67,7 +67,7 @@ function libraries_get_path($name, $base_path = FALSE) { * in both the site-wide directory and site-specific directory, only the * site-specific version will be listed. * - * @return + * @return array * A list of library directories. * * @ingroup libraries @@ -122,7 +122,7 @@ function libraries_get_libraries() { * - sites/$sitename/libraries * - any directories specified via hook_libraries_info_file_paths() * - * @return + * @return array * An array of info files, keyed by library name. The values are the paths of * the files. */ @@ -871,3 +871,37 @@ function libraries_get_version($library, $options) { } fclose($file); } + +/** + * Implements hook_help(). + */ +function libraries_help($path, $arg) { + switch ($path) { + case 'admin/reports/libraries': + return t('Click on a library for a status report or detailed installation instructions in case the library is not installed correctly.'); + } +} + +/** + * Implements hook_menu(). + */ +function libraries_menu() { + $items = array(); + $items['admin/reports/libraries'] = array( + 'title' => 'Libraries', + 'description' => 'An overview of libraries installed on this site.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('libraries_admin_overview'), + 'access arguments' => array('access site reports'), + 'file' => 'libraries.admin.inc' + ); + $items['admin/reports/libraries/%libraries'] = array( + 'title' => 'Library status report', + 'description' => 'Status overview for a single library', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('libraries_admin_library_status_form', 3), + 'access arguments' => array('access site reports'), + 'file' => 'libraries.admin.inc' + ); + return $items; +}