1<?php 2 3/** 4 * @see https://github.com/laminas/laminas-feed for the canonical source repository 5 * @copyright https://github.com/laminas/laminas-feed/blob/master/COPYRIGHT.md 6 * @license https://github.com/laminas/laminas-feed/blob/master/LICENSE.md New BSD License 7 */ 8 9namespace Laminas\Feed\Writer; 10 11use Laminas\ServiceManager\AbstractPluginManager; 12use Laminas\ServiceManager\Exception\InvalidServiceException; 13use Laminas\ServiceManager\Factory\InvokableFactory; 14 15/** 16 * Plugin manager implementation for feed writer extensions 17 * 18 * Validation checks that we have an Entry, Feed, or Extension\AbstractRenderer. 19 */ 20class ExtensionPluginManager extends AbstractPluginManager implements ExtensionManagerInterface 21{ 22 /** 23 * Aliases for default set of extension classes 24 * 25 * @var array 26 */ 27 protected $aliases = [ 28 'atomrendererfeed' => Extension\Atom\Renderer\Feed::class, 29 'atomRendererFeed' => Extension\Atom\Renderer\Feed::class, 30 'AtomRendererFeed' => Extension\Atom\Renderer\Feed::class, 31 'AtomRenderer\Feed' => Extension\Atom\Renderer\Feed::class, 32 'Atom\Renderer\Feed' => Extension\Atom\Renderer\Feed::class, 33 'contentrendererentry' => Extension\Content\Renderer\Entry::class, 34 'contentRendererEntry' => Extension\Content\Renderer\Entry::class, 35 'ContentRendererEntry' => Extension\Content\Renderer\Entry::class, 36 'ContentRenderer\Entry' => Extension\Content\Renderer\Entry::class, 37 'Content\Renderer\Entry' => Extension\Content\Renderer\Entry::class, 38 'dublincorerendererentry' => Extension\DublinCore\Renderer\Entry::class, 39 'dublinCoreRendererEntry' => Extension\DublinCore\Renderer\Entry::class, 40 'DublinCoreRendererEntry' => Extension\DublinCore\Renderer\Entry::class, 41 'DublinCoreRenderer\Entry' => Extension\DublinCore\Renderer\Entry::class, 42 'DublinCore\Renderer\Entry' => Extension\DublinCore\Renderer\Entry::class, 43 'dublincorerendererfeed' => Extension\DublinCore\Renderer\Feed::class, 44 'dublinCoreRendererFeed' => Extension\DublinCore\Renderer\Feed::class, 45 'DublinCoreRendererFeed' => Extension\DublinCore\Renderer\Feed::class, 46 'DublinCoreRenderer\Feed' => Extension\DublinCore\Renderer\Feed::class, 47 'DublinCore\Renderer\Feed' => Extension\DublinCore\Renderer\Feed::class, 48 'googleplaypodcastentry' => Extension\GooglePlayPodcast\Entry::class, 49 'googleplaypodcastEntry' => Extension\GooglePlayPodcast\Entry::class, 50 'googlePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, 51 'GooglePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, 52 'Googleplaypodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, 53 'GooglePlayPodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, 54 'googleplaypodcastfeed' => Extension\GooglePlayPodcast\Feed::class, 55 'googleplaypodcastFeed' => Extension\GooglePlayPodcast\Feed::class, 56 'googlePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, 57 'GooglePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, 58 'Googleplaypodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, 59 'GooglePlayPodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, 60 'googleplaypodcastrendererentry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 61 'googleplaypodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 62 'googlePlayPodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 63 'GooglePlayPodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 64 'GoogleplaypodcastRenderer\Entry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 65 'GooglePlayPodcast\Renderer\Entry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 66 'googleplaypodcastrendererfeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 67 'googleplaypodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 68 'googlePlayPodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 69 'GooglePlayPodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 70 'GoogleplaypodcastRenderer\Feed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 71 'GooglePlayPodcast\Renderer\Feed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 72 'itunesentry' => Extension\ITunes\Entry::class, 73 'itunesEntry' => Extension\ITunes\Entry::class, 74 'iTunesEntry' => Extension\ITunes\Entry::class, 75 'ItunesEntry' => Extension\ITunes\Entry::class, 76 'Itunes\Entry' => Extension\ITunes\Entry::class, 77 'ITunes\Entry' => Extension\ITunes\Entry::class, 78 'itunesfeed' => Extension\ITunes\Feed::class, 79 'itunesFeed' => Extension\ITunes\Feed::class, 80 'iTunesFeed' => Extension\ITunes\Feed::class, 81 'ItunesFeed' => Extension\ITunes\Feed::class, 82 'Itunes\Feed' => Extension\ITunes\Feed::class, 83 'ITunes\Feed' => Extension\ITunes\Feed::class, 84 'itunesrendererentry' => Extension\ITunes\Renderer\Entry::class, 85 'itunesRendererEntry' => Extension\ITunes\Renderer\Entry::class, 86 'iTunesRendererEntry' => Extension\ITunes\Renderer\Entry::class, 87 'ItunesRendererEntry' => Extension\ITunes\Renderer\Entry::class, 88 'ItunesRenderer\Entry' => Extension\ITunes\Renderer\Entry::class, 89 'ITunes\Renderer\Entry' => Extension\ITunes\Renderer\Entry::class, 90 'itunesrendererfeed' => Extension\ITunes\Renderer\Feed::class, 91 'itunesRendererFeed' => Extension\ITunes\Renderer\Feed::class, 92 'iTunesRendererFeed' => Extension\ITunes\Renderer\Feed::class, 93 'ItunesRendererFeed' => Extension\ITunes\Renderer\Feed::class, 94 'ItunesRenderer\Feed' => Extension\ITunes\Renderer\Feed::class, 95 'ITunes\Renderer\Feed' => Extension\ITunes\Renderer\Feed::class, 96 'slashrendererentry' => Extension\Slash\Renderer\Entry::class, 97 'slashRendererEntry' => Extension\Slash\Renderer\Entry::class, 98 'SlashRendererEntry' => Extension\Slash\Renderer\Entry::class, 99 'SlashRenderer\Entry' => Extension\Slash\Renderer\Entry::class, 100 'Slash\Renderer\Entry' => Extension\Slash\Renderer\Entry::class, 101 'threadingrendererentry' => Extension\Threading\Renderer\Entry::class, 102 'threadingRendererEntry' => Extension\Threading\Renderer\Entry::class, 103 'ThreadingRendererEntry' => Extension\Threading\Renderer\Entry::class, 104 'ThreadingRenderer\Entry' => Extension\Threading\Renderer\Entry::class, 105 'Threading\Renderer\Entry' => Extension\Threading\Renderer\Entry::class, 106 'wellformedwebrendererentry' => Extension\WellFormedWeb\Renderer\Entry::class, 107 'wellFormedWebRendererEntry' => Extension\WellFormedWeb\Renderer\Entry::class, 108 'WellFormedWebRendererEntry' => Extension\WellFormedWeb\Renderer\Entry::class, 109 'WellFormedWebRenderer\Entry' => Extension\WellFormedWeb\Renderer\Entry::class, 110 'WellFormedWeb\Renderer\Entry' => Extension\WellFormedWeb\Renderer\Entry::class, 111 112 // Legacy Zend Framework aliases 113 // @codingStandardsIgnoreStart 114 \Zend\Feed\Writer\Extension\Atom\Renderer\Feed::class => Extension\Atom\Renderer\Feed::class, 115 \Zend\Feed\Writer\Extension\Content\Renderer\Entry::class => Extension\Content\Renderer\Entry::class, 116 \Zend\Feed\Writer\Extension\DublinCore\Renderer\Entry::class => Extension\DublinCore\Renderer\Entry::class, 117 \Zend\Feed\Writer\Extension\DublinCore\Renderer\Feed::class => Extension\DublinCore\Renderer\Feed::class, 118 \Zend\Feed\Writer\Extension\GooglePlayPodcast\Entry::class => Extension\GooglePlayPodcast\Entry::class, 119 \Zend\Feed\Writer\Extension\GooglePlayPodcast\Feed::class => Extension\GooglePlayPodcast\Feed::class, 120 \Zend\Feed\Writer\Extension\GooglePlayPodcast\Renderer\Entry::class => Extension\GooglePlayPodcast\Renderer\Entry::class, 121 \Zend\Feed\Writer\Extension\GooglePlayPodcast\Renderer\Feed::class => Extension\GooglePlayPodcast\Renderer\Feed::class, 122 \Zend\Feed\Writer\Extension\ITunes\Entry::class => Extension\ITunes\Entry::class, 123 \Zend\Feed\Writer\Extension\ITunes\Feed::class => Extension\ITunes\Feed::class, 124 \Zend\Feed\Writer\Extension\ITunes\Renderer\Entry::class => Extension\ITunes\Renderer\Entry::class, 125 \Zend\Feed\Writer\Extension\ITunes\Renderer\Feed::class => Extension\ITunes\Renderer\Feed::class, 126 \Zend\Feed\Writer\Extension\Slash\Renderer\Entry::class => Extension\Slash\Renderer\Entry::class, 127 \Zend\Feed\Writer\Extension\Threading\Renderer\Entry::class => Extension\Threading\Renderer\Entry::class, 128 \Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry::class => Extension\WellFormedWeb\Renderer\Entry::class, 129 // @codingStandardsIgnoreEnd 130 131 // v2 normalized FQCNs 132 'zendfeedwriterextensionatomrendererfeed' => Extension\Atom\Renderer\Feed::class, 133 'zendfeedwriterextensioncontentrendererentry' => Extension\Content\Renderer\Entry::class, 134 'zendfeedwriterextensiondublincorerendererentry' => Extension\DublinCore\Renderer\Entry::class, 135 'zendfeedwriterextensiondublincorerendererfeed' => Extension\DublinCore\Renderer\Feed::class, 136 'zendfeedwriterextensiongoogleplaypodcastentry' => Extension\GooglePlayPodcast\Entry::class, 137 'zendfeedwriterextensiongoogleplaypodcastfeed' => Extension\GooglePlayPodcast\Feed::class, 138 'zendfeedwriterextensiongoogleplaypodcastrendererentry' => Extension\GooglePlayPodcast\Renderer\Entry::class, 139 'zendfeedwriterextensiongoogleplaypodcastrendererfeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 140 'zendfeedwriterextensionitunesentry' => Extension\ITunes\Entry::class, 141 'zendfeedwriterextensionitunesfeed' => Extension\ITunes\Feed::class, 142 'zendfeedwriterextensionitunesrendererentry' => Extension\ITunes\Renderer\Entry::class, 143 'zendfeedwriterextensionitunesrendererfeed' => Extension\ITunes\Renderer\Feed::class, 144 'zendfeedwriterextensionslashrendererentry' => Extension\Slash\Renderer\Entry::class, 145 'zendfeedwriterextensionthreadingrendererentry' => Extension\Threading\Renderer\Entry::class, 146 'zendfeedwriterextensionwellformedwebrendererentry' => Extension\WellFormedWeb\Renderer\Entry::class, 147 ]; 148 149 /** 150 * Factories for default set of extension classes 151 * 152 * @var array 153 */ 154 protected $factories = [ 155 Extension\Atom\Renderer\Feed::class => InvokableFactory::class, 156 Extension\Content\Renderer\Entry::class => InvokableFactory::class, 157 Extension\DublinCore\Renderer\Entry::class => InvokableFactory::class, 158 Extension\DublinCore\Renderer\Feed::class => InvokableFactory::class, 159 Extension\GooglePlayPodcast\Entry::class => InvokableFactory::class, 160 Extension\GooglePlayPodcast\Feed::class => InvokableFactory::class, 161 Extension\GooglePlayPodcast\Renderer\Entry::class => InvokableFactory::class, 162 Extension\GooglePlayPodcast\Renderer\Feed::class => InvokableFactory::class, 163 Extension\ITunes\Entry::class => InvokableFactory::class, 164 Extension\ITunes\Feed::class => InvokableFactory::class, 165 Extension\ITunes\Renderer\Entry::class => InvokableFactory::class, 166 Extension\ITunes\Renderer\Feed::class => InvokableFactory::class, 167 Extension\Slash\Renderer\Entry::class => InvokableFactory::class, 168 Extension\Threading\Renderer\Entry::class => InvokableFactory::class, 169 Extension\WellFormedWeb\Renderer\Entry::class => InvokableFactory::class, 170 // Legacy (v2) due to alias resolution; canonical form of resolved 171 // alias is used to look up the factory, while the non-normalized 172 // resolved alias is used as the requested name passed to the factory. 173 'laminasfeedwriterextensionatomrendererfeed' => InvokableFactory::class, 174 'laminasfeedwriterextensioncontentrendererentry' => InvokableFactory::class, 175 'laminasfeedwriterextensiondublincorerendererentry' => InvokableFactory::class, 176 'laminasfeedwriterextensiondublincorerendererfeed' => InvokableFactory::class, 177 'laminasfeedwriterextensiongoogleplaypodcastentry' => InvokableFactory::class, 178 'laminasfeedwriterextensiongoogleplaypodcastfeed' => InvokableFactory::class, 179 'laminasfeedwriterextensiongoogleplaypodcastrendererentry' => InvokableFactory::class, 180 'laminasfeedwriterextensiongoogleplaypodcastrendererfeed' => InvokableFactory::class, 181 182 'laminasfeedwriterextensionitunesentry' => InvokableFactory::class, 183 'laminasfeedwriterextensionitunesfeed' => InvokableFactory::class, 184 'laminasfeedwriterextensionitunesrendererentry' => InvokableFactory::class, 185 'laminasfeedwriterextensionitunesrendererfeed' => InvokableFactory::class, 186 'laminasfeedwriterextensionslashrendererentry' => InvokableFactory::class, 187 'laminasfeedwriterextensionthreadingrendererentry' => InvokableFactory::class, 188 'laminasfeedwriterextensionwellformedwebrendererentry' => InvokableFactory::class, 189 ]; 190 191 /** 192 * Do not share instances (v2) 193 * 194 * @var bool 195 */ 196 protected $shareByDefault = false; 197 198 /** 199 * Do not share instances (v3) 200 * 201 * @var bool 202 */ 203 protected $sharedByDefault = false; 204 205 /** 206 * Validate the plugin (v3) 207 * 208 * Checks that the extension loaded is of a valid type. 209 * 210 * @param mixed $plugin 211 * @return void 212 * @throws InvalidServiceException if invalid 213 */ 214 public function validate($plugin) 215 { 216 if ($plugin instanceof Extension\AbstractRenderer) { 217 // we're okay 218 return; 219 } 220 221 if ('Feed' === substr(get_class($plugin), -4)) { 222 // we're okay 223 return; 224 } 225 226 if ('Entry' === substr(get_class($plugin), -5)) { 227 // we're okay 228 return; 229 } 230 231 throw new InvalidServiceException(sprintf( 232 'Plugin of type %s is invalid; must implement %s\Extension\RendererInterface ' 233 . 'or the classname must end in "Feed" or "Entry"', 234 is_object($plugin) ? get_class($plugin) : gettype($plugin), 235 __NAMESPACE__ 236 )); 237 } 238 239 /** 240 * Validate plugin (v2) 241 * 242 * @param mixed $plugin 243 * @return void 244 * @throws Exception\InvalidArgumentException when invalid 245 */ 246 public function validatePlugin($plugin) 247 { 248 try { 249 $this->validate($plugin); 250 } catch (InvalidServiceException $e) { 251 throw new Exception\InvalidArgumentException(sprintf( 252 'Plugin of type %s is invalid; must implement %s\Extension\RendererInterface ' 253 . 'or the classname must end in "Feed" or "Entry"', 254 is_object($plugin) ? get_class($plugin) : gettype($plugin), 255 __NAMESPACE__ 256 )); 257 } 258 } 259} 260