diff --git a/Feed/Feed.php b/Feed/Feed.php index aa6c81b..8a12efb 100644 --- a/Feed/Feed.php +++ b/Feed/Feed.php @@ -15,8 +15,9 @@ use Eko\FeedBundle\Item\Writer\RoutedItemInterface; use Eko\FeedBundle\Formatter\RssFormatter; use Eko\FeedBundle\Field\ChannelField; -use Eko\FeedBundle\Field\ItemField; +use Eko\FeedBundle\Field\ItemFieldInterface; use Eko\FeedBundle\Item\Writer\ItemInterface; + use Symfony\Component\Routing\RouterInterface; /** @@ -190,11 +191,11 @@ public function getChannelFields() /** * Add a new item field to render * - * @param ItemField $field A custom Field instance + * @param ItemFieldInterface $field A custom Field instance * * @return \Eko\FeedBundle\Feed\Feed */ - public function addItemField(ItemField $field) + public function addItemField(ItemFieldInterface $field) { $this->itemFields[] = $field; diff --git a/Field/GroupItemField.php b/Field/GroupItemField.php new file mode 100644 index 0000000..f54c88a --- /dev/null +++ b/Field/GroupItemField.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Eko\FeedBundle\Field; + +use Eko\FeedBundle\Field\ItemField; +use Eko\FeedBundle\Field\ItemFieldInterface; + +/** + * GroupField + * + * This is items group field class + * + * @author Vincent Composieux + */ +class GroupItemField implements ItemFieldInterface +{ + /** + * @var string $name Field name + */ + protected $name; + + /** + * @var ItemField ItemField instance + */ + protected $itemField; + + /** + * Constructor + * + * @param string $name A group field name + * @param ItemField $itemField A ItemField instance + */ + public function __construct($name, ItemField $itemField) + { + $this->name = $name; + $this->itemField = $itemField; + } + + /** + * Returns group field name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Returns item field + * + * @return ItemField + */ + public function getItemField() + { + return $this->itemField; + } +} diff --git a/Field/ItemField.php b/Field/ItemField.php index 09f12d1..869e269 100644 --- a/Field/ItemField.php +++ b/Field/ItemField.php @@ -10,14 +10,16 @@ namespace Eko\FeedBundle\Field; +use Eko\FeedBundle\Field\ItemFieldInterface; + /** - * Field + * ItemField * * This is the items field class * * @author Vincent Composieux */ -class ItemField +class ItemField implements ItemFieldInterface { /** * @var string $name Field name diff --git a/Field/ItemFieldInterface.php b/Field/ItemFieldInterface.php new file mode 100644 index 0000000..394d595 --- /dev/null +++ b/Field/ItemFieldInterface.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Eko\FeedBundle\Field; + +/** + * FieldInterface + * + * This is the item field interface + * + * @author Vincent Composieux + */ +interface ItemFieldInterface +{ + /** + * Returns field name + * + * @return string + */ + public function getName(); +} diff --git a/Formatter/Formatter.php b/Formatter/Formatter.php index f23d4b3..4a8b36c 100644 --- a/Formatter/Formatter.php +++ b/Formatter/Formatter.php @@ -11,7 +11,8 @@ namespace Eko\FeedBundle\Formatter; use Eko\FeedBundle\Feed\Feed; -use Eko\FeedBundle\Field\ItemField; +use Eko\FeedBundle\Field\GroupItemField; +use Eko\FeedBundle\Field\ItemFieldInterface; use Eko\FeedBundle\Item\Writer\ItemInterface; /** @@ -53,44 +54,66 @@ public function __construct(Feed $feed) /** * Format items field * - * @param ItemField $field A item field instance - * @param ItemInterface $item An entity instance + * @param ItemFieldInterface $field A item field instance + * @param ItemInterface $item An entity instance * * @return string */ - protected function format(ItemField $field, ItemInterface $item) + protected function format(ItemFieldInterface $field, ItemInterface $item) { $name = $field->getName(); + if ($field instanceof GroupItemField) { + $element = $this->dom->createElement($name); + $itemElements = $this->format($field->getItemField(), $item); + + foreach ($itemElements as $itemElement) { + $element->appendChild($itemElement); + } + + return $element; + } + + $elements = array(); + $method = $field->getMethod(); - $value = $item->{$method}(); + $values = $item->{$method}(); + + if (!is_array($values)) { + $values = array($values); + } - if ($field->get('cdata')) { - $value = $this->dom->createCDATASection($value); + foreach ($values as $value) { + if ($field->get('cdata')) { + $value = $this->dom->createCDATASection($value); - $element = $this->dom->createElement($name); - $element->appendChild($value); - } else if ($field->get('attribute')) { - if (!$field->get('attribute_name')) { - throw new \InvalidArgumentException("'attribute' parameter required an 'attribute_name' parameter."); - } + $element = $this->dom->createElement($name); + $element->appendChild($value); - $element = $this->dom->createElement($name); - $element->setAttribute($field->get('attribute_name'), $item->getFeedItemLink()); + $elements[] = $element; + } else if ($field->get('attribute')) { + if (!$field->get('attribute_name')) { + throw new \InvalidArgumentException("'attribute' parameter required an 'attribute_name' parameter."); + } + + $element = $this->dom->createElement($name); + $element->setAttribute($field->get('attribute_name'), $item->getFeedItemLink()); - } else { - if ($format = $field->get('date_format')) { - if (!$value instanceof \DateTime) { - throw new \InvalidArgumentException(sprintf('Field "%s" should be a DateTime instance.', $name)); + $elements[] = $element; + } else { + if ($format = $field->get('date_format')) { + if (!$value instanceof \DateTime) { + throw new \InvalidArgumentException(sprintf('Field "%s" should be a DateTime instance.', $name)); + } + + $value = $value->format($format); } - $value = $value->format($format); + $elements[] = $this->dom->createElement($name, $value); } - - $element = $this->dom->createElement($name, $value); } - return $element; + return 1 == count($elements) ? current($elements) : $elements; } /** diff --git a/README.md b/README.md index 27e1086..a0e3a72 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,17 @@ $feed->add(new FakeEntity()); $feed->addItemField(new ItemField('fake_custom', 'getFeedItemCustom')); ``` +You can also add group item fields using this way, if your method returns an array: + +```php +get('eko_feed.feed.manager')->get('article'); +$feed->add(new FakeEntity()); +$feed->addItemField( + new GroupItemField('categories', new ItemField('category', 'getFeedCategoriesCustom')) +); +``` + Of course, `getFeedItemCustom()` method needs to be declared in your entity. Moreover, entities objects can be added separatly with add method: diff --git a/Tests/Entity/Writer/FakeItemInterfaceEntity.php b/Tests/Entity/Writer/FakeItemInterfaceEntity.php index 6687868..a8e7933 100644 --- a/Tests/Entity/Writer/FakeItemInterfaceEntity.php +++ b/Tests/Entity/Writer/FakeItemInterfaceEntity.php @@ -70,4 +70,18 @@ public function getFeedItemCustom() { return 'My custom field'; } + + /** + * Returns a fake custom categories array + * + * @return array + */ + public function getFeedCategoriesCustom() + { + return array( + 'category 1', + 'category 2', + 'category 3' + ); + } } \ No newline at end of file diff --git a/Tests/Format/AtomFormatterTest.php b/Tests/Format/AtomFormatterTest.php index d099ef1..9a9d0d4 100644 --- a/Tests/Format/AtomFormatterTest.php +++ b/Tests/Format/AtomFormatterTest.php @@ -12,6 +12,7 @@ use Eko\FeedBundle\Feed\FeedManager; use Eko\FeedBundle\Field\ChannelField; +use Eko\FeedBundle\Field\GroupItemField; use Eko\FeedBundle\Field\ItemField; use Eko\FeedBundle\Tests\Entity\Writer\FakeItemInterfaceEntity; use Eko\FeedBundle\Tests\Entity\Writer\FakeRoutedItemInterfaceEntity; @@ -140,6 +141,27 @@ public function testAddCustomItemFieldWithItemInterface() $this->assertContains('My custom field', $output); } + /** + * Check if a custom group item field is properly rendered with ItemInterface + */ + public function testAddCustomGroupItemFieldWithItemInterface() + { + $feed = $this->manager->get('article'); + $feed->add(new FakeItemInterfaceEntity()); + $feed->addItemField(new GroupItemField( + 'categories', + new ItemField('category', 'getFeedCategoriesCustom')) + ); + + $output = $feed->render('atom'); + + $this->assertContains('', $output); + $this->assertContains('category 1', $output); + $this->assertContains('category 2', $output); + $this->assertContains('category 3', $output); + $this->assertContains('', $output); + } + /** * Check if a custom item field is properly rendered with RoutedItemInterface */ diff --git a/Tests/Format/RSSFormatterTest.php b/Tests/Format/RSSFormatterTest.php index f3d87bf..45cce7b 100644 --- a/Tests/Format/RSSFormatterTest.php +++ b/Tests/Format/RSSFormatterTest.php @@ -12,6 +12,7 @@ use Eko\FeedBundle\Feed\FeedManager; use Eko\FeedBundle\Field\ChannelField; +use Eko\FeedBundle\Field\GroupItemField; use Eko\FeedBundle\Field\ItemField; use Eko\FeedBundle\Tests\Entity\Writer\FakeItemInterfaceEntity; use Eko\FeedBundle\Tests\Entity\Writer\FakeRoutedItemInterfaceEntity; @@ -115,6 +116,26 @@ public function testAddCustomItemFieldWithItemInterface() $this->assertContains('My custom field', $output); } + /** + * Check if a custom group item field is properly rendered with ItemInterface + */ + public function testAddCustomGroupItemFieldWithItemInterface() + { + $feed = $this->manager->get('article'); + $feed->add(new FakeItemInterfaceEntity()); + $feed->addItemField( + new GroupItemField('categories', new ItemField('category', 'getFeedCategoriesCustom')) + ); + + $output = $feed->render('rss'); + + $this->assertContains('', $output); + $this->assertContains('category 1', $output); + $this->assertContains('category 2', $output); + $this->assertContains('category 3', $output); + $this->assertContains('', $output); + } + /** * Check if a custom item field is properly rendered with RoutedItemInterface */