/libraries/src/Feed/Feed.php

https://github.com/joomla/joomla-cms · PHP · 371 lines · 140 code · 39 blank · 192 comment · 18 complexity · c0d1530978c53a29e1f39aa3296e531b MD5 · raw file

  1. <?php
  2. /**
  3. * Joomla! Content Management System
  4. *
  5. * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
  6. * @license GNU General Public License version 2 or later; see LICENSE.txt
  7. */
  8. namespace Joomla\CMS\Feed;
  9. use Joomla\CMS\Date\Date;
  10. /**
  11. * Class to encapsulate a feed for the Joomla Platform.
  12. *
  13. * @property FeedPerson $author Person responsible for feed content.
  14. * @property array $categories Categories to which the feed belongs.
  15. * @property array $contributors People who contributed to the feed content.
  16. * @property string $copyright Information about rights, e.g. copyrights, held in and over the feed.
  17. * @property string $description A phrase or sentence describing the feed.
  18. * @property string $generator A string indicating the program used to generate the feed.
  19. * @property FeedLink|null $image FeedLink object containing feed image properties.
  20. * @property Date $publishedDate The publication date for the feed content.
  21. * @property string $title A human readable title for the feed.
  22. * @property Date $updatedDate The last time the content of the feed changed.
  23. * @property string $uri Universal, permanent identifier for the feed.
  24. *
  25. * @since 3.1.4
  26. */
  27. class Feed implements \ArrayAccess, \Countable
  28. {
  29. /**
  30. * @var array The entry properties.
  31. * @since 3.1.4
  32. */
  33. protected $properties = array(
  34. 'uri' => '',
  35. 'title' => '',
  36. 'updatedDate' => '',
  37. 'description' => '',
  38. 'categories' => array(),
  39. 'contributors' => array(),
  40. );
  41. /**
  42. * @var array The list of feed entry objects.
  43. * @since 3.1.4
  44. */
  45. protected $entries = array();
  46. /**
  47. * Magic method to return values for feed properties.
  48. *
  49. * @param string $name The name of the property.
  50. *
  51. * @return mixed
  52. *
  53. * @since 3.1.4
  54. */
  55. public function __get($name)
  56. {
  57. return $this->properties[$name] ?? null;
  58. }
  59. /**
  60. * Magic method to set values for feed properties.
  61. *
  62. * @param string $name The name of the property.
  63. * @param mixed $value The value to set for the property.
  64. *
  65. * @return void
  66. *
  67. * @since 3.1.4
  68. */
  69. public function __set($name, $value)
  70. {
  71. // Ensure that setting a date always sets a Date instance.
  72. if ((($name === 'updatedDate') || ($name === 'publishedDate')) && !($value instanceof Date)) {
  73. $value = new Date($value);
  74. }
  75. // Validate that any authors that are set are instances of JFeedPerson or null.
  76. if (($name === 'author') && (!($value instanceof FeedPerson) || ($value === null))) {
  77. throw new \InvalidArgumentException(
  78. sprintf(
  79. '%1$s "author" must be an instance of Joomla\\CMS\\Feed\\FeedPerson. %2$s given.',
  80. \get_class($this),
  81. \gettype($value) === 'object' ? \get_class($value) : \gettype($value)
  82. )
  83. );
  84. }
  85. // Disallow setting categories or contributors directly.
  86. if (\in_array($name, array('categories', 'contributors'))) {
  87. throw new \InvalidArgumentException(
  88. sprintf(
  89. 'Cannot directly set %1$s property "%2$s".',
  90. \get_class($this),
  91. $name
  92. )
  93. );
  94. }
  95. $this->properties[$name] = $value;
  96. }
  97. /**
  98. * Method to add a category to the feed object.
  99. *
  100. * @param string $name The name of the category to add.
  101. * @param string $uri The optional URI for the category to add.
  102. *
  103. * @return Feed
  104. *
  105. * @since 3.1.4
  106. */
  107. public function addCategory($name, $uri = '')
  108. {
  109. $this->properties['categories'][$name] = $uri;
  110. return $this;
  111. }
  112. /**
  113. * Method to add a contributor to the feed object.
  114. *
  115. * @param string $name The full name of the person to add.
  116. * @param string $email The email address of the person to add.
  117. * @param string $uri The optional URI for the person to add.
  118. * @param string $type The optional type of person to add.
  119. *
  120. * @return Feed
  121. *
  122. * @since 3.1.4
  123. */
  124. public function addContributor($name, $email, $uri = null, $type = null)
  125. {
  126. $contributor = new FeedPerson($name, $email, $uri, $type);
  127. // If the new contributor already exists then there is nothing to do, so just return.
  128. foreach ($this->properties['contributors'] as $c) {
  129. if ($c == $contributor) {
  130. return $this;
  131. }
  132. }
  133. // Add the new contributor.
  134. $this->properties['contributors'][] = $contributor;
  135. return $this;
  136. }
  137. /**
  138. * Method to add an entry to the feed object.
  139. *
  140. * @param FeedEntry $entry The entry object to add.
  141. *
  142. * @return Feed
  143. *
  144. * @since 3.1.4
  145. */
  146. public function addEntry(FeedEntry $entry)
  147. {
  148. // If the new entry already exists then there is nothing to do, so just return.
  149. foreach ($this->entries as $e) {
  150. if ($e == $entry) {
  151. return $this;
  152. }
  153. }
  154. // Add the new entry.
  155. $this->entries[] = $entry;
  156. return $this;
  157. }
  158. /**
  159. * Returns a count of the number of entries in the feed.
  160. *
  161. * This method is here to implement the Countable interface.
  162. * You can call it by doing count($feed) rather than $feed->count();
  163. *
  164. * @return integer number of entries in the feed.
  165. */
  166. #[\ReturnTypeWillChange]
  167. public function count()
  168. {
  169. return \count($this->entries);
  170. }
  171. /**
  172. * Whether or not an offset exists. This method is executed when using isset() or empty() on
  173. * objects implementing ArrayAccess.
  174. *
  175. * @param mixed $offset An offset to check for.
  176. *
  177. * @return boolean
  178. *
  179. * @see ArrayAccess::offsetExists()
  180. * @since 3.1.4
  181. */
  182. #[\ReturnTypeWillChange]
  183. public function offsetExists($offset)
  184. {
  185. return isset($this->entries[$offset]);
  186. }
  187. /**
  188. * Returns the value at specified offset.
  189. *
  190. * @param mixed $offset The offset to retrieve.
  191. *
  192. * @return mixed The value at the offset.
  193. *
  194. * @see ArrayAccess::offsetGet()
  195. * @since 3.1.4
  196. */
  197. #[\ReturnTypeWillChange]
  198. public function offsetGet($offset)
  199. {
  200. return $this->entries[$offset];
  201. }
  202. /**
  203. * Assigns a value to the specified offset.
  204. *
  205. * @param mixed $offset The offset to assign the value to.
  206. * @param FeedEntry $value The JFeedEntry to set.
  207. *
  208. * @return boolean
  209. *
  210. * @see ArrayAccess::offsetSet()
  211. * @since 3.1.4
  212. * @throws \InvalidArgumentException
  213. */
  214. #[\ReturnTypeWillChange]
  215. public function offsetSet($offset, $value)
  216. {
  217. if (!($value instanceof FeedEntry)) {
  218. throw new \InvalidArgumentException(
  219. sprintf(
  220. '%1$s entries must be an instance of Joomla\\CMS\\Feed\\FeedPerson. %2$s given.',
  221. \get_class($this),
  222. \gettype($value) === 'object' ? \get_class($value) : \gettype($value)
  223. )
  224. );
  225. }
  226. $this->entries[$offset] = $value;
  227. return true;
  228. }
  229. /**
  230. * Unsets an offset.
  231. *
  232. * @param mixed $offset The offset to unset.
  233. *
  234. * @return void
  235. *
  236. * @see ArrayAccess::offsetUnset()
  237. * @since 3.1.4
  238. */
  239. #[\ReturnTypeWillChange]
  240. public function offsetUnset($offset)
  241. {
  242. unset($this->entries[$offset]);
  243. }
  244. /**
  245. * Method to remove a category from the feed object.
  246. *
  247. * @param string $name The name of the category to remove.
  248. *
  249. * @return Feed
  250. *
  251. * @since 3.1.4
  252. */
  253. public function removeCategory($name)
  254. {
  255. unset($this->properties['categories'][$name]);
  256. return $this;
  257. }
  258. /**
  259. * Method to remove a contributor from the feed object.
  260. *
  261. * @param FeedPerson $contributor The person object to remove.
  262. *
  263. * @return Feed
  264. *
  265. * @since 3.1.4
  266. */
  267. public function removeContributor(FeedPerson $contributor)
  268. {
  269. // If the contributor exists remove it.
  270. foreach ($this->properties['contributors'] as $k => $c) {
  271. if ($c == $contributor) {
  272. unset($this->properties['contributors'][$k]);
  273. $this->properties['contributors'] = array_values($this->properties['contributors']);
  274. return $this;
  275. }
  276. }
  277. return $this;
  278. }
  279. /**
  280. * Method to remove an entry from the feed object.
  281. *
  282. * @param FeedEntry $entry The entry object to remove.
  283. *
  284. * @return Feed
  285. *
  286. * @since 3.1.4
  287. */
  288. public function removeEntry(FeedEntry $entry)
  289. {
  290. // If the entry exists remove it.
  291. foreach ($this->entries as $k => $e) {
  292. if ($e == $entry) {
  293. unset($this->entries[$k]);
  294. $this->entries = array_values($this->entries);
  295. return $this;
  296. }
  297. }
  298. return $this;
  299. }
  300. /**
  301. * Shortcut method to set the author for the feed object.
  302. *
  303. * @param string $name The full name of the person to set.
  304. * @param string $email The email address of the person to set.
  305. * @param string $uri The optional URI for the person to set.
  306. * @param string $type The optional type of person to set.
  307. *
  308. * @return Feed
  309. *
  310. * @since 3.1.4
  311. */
  312. public function setAuthor($name, $email, $uri = null, $type = null)
  313. {
  314. $author = new FeedPerson($name, $email, $uri, $type);
  315. $this->properties['author'] = $author;
  316. return $this;
  317. }
  318. /**
  319. * Method to reverse the items if display is set to 'oldest first'
  320. *
  321. * @return Feed
  322. *
  323. * @since 3.1.4
  324. */
  325. public function reverseItems()
  326. {
  327. if (\is_array($this->entries) && !empty($this->entries)) {
  328. $this->entries = array_reverse($this->entries);
  329. }
  330. return $this;
  331. }
  332. }