PoDatabaseReader.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. namespace Drupal\locale;
  3. use Drupal\Component\Gettext\PoHeader;
  4. use Drupal\Component\Gettext\PoItem;
  5. use Drupal\Component\Gettext\PoReaderInterface;
  6. /**
  7. * Gettext PO reader working with the locale module database.
  8. */
  9. class PoDatabaseReader implements PoReaderInterface {
  10. /**
  11. * An associative array indicating which type of strings should be read.
  12. *
  13. * Elements of the array:
  14. * - not_customized: boolean indicating if not customized strings should be
  15. * read.
  16. * - customized: boolean indicating if customized strings should be read.
  17. * - no_translated: boolean indicating if non-translated should be read.
  18. *
  19. * The three options define three distinct sets of strings, which combined
  20. * cover all strings.
  21. *
  22. * @var array
  23. */
  24. private $options;
  25. /**
  26. * Language code of the language being read from the database.
  27. *
  28. * @var string
  29. */
  30. private $langcode;
  31. /**
  32. * Store the result of the query so it can be iterated later.
  33. *
  34. * @var resource
  35. */
  36. private $result;
  37. /**
  38. * Constructor, initializes with default options.
  39. */
  40. public function __construct() {
  41. $this->setOptions([]);
  42. }
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public function getLangcode() {
  47. return $this->langcode;
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function setLangcode($langcode) {
  53. $this->langcode = $langcode;
  54. }
  55. /**
  56. * Get the options used by the reader.
  57. */
  58. public function getOptions() {
  59. return $this->options;
  60. }
  61. /**
  62. * Set the options for the current reader.
  63. */
  64. public function setOptions(array $options) {
  65. $options += [
  66. 'customized' => FALSE,
  67. 'not_customized' => FALSE,
  68. 'not_translated' => FALSE,
  69. ];
  70. $this->options = $options;
  71. }
  72. /**
  73. * {@inheritdoc}
  74. */
  75. public function getHeader() {
  76. return new PoHeader($this->getLangcode());
  77. }
  78. /**
  79. * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader().
  80. *
  81. * @throws Exception
  82. * Always, because you cannot set the PO header of a reader.
  83. */
  84. public function setHeader(PoHeader $header) {
  85. throw new \Exception('You cannot set the PO header in a reader.');
  86. }
  87. /**
  88. * Builds and executes a database query based on options set earlier.
  89. */
  90. private function loadStrings() {
  91. $langcode = $this->langcode;
  92. $options = $this->options;
  93. $conditions = [];
  94. if (array_sum($options) == 0) {
  95. // If user asked to not include anything in the translation files,
  96. // that would not make sense, so just fall back on providing a template.
  97. $langcode = NULL;
  98. // Force option to get both translated and untranslated strings.
  99. $options['not_translated'] = TRUE;
  100. }
  101. // Build and execute query to collect source strings and translations.
  102. if (!empty($langcode)) {
  103. $conditions['language'] = $langcode;
  104. // Translate some options into field conditions.
  105. if ($options['customized']) {
  106. if (!$options['not_customized']) {
  107. // Filter for customized strings only.
  108. $conditions['customized'] = LOCALE_CUSTOMIZED;
  109. }
  110. // Else no filtering needed in this case.
  111. }
  112. else {
  113. if ($options['not_customized']) {
  114. // Filter for non-customized strings only.
  115. $conditions['customized'] = LOCALE_NOT_CUSTOMIZED;
  116. }
  117. else {
  118. // Filter for strings without translation.
  119. $conditions['translated'] = FALSE;
  120. }
  121. }
  122. if (!$options['not_translated']) {
  123. // Filter for string with translation.
  124. $conditions['translated'] = TRUE;
  125. }
  126. return \Drupal::service('locale.storage')->getTranslations($conditions);
  127. }
  128. else {
  129. // If no language, we don't need any of the target fields.
  130. return \Drupal::service('locale.storage')->getStrings($conditions);
  131. }
  132. }
  133. /**
  134. * Get the database result resource for the given language and options.
  135. */
  136. private function readString() {
  137. if (!isset($this->result)) {
  138. $this->result = $this->loadStrings();
  139. }
  140. return array_shift($this->result);
  141. }
  142. /**
  143. * {@inheritdoc}
  144. */
  145. public function readItem() {
  146. if ($string = $this->readString()) {
  147. $values = (array) $string;
  148. $po_item = new PoItem();
  149. $po_item->setFromArray($values);
  150. return $po_item;
  151. }
  152. }
  153. }