PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php

https://gitlab.com/andecode/theme-spark
PHP | 291 lines | 168 code | 31 blank | 92 comment | 18 complexity | 751d3e9d697ad86d42cca0f4bea6df29 MD5 | raw file
  1. <?php
  2. namespace Drupal\aggregator\Plugin\aggregator\processor;
  3. use Drupal\aggregator\Entity\Item;
  4. use Drupal\aggregator\FeedInterface;
  5. use Drupal\aggregator\FeedStorageInterface;
  6. use Drupal\aggregator\ItemStorageInterface;
  7. use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
  8. use Drupal\aggregator\Plugin\ProcessorInterface;
  9. use Drupal\Component\Utility\Unicode;
  10. use Drupal\Core\Config\ConfigFactoryInterface;
  11. use Drupal\Core\Datetime\DateFormatterInterface;
  12. use Drupal\Core\Form\ConfigFormBaseTrait;
  13. use Drupal\Core\Form\FormStateInterface;
  14. use Drupal\Core\Messenger\MessengerInterface;
  15. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  16. use Drupal\Core\Url;
  17. use Symfony\Component\DependencyInjection\ContainerInterface;
  18. /**
  19. * Defines a default processor implementation.
  20. *
  21. * Creates lightweight records from feed items.
  22. *
  23. * @AggregatorProcessor(
  24. * id = "aggregator",
  25. * title = @Translation("Default processor"),
  26. * description = @Translation("Creates lightweight records from feed items.")
  27. * )
  28. */
  29. class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface, ContainerFactoryPluginInterface {
  30. use ConfigFormBaseTrait;
  31. /**
  32. * Contains the configuration object factory.
  33. *
  34. * @var \Drupal\Core\Config\ConfigFactoryInterface
  35. */
  36. protected $configFactory;
  37. /**
  38. * The entity storage for items.
  39. *
  40. * @var \Drupal\aggregator\ItemStorageInterface
  41. */
  42. protected $itemStorage;
  43. /**
  44. * The date formatter service.
  45. *
  46. * @var \Drupal\Core\Datetime\DateFormatterInterface
  47. */
  48. protected $dateFormatter;
  49. /**
  50. * The messenger.
  51. *
  52. * @var \Drupal\Core\Messenger\MessengerInterface
  53. */
  54. protected $messenger;
  55. /**
  56. * Constructs a DefaultProcessor object.
  57. *
  58. * @param array $configuration
  59. * A configuration array containing information about the plugin instance.
  60. * @param string $plugin_id
  61. * The plugin_id for the plugin instance.
  62. * @param mixed $plugin_definition
  63. * The plugin implementation definition.
  64. * @param \Drupal\Core\Config\ConfigFactoryInterface $config
  65. * The configuration factory object.
  66. * @param \Drupal\aggregator\ItemStorageInterface $item_storage
  67. * The entity storage for feed items.
  68. * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
  69. * The date formatter service.
  70. * @param \Drupal\Core\Messenger\MessengerInterface $messenger
  71. * The messenger.
  72. */
  73. public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, ItemStorageInterface $item_storage, DateFormatterInterface $date_formatter, MessengerInterface $messenger) {
  74. $this->configFactory = $config;
  75. $this->itemStorage = $item_storage;
  76. $this->dateFormatter = $date_formatter;
  77. $this->messenger = $messenger;
  78. // @todo Refactor aggregator plugins to ConfigEntity so merging
  79. // the configuration here is not needed.
  80. parent::__construct($configuration + $this->getConfiguration(), $plugin_id, $plugin_definition);
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  86. return new static(
  87. $configuration,
  88. $plugin_id,
  89. $plugin_definition,
  90. $container->get('config.factory'),
  91. $container->get('entity_type.manager')->getStorage('aggregator_item'),
  92. $container->get('date.formatter'),
  93. $container->get('messenger')
  94. );
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. protected function getEditableConfigNames() {
  100. return ['aggregator.settings'];
  101. }
  102. /**
  103. * {@inheritdoc}
  104. */
  105. public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  106. $config = $this->config('aggregator.settings');
  107. $processors = $config->get('processors');
  108. $info = $this->getPluginDefinition();
  109. $counts = [3, 5, 10, 15, 20, 25];
  110. $items = array_map(function ($count) {
  111. return $this->formatPlural($count, '1 item', '@count items');
  112. }, array_combine($counts, $counts));
  113. $intervals = [3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800];
  114. $period = array_map([$this->dateFormatter, 'formatInterval'], array_combine($intervals, $intervals));
  115. $period[FeedStorageInterface::CLEAR_NEVER] = t('Never');
  116. $form['processors'][$info['id']] = [];
  117. // Only wrap into details if there is a basic configuration.
  118. if (isset($form['basic_conf'])) {
  119. $form['processors'][$info['id']] = [
  120. '#type' => 'details',
  121. '#title' => t('Default processor settings'),
  122. '#description' => $info['description'],
  123. '#open' => in_array($info['id'], $processors),
  124. ];
  125. }
  126. $form['processors'][$info['id']]['aggregator_summary_items'] = [
  127. '#type' => 'select',
  128. '#title' => t('Number of items shown in listing pages'),
  129. '#default_value' => $config->get('source.list_max'),
  130. '#empty_value' => 0,
  131. '#options' => $items,
  132. ];
  133. $form['processors'][$info['id']]['aggregator_clear'] = [
  134. '#type' => 'select',
  135. '#title' => t('Discard items older than'),
  136. '#default_value' => $config->get('items.expire'),
  137. '#options' => $period,
  138. '#description' => t('Requires a correctly configured <a href=":cron">cron maintenance task</a>.', [':cron' => Url::fromRoute('system.status')->toString()]),
  139. ];
  140. $lengths = [0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000];
  141. $options = array_map(function ($length) {
  142. return ($length == 0) ? t('Unlimited') : $this->formatPlural($length, '1 character', '@count characters');
  143. }, array_combine($lengths, $lengths));
  144. $form['processors'][$info['id']]['aggregator_teaser_length'] = [
  145. '#type' => 'select',
  146. '#title' => t('Length of trimmed description'),
  147. '#default_value' => $config->get('items.teaser_length'),
  148. '#options' => $options,
  149. '#description' => t('The maximum number of characters used in the trimmed version of content.'),
  150. ];
  151. return $form;
  152. }
  153. /**
  154. * {@inheritdoc}
  155. */
  156. public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  157. $this->configuration['items']['expire'] = $form_state->getValue('aggregator_clear');
  158. $this->configuration['items']['teaser_length'] = $form_state->getValue('aggregator_teaser_length');
  159. $this->configuration['source']['list_max'] = $form_state->getValue('aggregator_summary_items');
  160. // @todo Refactor aggregator plugins to ConfigEntity so this is not needed.
  161. $this->setConfiguration($this->configuration);
  162. }
  163. /**
  164. * {@inheritdoc}
  165. */
  166. public function process(FeedInterface $feed) {
  167. if (!is_array($feed->items)) {
  168. return;
  169. }
  170. foreach ($feed->items as $item) {
  171. // @todo The default entity view builder always returns an empty
  172. // array, which is ignored in aggregator_save_item() currently. Should
  173. // probably be fixed.
  174. if (empty($item['title'])) {
  175. continue;
  176. }
  177. // Save this item. Try to avoid duplicate entries as much as possible. If
  178. // we find a duplicate entry, we resolve it and pass along its ID is such
  179. // that we can update it if needed.
  180. if (!empty($item['guid'])) {
  181. $values = ['fid' => $feed->id(), 'guid' => $item['guid']];
  182. }
  183. elseif ($item['link'] && $item['link'] != $feed->link && $item['link'] != $feed->url) {
  184. $values = ['fid' => $feed->id(), 'link' => $item['link']];
  185. }
  186. else {
  187. $values = ['fid' => $feed->id(), 'title' => $item['title']];
  188. }
  189. // Try to load an existing entry.
  190. if ($entry = $this->itemStorage->loadByProperties($values)) {
  191. $entry = reset($entry);
  192. }
  193. else {
  194. $entry = Item::create(['langcode' => $feed->language()->getId()]);
  195. }
  196. if ($item['timestamp']) {
  197. $entry->setPostedTime($item['timestamp']);
  198. }
  199. // Make sure the item title and author fit in the 255 varchar column.
  200. $entry->setTitle(Unicode::truncate($item['title'], 255, TRUE, TRUE));
  201. $entry->setAuthor(Unicode::truncate($item['author'], 255, TRUE, TRUE));
  202. $entry->setFeedId($feed->id());
  203. $entry->setLink($item['link']);
  204. $entry->setGuid($item['guid']);
  205. $description = '';
  206. if (!empty($item['description'])) {
  207. $description = $item['description'];
  208. }
  209. $entry->setDescription($description);
  210. $entry->save();
  211. }
  212. }
  213. /**
  214. * {@inheritdoc}
  215. */
  216. public function delete(FeedInterface $feed) {
  217. if ($items = $this->itemStorage->loadByFeed($feed->id())) {
  218. $this->itemStorage->delete($items);
  219. }
  220. // @todo This should be moved out to caller with a different message maybe.
  221. $this->messenger->addStatus(t('The news items from %site have been deleted.', ['%site' => $feed->label()]));
  222. }
  223. /**
  224. * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
  225. *
  226. * Expires items from a feed depending on expiration settings.
  227. */
  228. public function postProcess(FeedInterface $feed) {
  229. $aggregator_clear = $this->configuration['items']['expire'];
  230. if ($aggregator_clear != FeedStorageInterface::CLEAR_NEVER) {
  231. // Delete all items that are older than flush item timer.
  232. $age = REQUEST_TIME - $aggregator_clear;
  233. $result = $this->itemStorage->getQuery()
  234. ->accessCheck(FALSE)
  235. ->condition('fid', $feed->id())
  236. ->condition('timestamp', $age, '<')
  237. ->execute();
  238. if ($result) {
  239. $entities = $this->itemStorage->loadMultiple($result);
  240. $this->itemStorage->delete($entities);
  241. }
  242. }
  243. }
  244. /**
  245. * {@inheritdoc}
  246. */
  247. public function getConfiguration() {
  248. return $this->configFactory->get('aggregator.settings')->get();
  249. }
  250. /**
  251. * {@inheritdoc}
  252. */
  253. public function setConfiguration(array $configuration) {
  254. $config = $this->config('aggregator.settings');
  255. foreach ($configuration as $key => $value) {
  256. $config->set($key, $value);
  257. }
  258. $config->save();
  259. }
  260. }