<?php

/**
 * @file
 * Admin page callbacks for the system module.
 */

use Drupal\Component\Utility\Html;
use Drupal\Core\Render\Element;
use Drupal\Core\Template\Attribute;

/**
 * Prepares variables for administrative content block templates.
 *
 * Default template: admin-block-content.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - content: An array containing information about the block. Each element
 *     of the array represents an administrative menu item, and must at least
 *     contain the keys 'title', 'link_path', and 'localized_options', which are
 *     passed to l(). A 'description' key may also be provided.
 */
function template_preprocess_admin_block_content(&$variables) {
  if (!empty($variables['content'])) {
    $variables['compact'] = system_admin_compact_mode();
    foreach ($variables['content'] as $key => $item) {
      $variables['content'][$key]['link'] = \Drupal::l($item['title'], $item['url']);
      if (!$variables['compact'] && isset($item['description'])) {
        $variables['content'][$key]['description'] = ['#markup' => $item['description']];
      }
      else {
        $variables['content'][$key]['description'] = FALSE;
      }
    }
  }
}

/**
 * Prepares variables for administrative index page templates.
 *
 * Default template: admin-page.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - blocks: An array of blocks to display. Each array should include a
 *     'title', a 'description', a formatted 'content' and a 'position' which
 *     will control which container it will be in. This is usually 'left' or
 *     'right'.
 */
function template_preprocess_admin_page(&$variables) {
  $variables['system_compact_link'] = array(
    '#type' => 'system_compact_link',
  );
  $variables['containers'] = array();
  $stripe = 0;
  foreach ($variables['blocks'] as $block) {
    if (!empty($block['content']['#content'])) {
      if (empty($block['position'])) {
        // Perform automatic striping.
        $block['position'] = ++$stripe % 2 ? 'left' : 'right';
      }
      $variables['containers'][$block['position']]['blocks'][] = array(
        '#theme' => 'admin_block',
        '#block' => $block,
      );
    }
  }
}

/**
 * Prepares variables for admin index templates.
 *
 * Default template: system-admin-index.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - menu_items: An array of modules to be displayed.
 */
function template_preprocess_system_admin_index(&$variables) {
  $variables['system_compact_link'] = array(
    '#type' => 'system_compact_link',
  );
  $variables['containers'] = array();
  $stripe = 0;
  // Iterate over all modules.
  foreach ($variables['menu_items'] as $module => $block) {
    list($description, $items) = $block;
    $position = ++$stripe % 2 ? 'left' : 'right';
    // Output links.
    if (count($items)) {
      $variables['containers'][$position][] = array(
        '#theme' => 'admin_block',
        '#block' => array(
          'position' => $position,
          'title' => $module,
          'content' => array(
            '#theme' => 'admin_block_content',
            '#content' => $items,
          ),
          'description' => t($description),
        ),
      );
    }
  }
}

/**
 * Prepares variables for status report template.
 *
 * Default template: status-report.html.twig.
 *
 * This theme function is dependent on install.inc being loaded, because
 * that's where the constants are defined.
 *
 * @param $variables
 *   An associative array containing:
 *   - requirements: An array of requirements/status items. Each requirement
 *     is an associative array containing the following elements:
 *     - title: The name of the requirement.
 *     - value: (optional) The current value (version, time, level, etc).
 *     - description: (optional) The description of the requirement.
 *     - severity: (optional) The requirement's result/severity level, one of:
 *       - REQUIREMENT_INFO: Status information.
 *       - REQUIREMENT_OK: The requirement is satisfied.
 *       - REQUIREMENT_WARNING: The requirement failed with a warning.
 *       - REQUIREMENT_ERROR: The requirement failed with an error.
 */
function template_preprocess_status_report(&$variables) {
  $severities = array(
    REQUIREMENT_INFO => array(
      'title' => t('Info'),
      'status' => 'info',
    ),
    REQUIREMENT_OK => array(
      'title' => t('OK'),
      'status' => 'ok',
    ),
    REQUIREMENT_WARNING => array(
      'title' => t('Warning'),
      'status' => 'warning',
    ),
    REQUIREMENT_ERROR => array(
      'title' => t('Error'),
      'status' => 'error',
    ),
  );

  foreach ($variables['requirements'] as $i => $requirement) {
    // Always use the explicit requirement severity, if defined. Otherwise,
    // default to REQUIREMENT_OK in the installer to visually confirm that
    // installation requirements are met. And default to REQUIREMENT_INFO to
    // denote neutral information without special visualization.
    if (isset($requirement['severity'])) {
      $severity = $severities[(int) $requirement['severity']];
    }
    elseif (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install') {
      $severity = $severities[REQUIREMENT_OK];
    }
    else {
      $severity = $severities[REQUIREMENT_INFO];
    }
    $variables['requirements'][$i]['severity_title'] = $severity['title'];
    $variables['requirements'][$i]['severity_status'] = $severity['status'];
  }
}

/**
 * Prepares variables for the module details templates.
 *
 * Default template: system-modules-details.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - form: A render element representing the form. The main form element
 *     represents a package, and child elements of the form are individual
 *     projects. Each project (or module) is an associative array containing the
 *     following elements:
 *     - name: The name of the module.
 *     - enable: A checkbox for enabling the module.
 *     - description: A description of the module.
 *     - version: The version of the module.
 *     - links: Administration links provided by the module.
 *     - #requires: A list of modules that the project requires.
 *     - #required_by: A list of modules that require the project.
 *     - #attributes: A list of attributes for the module wrapper.
 *
 * @see \Drupal\system\Form\ModulesListForm
 */
function template_preprocess_system_modules_details(&$variables) {
  $form = $variables['form'];

  $variables['modules'] = [];
  // Iterate through all the modules, which are children of this element.
  foreach (Element::children($form) as $key) {
    // Stick the key into $module for easier access.
    $module = $form[$key];
    unset($module['enable']['#title']);
    $module['#requires'] = array_filter($module['#requires']);
    $module['#required_by'] = array_filter($module['#required_by']);
    // Add the checkbox to allow installing new modules and to show the
    // installation status of the module.
    $module['checkbox'] = $module['enable'];

    // Add the module label and expand/collapse functionality.
    $id = Html::getUniqueId('module-' . $key);
    $module['id'] = $id;
    $module['enable_id'] = $module['enable']['#id'];

    // @todo Remove early rendering and use safe_join in the Twig template once
    //   https://www.drupal.org/node/2579091 is fixed.
    $renderer = \Drupal::service('renderer');
    $machine_name_render = [
      '#prefix' => '<span dir="ltr" class="table-filter-text-source">',
      '#plain_text' => $key,
      '#suffix' => '</span>',
    ];
    $module['machine_name'] = $renderer->render($machine_name_render);

    if (!empty($module['#requires'])) {
      $requires = [
        '#theme' => 'item_list',
        '#items' => $module['#requires'],
        '#context' => ['list_style' => 'comma-list'],
      ];
      $module['requires'] = $renderer->render($requires);
    }
    if (!empty($module['#required_by'])) {
      $required_by = [
        '#theme' => 'item_list',
        '#items' => $module['#required_by'],
        '#context' => ['list_style' => 'comma-list'],
      ];
      $module['required_by'] = $renderer->render($required_by);
    }

    if (!empty($module['version'])) {
      $module['version'] = $renderer->render($module['version']);
    }

    $module['attributes'] = new Attribute($module['#attributes']);
    $variables['modules'][] = $module;
  }
}

/**
 * Prepares variables for module uninstall templates.
 *
 * Default template: system-modules-uninstall.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - form: A render element representing the form. Child elements of the form
 *     are individual modules. Each module is an associative array containing
 *     the following elements:
 *     - #module_name: The name of the module as a string.
 *     - name: The name of the module in a renderable array.
 *     - description: A description of the module.
 *     - #required_by: (optional) A list of modules that require the module.
 *     - #validation_reasons: (optional) Additional reasons why the module
 *       cannot be uninstalled.
 *     - #attributes: A list of attributes for the module wrapper.
 *
 * @ingroup themeable
 */
function template_preprocess_system_modules_uninstall(&$variables) {
  $form = $variables['form'];
  $variables['modules'] = [];

  // Iterate through all the modules, which are children of this element.
  foreach (Element::children($form['modules']) as $key) {
    $module = $form['modules'][$key];
    $module['module_name'] = $module['#module_name'];
    $module['checkbox'] = $form['uninstall'][$key];
    $module['checkbox_id'] = $form['uninstall'][$key]['#id'];

    if (!empty($module['#validation_reasons'])) {
      $module['validation_reasons'] = $module['#validation_reasons'];
      $module['reasons_count'] = count($module['validation_reasons']);
    }
    else {
      $module['reasons_count'] = 0;
    }
    if (!empty($module['#required_by'])) {
      $module['required_by'] = $module['#required_by'];
      $module['reasons_count'] = $module['reasons_count'] + 1;
    }
    $module['attributes'] = new Attribute($module['#attributes']);
    $variables['modules'][] = $module;
  }
}

/**
 * Prepares variables for appearance page templates.
 *
 * Default template: system-themes-page.html.twig.
 *
 * @param $variables
 *   An associative array containing:
 *   - theme_groups: An associative array containing groups of themes.
 *   - theme_group_titles: An associative array containing titles of themes.
 */
function template_preprocess_system_themes_page(&$variables) {
  $groups = array();
  $theme_groups = $variables['theme_groups'];
  $variables['attributes']['id'] = 'system-themes-page';

  foreach ($variables['theme_group_titles'] as $state => $title) {
    if (!count($theme_groups[$state])) {
      // Skip this group of themes if no theme is there.
      continue;
    }
    // Start new theme group.
    $theme_group = array();
    $theme_group['state'] = $state;
    $theme_group['title'] = $title;
    $theme_group['themes'] = array();
    $theme_group['attributes'] = new Attribute();

    foreach ($theme_groups[$state] as $theme) {
      $current_theme = array();

      // Screenshot depicting the theme.
      if ($theme->screenshot) {
        $current_theme['screenshot'] = array(
          '#theme' => 'image',
          '#uri' => $theme->screenshot['uri'],
          '#alt' => $theme->screenshot['alt'],
          '#title' => $theme->screenshot['title'],
          '#attributes' => $theme->screenshot['attributes'],
        );
      }
      else {
        $current_theme['screenshot'] = array(
          '#theme' => 'image',
          '#uri' => drupal_get_path('module', 'system') . '/images/no_screenshot.png',
          '#alt' => t('No screenshot'),
          '#title' => t('No screenshot'),
          '#attributes' => new Attribute(array('class' => array('no-screenshot'))),
        );
      }

      // Localize the theme description.
      $current_theme['description'] = t($theme->info['description']);

      $current_theme['attributes'] = new Attribute();
      $current_theme['name'] = $theme->info['name'];
      $current_theme['version'] = isset($theme->info['version']) ? $theme->info['version'] : '';
      $current_theme['notes'] = $theme->notes;
      $current_theme['is_default'] = $theme->is_default;
      $current_theme['is_admin'] = $theme->is_admin;

      // Make sure to provide feedback on compatibility.
      $current_theme['incompatible'] = '';
      if (!empty($theme->incompatible_core)) {
        $current_theme['incompatible'] = t("This theme is not compatible with Drupal @core_version. Check that the .info.yml file contains the correct 'core' value.", ['@core_version' => \Drupal::CORE_COMPATIBILITY]);
      }
      elseif (!empty($theme->incompatible_region)) {
        $current_theme['incompatible'] = t("This theme is missing a 'content' region.");
      }
      elseif (!empty($theme->incompatible_php)) {
        if (substr_count($theme->info['php'], '.') < 2) {
          $theme->info['php'] .= '.*';
        }
        $current_theme['incompatible'] = t('This theme requires PHP version @php_required and is incompatible with PHP version @php_version.', array('@php_required' => $theme->info['php'], '@php_version' => phpversion()));
      }
      elseif (!empty($theme->incompatible_base)) {
        $current_theme['incompatible'] = t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => $theme->info['base theme']));
      }
      elseif (!empty($theme->incompatible_engine)) {
        $current_theme['incompatible'] = t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => $theme->info['engine']));
      }

      // Build operation links.
      $current_theme['operations'] = array(
        '#theme' => 'links',
        '#links' => $theme->operations,
        '#attributes' => array(
          'class' => array('operations', 'clearfix'),
        ),
      );
      $theme_group['themes'][] = $current_theme;
    }
    $groups[] = $theme_group;
  }
  $variables['theme_groups'] = $groups;
}
