You are here

jqp.admin.inc in jQuery Plugin Handler (JQP) 6.2

This file includes all functionality for the libraries configuration pages

File

jqp.admin.inc
View source
<?php

/**
 * @file
 *
 * This file includes all functionality for the libraries configuration pages
 */

/**
 * Page callback for admin/build/jqp.
 *
 * Lists all installed javascript libraries.
 */
function jqp_status_page() {
  $js_libraries = jqp_rebuild_cache();
  if (!empty($js_libraries)) {

    // Set the table header.
    $header = array(
      t('Name'),
      t('Description'),
      t('Versions'),
      t('Operations'),
      t('Status'),
    );
    foreach ($js_libraries as $name => $library) {

      // Reset the status class to 'ok'.
      $status = 'ok';

      // Reset all arrays.
      $versions = $links = $warnings = array();

      // Get all versions and check wheter all files exists
      foreach (array(
        'scripts',
        'stylesheets',
      ) as $type) {

        // Proceed only if there are files added to this type
        if (!empty($library->info[$type])) {
          foreach ($library->info[$type] as $v => $files) {
            unset($files['changed']);
            $versions[$v] = $v == 0 ? 'default' : $v;
            $links[$v] = l(t('configure'), "admin/build/jqp/{$name}/{$v}");

            // Check if all files for this version exist
            foreach ($files as $file) {
              if (!file_exists($file)) {

                // The file does not exist.
                // Set the status of this version to 'warning' and stop checking.
                $warnings[$v] = TRUE;
                $status = 'warning';
                continue;
              }
            }
          }
        }
      }

      // Reset the $first which is used to check if we're in the first tr of a library
      $first = TRUE;
      foreach (array_keys($versions) as $v) {
        $library_name = '';
        if ($first) {
          if ($library->info['project_url']) {
            $library_name = l($library->info['name'], $library->info['project_url'], array(
              'attributes' => array(
                'title' => t('Click here to go to %library\'s project page.', array(
                  '%library' => $library->info['name'],
                )),
              ),
            ));
          }
          else {
            $library_name = $library->info['name'];
          }
        }

        // Create the unique table row
        $rows[$name . $v] = array(
          'data' => array(
            $library_name ? "<strong>{$library_name}</strong>" : '',
            $first ? $library->info['description'] : '',
            $versions[$v],
            $links[$v],
            theme('image', "misc/watchdog-" . ($warnings[$v] ? 'warning' : 'ok') . ".png"),
          ),
          'class' => ($first ? 'first ' : '') . $status,
        );

        // The first table row for this library is created.
        // Set $first to FALSE for reference.
        $first = FALSE;
      }
      $rows[$name . $v]['class'] .= ' last';
    }

    // Add a bit of custom css to overwrite the default 'odd' and 'even' behaviour.
    drupal_add_css(drupal_get_path('module', 'jqp') . '/jqp.admin.css');

    // Create the table
    $output = theme('table', $header, $rows, array(
      'class' => 'js_libraries_table multirow',
    ));
  }
  else {

    // Nothing to show.
    $output = "<p>" . t('No javascript libraries installed yet!') . "</p>";
  }
  return $output;
}

/**
 * Builds the form which is used to edit a single version of a library
 */
function js_library_edit(&$form_state, $js_library, $version = 0, $op = NULL) {
  $types = array(
    'scripts',
    'stylesheets',
  );

  // Used to create an array for form fields which needs to be rendered by the theme function
  $form['files'] = array(
    '#type' => 'value',
    "#value" => array(),
  );
  $index = 0;
  $form['js_library'] = array(
    '#type' => 'value',
    "#value" => $js_library,
  );
  $form['version'] = array(
    '#type' => 'value',
    "#value" => $version,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );

  // If operation is 'add' we want to display empty fields.
  // We overwrite $js_library with an empty placeholder.
  if ($op == 'add') {
    $form['add'] = array(
      '#type' => 'value',
      '#value' => TRUE,
    );
    _jqp_form_elements($form, $index, array(
      'version' => $version,
    ));
    return $form;
  }
  foreach ($types as $type) {
    if (!empty($js_library->info[$type][$version])) {
      $added_types[] = $type;
      foreach ($js_library->info[$type][$version] as $key => $path) {
        if ($key !== 'changed') {
          $values = array(
            'name' => $key,
            'path' => $path,
            'version' => $version,
            'type' => $type,
            'operations' => array(
              l(t('remove'), "admin/build/jqp/{$js_library->name}/{$version}/remove_file", array(
                'query' => "type={$type}&file=" . urlencode($key),
              )),
            ),
          );
          _jqp_form_elements($form, $index, $values);
          $index++;
        }
      }
    }
  }

  // If this is not the default version (0), and there are files types available which aren't added yet,
  // we add it here and disable it.
  if ($version !== 0) {
    foreach ($types as $type) {
      if (!in_array($type, $added_types) && isset($js_library->info[$type][0])) {
        foreach ($js_library->info[$type][0] as $key => $path) {
          if ($key !== 'changed') {
            _jqp_form_elements($form, -$index, array(
              'name' => $key,
              'path' => $path,
              'version' => 0,
            ));
            $index++;
          }
        }
      }
    }
  }
  $form['reset'] = array(
    '#type' => 'submit',
    '#value' => t('Reset'),
  );
  return $form;
}

/**
 * Helper function for dynamically creating the form elements required by a single file.
 */
function _jqp_form_elements(&$form, $index, $values = array()) {
  $form["file-{$index}-name"] = array(
    '#title' => t('Name'),
    '#type' => 'textfield',
    '#default_value' => $values['name'],
    '#size' => 10,
    '#required' => !($index < 0),
    '#disabled' => $index < 0,
  );
  $form["file-{$index}-path"] = array(
    '#title' => t('Path'),
    '#type' => 'textfield',
    '#size' => FALSE,
    '#default_value' => $values['path'],
    '#autocomplete_path' => 'jqp_autocomplete',
    '#required' => !($index < 0),
    '#disabled' => $index < 0,
  );
  $form["file-{$index}-type"] = array(
    '#title' => t('Type'),
    '#type' => 'select',
    '#default_value' => $values['type'],
    '#options' => array(
      'scripts' => t('Javascript'),
      'stylesheets' => t('Stylesheet'),
    ),
    '#required' => !($index < 0),
    '#disabled' => $index < 0,
  );
  $form["file-{$index}-operations"] = array(
    '#value' => !empty($values['operations']) ? join($values['operations']) : '',
  );
  $form["file-{$index}-status"] = array(
    '#type' => 'value',
    '#value' => file_exists($values['path']),
  );
  $form["file-{$index}-version"] = array(
    '#type' => 'value',
    '#value' => $values['version'],
  );
  $form['files']['#value'][$index] = $values['name'];
}

/**
 * Submit handler for js_library_edit().
 */
function js_library_edit_submit($form, &$form_state) {
  $js_library = $form_state['values']["js_library"];
  $version = $form_state['values']["version"];
  if ($form_state['values']['op'] == t('Reset')) {
    $form_state['redirect'] = "admin/build/jqp/{$js_library->name}/{$version}/reset";
    return;
  }
  foreach (array_keys($form_state['values']['files']) as $index) {
    if ($index >= 0) {
      $name = $form_state['values']["file-{$index}-name"];
      $path = $form_state['values']["file-{$index}-path"];
      $type = $form_state['values']["file-{$index}-type"];
      $js_library->info[$type][$version][$name] = $path;
      $js_library->info[$type][$version]['changed'] = TRUE;
    }
  }
  db_query("UPDATE {system} SET info = '%s' WHERE type = '%s' AND name = '%s'", serialize($js_library->info), 'javascript library', $js_library->name);
  drupal_set_message(t('The configuration options have been saved!'));
  $form_state['redirect'] = "admin/build/jqp";
  if ($form_state['values']['add']) {
    $form_state['redirect'] .= "/{$js_library->name}/{$version}";
  }
}

/**
 * Theme function for the js_library_edit form.
 * Creates a table in which each tr contans all form elements for a single file.
 */
function theme_js_library_edit($form) {
  if (!empty($form['files']['#value'])) {

    // Set the table header.
    $header = array(
      t('Filename'),
      t('Path'),
      t('Type'),
      t('Version'),
      t('Operations'),
      t('Status'),
    );
    ksort($form['files']['#value']);
    foreach ($form['files']['#value'] as $index => $file) {
      $version = $form["file-{$index}-version"]['#value'];
      if ($new = $form['add']['#value']) {
        unset($form["file-{$index}-name"]['#title']);
      }
      else {
        $form["file-{$index}-name"]['#type'] = 'hidden';
        $name = $form["file-{$index}-name"]['#value'];
        $form["file-{$index}-type"]['#type'] = 'hidden';
        $type = $form["file-{$index}-type"]['#value'];
      }
      unset($form["file-{$index}-path"]['#title'], $form["file-{$index}-type"]['#title']);
      if ($form['version']['#value'] !== $version) {
        $version = l($version == 0 ? t('default') : $version, "admin/build/jqp/" . $form['js_library']['#value']->name . "/{$version}");
      }
      else {
        $version = $version == 0 ? t('default') : $version;
      }
      $status = $form["file-{$index}-status"]['#value'] ? 'ok' : 'warning';
      $rows[] = array(
        'data' => array(
          $new ? drupal_render($form["file-{$index}-name"]) : $name,
          drupal_render($form["file-{$index}-path"]),
          $new ? drupal_render($form["file-{$index}-type"]) : $form["file-{$index}-type"]['#options'][$type],
          $version,
          drupal_render($form["file-{$index}-operations"]),
          theme('image', "misc/watchdog-{$status}.png", $status, $status, NULL, FALSE),
        ),
        'class' => $status,
      );
    }
    $path = drupal_get_path('module', 'jqp');
    drupal_add_css("{$path}/jqp.admin.css");
    drupal_add_js("{$path}/jqp.admin.js");
    drupal_add_js(array(
      'jqp_module_path' => $path,
    ), 'setting');
    return theme('table', $header, $rows, array(
      'class' => 'js_libraries_table',
    )) . drupal_render($form);
  }
}

/**
 * Wrapper function for all actions which needs confirmation before execution.
 */
function jqp_confirm_form(&$form_state, $js_library = NULL, $version = 0) {
  $form['js_library'] = array(
    '#type' => 'value',
    '#value' => $js_library,
  );
  $form['version'] = array(
    '#type' => 'value',
    '#value' => $version,
  );
  $form['file'] = array(
    '#type' => 'value',
    '#value' => $_GET['file'],
  );
  $form['type'] = array(
    '#type' => 'value',
    '#value' => $_GET['type'],
  );
  if (isset($js_library, $version, $_GET['file'], $_GET['type'])) {
    return confirm_form($form, t('Are you sure you want to remove the file %item from %library', array(
      '%item' => $_GET['file'],
      '%library' => $js_library->info['name'],
    )), "admin/build/jqp/{$js_library->name}/{$version}", t('Removal of this file only applies to version !version of this library.', array(
      '!version' => $version,
    )), t('Remove'));
  }
  elseif (isset($js_library, $version)) {
    return confirm_form($form, t('Are you sure you want to reset the item %item to its default values?', array(
      '%item' => $js_library->info['name'],
    )), "admin/build/jqp/{$js_library->name}/{$version}", t('Any customizations will be lost. This action cannot be undone.'), t('Reset'));
  }
  elseif (arg(3) == 'rebuild_confirm') {
    $form = array(
      'reset_all' => array(
        '#type' => 'value',
        '#value' => TRUE,
      ),
    );
    return confirm_form($form, t('Are you sure you want to completely rebuild all javascript libraries?'), "admin/build/jqp", t('Any customizations will be lost. This action cannot be undone.'), t('Reset'));
  }
  else {
    drupal_goto('admin/build/jqp');
  }
}

/**
 * Submit handler for jqp_confirm_form().
 */
function jqp_confirm_form_submit($form, &$form_state) {
  $js_library = $form_state['values']["js_library"];
  $version = $form_state['values']["version"];
  $file = $form_state['values']["file"];
  $type = $form_state['values']["type"];
  $op = $form_state['values']['op'];
  $reset_all = $form_state['values']['reset_all'];
  $form_state['redirect'] = "admin/build/jqp";
  switch ($op) {
    case t('Remove'):
      unset($js_library->info[$type][$version][$file]);
      $message = t('The file has been unattached.');
      break;
    case t('Reset'):
      if (!$reset_all) {
        foreach (array(
          'scripts',
          'stylesheets',
        ) as $type) {
          if (is_array($js_library->info[$type])) {
            foreach (array_keys($js_library->info[$type]) as $key) {
              unset($js_library->info[$type][$key]['changed']);
            }
          }
        }
        $message = t('The javascript library has been reset to its default settings!');
      }
      break;
  }
  if ($reset_all) {
    $message = t('All javascript libraries has been reset to their default settings!');
  }
  else {
    db_query("UPDATE {system} SET info = '%s' WHERE filename = '%s'", serialize($js_library->info), $js_library->filename);
    $form_state['redirect'] .= "/{$js_library->name}/{$version}";
  }
  if ($op == t('Reset')) {
    jqp_rebuild_cache($reset_all);
  }
  drupal_set_message($message);
}

/**
 * AJAX callback function for Drupal.behaviors.libraryCheckInput().
 *
 * Validates the path suggested in the input form field from js_library_edit().
 *
 * @see jqp.admin.js
 * @see js_library_edit()
 */
function _jqp_ajax_check_file() {
  $p = (object) $_POST;
  if (isset($p->path) && user_access('administer javascript libraries')) {
    $result['result'] = isset($p->path) && file_exists($p->path) && is_file($p->path);
    if ($result['result'] && isset($p->type)) {
      $type = $p->type == t('Javascript') ? '.js' : ($p->type == t('Stylesheet') ? '.css' : FALSE);
      if ($type) {
        $result['result'] = strrpos($p->path, "{$type}") == drupal_strlen($p->path) - drupal_strlen($type);
      }
    }
    print drupal_to_js($result);
  }
}

/**
 * AJAX response function for #autocomplete form elements.
 *
 * Returns all .css and .js file paths matching the search string.
 */
function _jqp_autocomplete() {
  $matches = array();
  $args = func_get_args();
  if (!empty($args)) {
    $string = join('/', $args);
    foreach (jqp_scan_dir() as $file) {
      if (strstr($file->filename, $string)) {
        $matches[$file->filename] = $file->filename;

        // stop if the matches exceed 10 elements
        if (count($matches) >= 20) {
          break;
        }
      }
    }
  }
  drupal_json($matches);
}

Functions

Namesort descending Description
jqp_confirm_form Wrapper function for all actions which needs confirmation before execution.
jqp_confirm_form_submit Submit handler for jqp_confirm_form().
jqp_status_page Page callback for admin/build/jqp.
js_library_edit Builds the form which is used to edit a single version of a library
js_library_edit_submit Submit handler for js_library_edit().
theme_js_library_edit Theme function for the js_library_edit form. Creates a table in which each tr contans all form elements for a single file.
_jqp_ajax_check_file AJAX callback function for Drupal.behaviors.libraryCheckInput().
_jqp_autocomplete AJAX response function for #autocomplete form elements.
_jqp_form_elements Helper function for dynamically creating the form elements required by a single file.