SubscriptionListBuilder.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace PicoFeed\Serialization;
  3. use DOMDocument;
  4. use DOMElement;
  5. /**
  6. * Class SubscriptionListBuilder
  7. *
  8. * @package PicoFeed\Serialization
  9. * @author Frederic Guillot
  10. */
  11. class SubscriptionListBuilder
  12. {
  13. /**
  14. * @var SubscriptionList
  15. */
  16. protected $subscriptionList;
  17. /**
  18. * @var DOMDocument
  19. */
  20. protected $document;
  21. /**
  22. * Constructor.
  23. *
  24. * @access public
  25. * @param SubscriptionList $subscriptionList
  26. */
  27. public function __construct(SubscriptionList $subscriptionList)
  28. {
  29. $this->subscriptionList = $subscriptionList;
  30. }
  31. /**
  32. * Get object instance
  33. *
  34. * @static
  35. * @access public
  36. * @param SubscriptionList $subscriptionList
  37. * @return SubscriptionListBuilder
  38. */
  39. public static function create(SubscriptionList $subscriptionList)
  40. {
  41. return new static($subscriptionList);
  42. }
  43. /**
  44. * Build OPML feed
  45. *
  46. * @access public
  47. * @param string $filename
  48. * @return string
  49. */
  50. public function build($filename = '')
  51. {
  52. $this->document = new DomDocument('1.0', 'UTF-8');
  53. $this->document->formatOutput = true;
  54. $opmlElement = $this->document->createElement('opml');
  55. $opmlElement->setAttribute('version', '1.0');
  56. $headElement = $this->document->createElement('head');
  57. if ($this->subscriptionList->getTitle() !== '') {
  58. $titleElement = $this->document->createElement('title');
  59. $titleElement->appendChild($this->document->createTextNode($this->subscriptionList->getTitle()));
  60. $headElement->appendChild($titleElement);
  61. }
  62. $opmlElement->appendChild($headElement);
  63. $opmlElement->appendChild($this->buildBody());
  64. $this->document->appendChild($opmlElement);
  65. if ($filename !== '') {
  66. $this->document->save($filename);
  67. return '';
  68. }
  69. return $this->document->saveXML();
  70. }
  71. /**
  72. * Return true if the list has categories
  73. *
  74. * @access public
  75. * @return bool
  76. */
  77. public function hasCategories()
  78. {
  79. foreach ($this->subscriptionList->subscriptions as $subscription) {
  80. if ($subscription->getCategory() !== '') {
  81. return true;
  82. }
  83. }
  84. return false;
  85. }
  86. /**
  87. * Build OPML body
  88. *
  89. * @access protected
  90. * @return DOMElement
  91. */
  92. protected function buildBody()
  93. {
  94. $bodyElement = $this->document->createElement('body');
  95. if ($this->hasCategories()) {
  96. $this->buildCategories($bodyElement);
  97. return $bodyElement;
  98. }
  99. foreach ($this->subscriptionList->subscriptions as $subscription) {
  100. $bodyElement->appendChild($this->buildSubscription($subscription));
  101. }
  102. return $bodyElement;
  103. }
  104. /**
  105. * Build categories section
  106. *
  107. * @access protected
  108. * @param DOMElement $bodyElement
  109. */
  110. protected function buildCategories(DOMElement $bodyElement)
  111. {
  112. $categories = $this->groupByCategories();
  113. foreach ($categories as $category => $subscriptions) {
  114. $bodyElement->appendChild($this->buildCategory($category, $subscriptions));
  115. }
  116. }
  117. /**
  118. * Build category tag
  119. *
  120. * @access protected
  121. * @param string $category
  122. * @param array $subscriptions
  123. * @return DOMElement
  124. */
  125. protected function buildCategory($category, array $subscriptions)
  126. {
  127. $outlineElement = $this->document->createElement('outline');
  128. $outlineElement->setAttribute('text', $category);
  129. foreach ($subscriptions as $subscription) {
  130. $outlineElement->appendChild($this->buildSubscription($subscription));
  131. }
  132. return $outlineElement;
  133. }
  134. /**
  135. * Build subscription entry
  136. *
  137. * @access public
  138. * @param Subscription $subscription
  139. * @return DOMElement
  140. */
  141. protected function buildSubscription(Subscription $subscription)
  142. {
  143. $outlineElement = $this->document->createElement('outline');
  144. $outlineElement->setAttribute('type', $subscription->getType() ?: 'rss');
  145. $outlineElement->setAttribute('text', $subscription->getTitle() ?: $subscription->getFeedUrl());
  146. $outlineElement->setAttribute('xmlUrl', $subscription->getFeedUrl());
  147. if ($subscription->getTitle() !== '') {
  148. $outlineElement->setAttribute('title', $subscription->getTitle());
  149. }
  150. if ($subscription->getDescription() !== '') {
  151. $outlineElement->setAttribute('description', $subscription->getDescription());
  152. }
  153. if ($subscription->getSiteUrl() !== '') {
  154. $outlineElement->setAttribute('htmlUrl', $subscription->getSiteUrl());
  155. }
  156. return $outlineElement;
  157. }
  158. /**
  159. * Group subscriptions by category
  160. *
  161. * @access private
  162. * @return array
  163. */
  164. private function groupByCategories()
  165. {
  166. $categories = array();
  167. foreach ($this->subscriptionList->subscriptions as $subscription) {
  168. $categories[$subscription->getCategory()][] = $subscription;
  169. }
  170. return $categories;
  171. }
  172. }