You are here

class PotxExtractTranslationForm in Translation template extractor 8

Class PotxExtractTranslationForm.

@package Drupal\potx\Form

Hierarchy

Expanded class hierarchy of PotxExtractTranslationForm

1 string reference to 'PotxExtractTranslationForm'
potx.routing.yml in ./potx.routing.yml
potx.routing.yml

File

src/Form/PotxExtractTranslationForm.php, line 17

Namespace

Drupal\potx\Form
View source
class PotxExtractTranslationForm extends FormBase {

  /**
   * The language manager.
   *
   * @var \Drupal\language\ConfigurableLanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * The theme handler.
   *
   * @var \Drupal\Core\Extension\ThemeHandlerInterface
   */
  protected $themeHandler;

  /**
   * Constructs a new PotxExtractTranslationForm object.
   *
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
   *   The theme handler.
   */
  public function __construct(LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
    $this->languageManager = $language_manager;
    $this->moduleHandler = $module_handler;
    $this->themeHandler = $theme_handler;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('language_manager'), $container
      ->get('module_handler'), $container
      ->get('theme_handler'));
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'potx_extract_transation';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $components = $this
      ->generateComponentList();
    $this
      ->buildComponentSelector($form, $components);

    // Generate translation file for a specific language if possible.
    $languages = $this->languageManager
      ->getLanguages();
    if (count($languages) > 1 || !isset($languages['en'])) {

      // We have more languages, or the single language we have is not English.
      $options = [
        'n/a' => $this
          ->t('Language independent template'),
      ];
      foreach ($languages as $langcode => $language) {

        // Skip English, as we should not have translations for this language.
        if ($langcode == 'en') {
          continue;
        }
        $options[$langcode] = $this
          ->t('Template file for @langname translations', [
          '@langname' => $language
            ->getName(),
        ]);
      }
      $form['langcode'] = [
        '#type' => 'radios',
        '#title' => $this
          ->t('Template language'),
        '#default_value' => 'n/a',
        '#options' => $options,
        '#description' => $this
          ->t('Export a language independent or language dependent (plural forms, language team name, etc.) template.'),
      ];
      $form['translations'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Include translations'),
        '#description' => $this
          ->t('Include translations of strings in the file generated. Not applicable for language independent templates.'),
      ];
    }
    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this
        ->t('Extract'),
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if (empty($form_state
      ->getValue('component'))) {
      $form_state
        ->setErrorByName('component', $this
        ->t('You should select a component to export.'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    // This could take some time.
    @set_time_limit(0);
    $this->moduleHandler
      ->loadInclude('potx', 'inc');
    $this->moduleHandler
      ->loadInclude('potx', 'inc', 'potx.local');

    // Silence status messages.
    potx_status('set', POTX_STATUS_MESSAGE);

    // $form_state->getValue('component') either contains a specific file name
    // with path, or a directory name for a module/theme or a module suite.
    // Examples:
    // - modules/watchdog
    // - sites/all/modules/coder
    // - sites/all/modules/i18n/i18n.module
    // - themes/garland.
    $component = $form_state
      ->getValue('component');
    $pathinfo = pathinfo($component);
    if (!isset($pathinfo['filename'])) {

      // The filename key is only available in PHP 5.2.0+.
      $pathinfo['filename'] = substr($pathinfo['basename'], 0, strrpos($pathinfo['basename'], '.'));
    }
    if (isset($pathinfo['extension'])) {

      // A specific module or theme file was requested (otherwise there should
      // be no extension).
      potx_local_init($pathinfo['dirname']);
      $files = _potx_explore_dir($pathinfo['dirname'] . '/', $pathinfo['filename']);
      $strip_prefix = 1 + strlen($pathinfo['dirname']);
      $outputname = $pathinfo['filename'];
    }
    else {
      potx_local_init($component);
      $files = _potx_explore_dir($component . '/');
      $strip_prefix = 1 + strlen($component);
      $outputname = $pathinfo['basename'];
    }

    // Decide on template or translation file generation.
    $template_langcode = $translation_langcode = NULL;
    if ($form_state
      ->hasValue('langcode') && $form_state
      ->getValue('langcode') != 'n/a') {
      $template_langcode = $form_state
        ->getValue('langcode');
      $outputname .= '.' . $template_langcode;
      if (!empty($form_state
        ->getValue('translations'))) {
        $translation_langcode = $template_langcode;
        $outputname .= '.po';
      }
      else {
        $outputname .= '.pot';
      }
    }
    else {
      $outputname .= '.pot';
    }

    // Collect every string in affected files. Installer related strings are
    // discarded.
    foreach ($files as $file) {
      _potx_process_file($file, $strip_prefix);
    }
    potx_finish_processing('_potx_save_string');

    // Need to include full parameter list to get to passing the language codes.
    _potx_build_files(POTX_STRING_RUNTIME, POTX_BUILD_SINGLE, 'general', '_potx_save_string', '_potx_save_version', '_potx_get_header', $template_langcode, $translation_langcode);
    _potx_write_files($outputname, 'attachment');
    exit;
  }

  /**
   * Generate a hierarchical structured list of components.
   *
   * @return array
   *   Array in the directory structure identified.
   *    - 'normal'  keyed elements being subfolders
   *    - '#name'   elements being component objects for the 'name' component
   *    - '#-count' being the file count of all components in the directory
   */
  private function generateComponentList() {
    $components = [];

    // Get a list of all enabled modules and themes.
    $modules = $this->moduleHandler
      ->getModuleList();
    $themes = $this->themeHandler
      ->listInfo();

    /** @var \Drupal\Core\Extension\Extension[] $result */
    $result = array_merge($modules, $themes);
    foreach ($result as $component) {

      // Build directory tree structure.
      $path_parts = explode('/', $component
        ->getPath());
      $dir =& $components;
      foreach ($path_parts as $dirname) {
        if (!isset($dir[$dirname])) {
          $dir[$dirname] = [];
        }
        $dir =& $dir[$dirname];
      }

      // Information about components in this directory.
      $dir['#' . $component
        ->getExtensionFilename()] = $component;
      $dir['#-count'] = isset($dir['#-count']) ? $dir['#-count'] + 1 : 1;
    }
    return $components;
  }

  /**
   * Build a chunk of the component selection form.
   *
   * @param array $form
   *   Form to populate with fields.
   * @param array $components
   *   Structured array with components as returned by
   *   $this->generateComponentList().
   * @param string $dirname
   *   Name of directory handled.
   *
   * @return mixed
   *   A count of the number of components or void.
   */
  private function buildComponentSelector(array &$form, array &$components, $dirname = '') {

    // Pop off count of components in this directory.
    if (isset($components['#-count'])) {
      $component_count = $components['#-count'];
      unset($components['#-count']);
    }
    $dirkeys = array_keys($components);

    // A directory with one component.
    if (isset($component_count) && count($components) == 1) {
      $component = array_shift($components);
      $dirname = $component
        ->getPath();
      $form[$this
        ->getFormElementId('dir', $dirname)] = [
        '#type' => 'radio',
        '#title' => t('Extract from %name in the %directory directory', [
          '%directory' => $dirname,
          '%name' => $component
            ->getName(),
        ]),
        '#description' => t('Generates output from all files found in this directory.'),
        '#default_value' => 0,
        '#return_value' => $dirname,
        // Get all radio buttons into the same group.
        '#parents' => [
          'component',
        ],
      ];
      return;
    }

    // A directory with multiple components in it.
    if (preg_match('!/(modules|themes)\\b(/.+)?!', $dirname, $pathmatch)) {
      $t_args = [
        '@directory' => substr($dirname, 1),
      ];
      if (isset($pathmatch[2])) {
        $form[$this
          ->getFormElementId('dir', $dirname)] = [
          '#type' => 'radio',
          '#title' => t('Extract from all in directory "@directory"', $t_args),
          '#description' => t('To extract from a single component in this directory, choose the desired entry in the fieldset below.'),
          '#default_value' => 0,
          '#return_value' => substr($dirname, 1),
          // Get all radio buttons into the same group.
          '#parents' => [
            'component',
          ],
        ];
      }
      $element = [
        '#type' => 'details',
        '#title' => t('Directory "@directory"', $t_args),
        '#open' => FALSE,
      ];
      $form[$this
        ->getFormElementId('fs', $dirname)] =& $element;
    }
    else {
      $element =& $form;
    }
    foreach ($dirkeys as $entry) {

      // A component in this directory with multiple components.
      if ($entry[0] == '#') {

        // Component entry.
        $t_args = [
          '%directory' => $components[$entry]
            ->getPath(),
          '%name' => $components[$entry]
            ->getName(),
          '%pattern' => $components[$entry]
            ->getName() . '.*',
        ];
        $element[$this
          ->getFormElementId('com', $components[$entry]
          ->getExtensionFilename())] = [
          '#type' => 'radio',
          '#title' => $this
            ->t('Extract from %name', $t_args),
          '#description' => $this
            ->t('Extract from files named %pattern in the %directory directory.', $t_args),
          '#default_value' => 0,
          '#return_value' => $components[$entry]
            ->getExtensionPathname(),
          // Get all radio buttons into the same group.
          '#parents' => [
            'component',
          ],
        ];
      }
      else {
        $this
          ->buildComponentSelector($element, $components[$entry], "{$dirname}/{$entry}");
      }
    }
    return count($components);
  }

  /**
   * Generate a sane form element ID for the current radio button.
   *
   * @param string $type
   *   Type of ID generated: 'fs' for fieldset, 'dir' for directory, 'com' for
   *   component.
   * @param string $path
   *   Path of file we generate an ID for.
   *
   * @return string
   *   The generated ID.
   */
  private function getFormElementId($type, $path) {
    return 'potx-' . $type . '-' . preg_replace('/[^a-zA-Z0-9]+/', '-', $path);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 1
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PotxExtractTranslationForm::$languageManager protected property The language manager.
PotxExtractTranslationForm::$moduleHandler protected property The module handler.
PotxExtractTranslationForm::$themeHandler protected property The theme handler.
PotxExtractTranslationForm::buildComponentSelector private function Build a chunk of the component selection form.
PotxExtractTranslationForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
PotxExtractTranslationForm::create public static function Instantiates a new instance of this class. Overrides FormBase::create
PotxExtractTranslationForm::generateComponentList private function Generate a hierarchical structured list of components.
PotxExtractTranslationForm::getFormElementId private function Generate a sane form element ID for the current radio button.
PotxExtractTranslationForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
PotxExtractTranslationForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
PotxExtractTranslationForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
PotxExtractTranslationForm::__construct public function Constructs a new PotxExtractTranslationForm object.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.