pictcode / lib / Cake / View / Helper / RssHelper.php @ 635eef61
履歴 | 表示 | アノテート | ダウンロード (9.271 KB)
| 1 | 635eef61 | spyder1211 | <?php
|
|---|---|---|---|
| 2 | /**
|
||
| 3 | * RSS Helper class file.
|
||
| 4 | *
|
||
| 5 | * Simplifies the output of RSS feeds.
|
||
| 6 | *
|
||
| 7 | * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||
| 8 | * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 9 | *
|
||
| 10 | * Licensed under The MIT License
|
||
| 11 | * For full copyright and license information, please see the LICENSE.txt
|
||
| 12 | * Redistributions of files must retain the above copyright notice.
|
||
| 13 | *
|
||
| 14 | * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 15 | * @link http://cakephp.org CakePHP(tm) Project
|
||
| 16 | * @package Cake.View.Helper
|
||
| 17 | * @since CakePHP(tm) v 1.2
|
||
| 18 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||
| 19 | */
|
||
| 20 | |||
| 21 | App::uses('AppHelper', 'View/Helper'); |
||
| 22 | App::uses('Xml', 'Utility'); |
||
| 23 | |||
| 24 | /**
|
||
| 25 | * RSS Helper class for easy output RSS structures.
|
||
| 26 | *
|
||
| 27 | * @package Cake.View.Helper
|
||
| 28 | * @property TimeHelper $Time
|
||
| 29 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html
|
||
| 30 | */
|
||
| 31 | class RssHelper extends AppHelper { |
||
| 32 | |||
| 33 | /**
|
||
| 34 | * Helpers used by RSS Helper
|
||
| 35 | *
|
||
| 36 | * @var array
|
||
| 37 | */
|
||
| 38 | public $helpers = array('Time'); |
||
| 39 | |||
| 40 | /**
|
||
| 41 | * Base URL
|
||
| 42 | *
|
||
| 43 | * @var string
|
||
| 44 | */
|
||
| 45 | public $base = null; |
||
| 46 | |||
| 47 | /**
|
||
| 48 | * URL to current action.
|
||
| 49 | *
|
||
| 50 | * @var string
|
||
| 51 | */
|
||
| 52 | public $here = null; |
||
| 53 | |||
| 54 | /**
|
||
| 55 | * Parameter array.
|
||
| 56 | *
|
||
| 57 | * @var array
|
||
| 58 | */
|
||
| 59 | public $params = array(); |
||
| 60 | |||
| 61 | /**
|
||
| 62 | * Current action.
|
||
| 63 | *
|
||
| 64 | * @var string
|
||
| 65 | */
|
||
| 66 | public $action = null; |
||
| 67 | |||
| 68 | /**
|
||
| 69 | * POSTed model data
|
||
| 70 | *
|
||
| 71 | * @var array
|
||
| 72 | */
|
||
| 73 | public $data = null; |
||
| 74 | |||
| 75 | /**
|
||
| 76 | * Name of the current model
|
||
| 77 | *
|
||
| 78 | * @var string
|
||
| 79 | */
|
||
| 80 | public $model = null; |
||
| 81 | |||
| 82 | /**
|
||
| 83 | * Name of the current field
|
||
| 84 | *
|
||
| 85 | * @var string
|
||
| 86 | */
|
||
| 87 | public $field = null; |
||
| 88 | |||
| 89 | /**
|
||
| 90 | * Default spec version of generated RSS
|
||
| 91 | *
|
||
| 92 | * @var string
|
||
| 93 | */
|
||
| 94 | public $version = '2.0'; |
||
| 95 | |||
| 96 | /**
|
||
| 97 | * Returns an RSS document wrapped in `<rss />` tags
|
||
| 98 | *
|
||
| 99 | * @param array $attrib `<rss />` tag attributes
|
||
| 100 | * @param string $content Tag content.
|
||
| 101 | * @return string An RSS document
|
||
| 102 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::document
|
||
| 103 | */
|
||
| 104 | public function document($attrib = array(), $content = null) { |
||
| 105 | if ($content === null) { |
||
| 106 | $content = $attrib; |
||
| 107 | $attrib = array(); |
||
| 108 | } |
||
| 109 | if (!isset($attrib['version']) || empty($attrib['version'])) { |
||
| 110 | $attrib['version'] = $this->version; |
||
| 111 | } |
||
| 112 | |||
| 113 | return $this->elem('rss', $attrib, $content); |
||
| 114 | } |
||
| 115 | |||
| 116 | /**
|
||
| 117 | * Returns an RSS `<channel />` element
|
||
| 118 | *
|
||
| 119 | * @param array $attrib `<channel />` tag attributes
|
||
| 120 | * @param array $elements Named array elements which are converted to tags
|
||
| 121 | * @param string $content Content (`<item />`'s belonging to this channel
|
||
| 122 | * @return string An RSS `<channel />`
|
||
| 123 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::channel
|
||
| 124 | */
|
||
| 125 | public function channel($attrib = array(), $elements = array(), $content = null) { |
||
| 126 | if (!isset($elements['link'])) { |
||
| 127 | $elements['link'] = '/'; |
||
| 128 | } |
||
| 129 | if (!isset($elements['title'])) { |
||
| 130 | $elements['title'] = ''; |
||
| 131 | } |
||
| 132 | if (!isset($elements['description'])) { |
||
| 133 | $elements['description'] = ''; |
||
| 134 | } |
||
| 135 | $elements['link'] = $this->url($elements['link'], true); |
||
| 136 | |||
| 137 | $elems = ''; |
||
| 138 | foreach ($elements as $elem => $data) { |
||
| 139 | $attributes = array(); |
||
| 140 | if (is_array($data)) { |
||
| 141 | if (strtolower($elem) === 'cloud') { |
||
| 142 | $attributes = $data; |
||
| 143 | $data = array(); |
||
| 144 | } elseif (isset($data['attrib']) && is_array($data['attrib'])) { |
||
| 145 | $attributes = $data['attrib']; |
||
| 146 | unset($data['attrib']); |
||
| 147 | } else {
|
||
| 148 | $innerElements = ''; |
||
| 149 | foreach ($data as $subElement => $value) { |
||
| 150 | $innerElements .= $this->elem($subElement, array(), $value); |
||
| 151 | } |
||
| 152 | $data = $innerElements; |
||
| 153 | } |
||
| 154 | } |
||
| 155 | $elems .= $this->elem($elem, $attributes, $data); |
||
| 156 | } |
||
| 157 | return $this->elem('channel', $attrib, $elems . $content, !($content === null)); |
||
| 158 | } |
||
| 159 | |||
| 160 | /**
|
||
| 161 | * Transforms an array of data using an optional callback, and maps it to a set
|
||
| 162 | * of `<item />` tags
|
||
| 163 | *
|
||
| 164 | * @param array $items The list of items to be mapped
|
||
| 165 | * @param string|array $callback A string function name, or array containing an object
|
||
| 166 | * and a string method name
|
||
| 167 | * @return string A set of RSS `<item />` elements
|
||
| 168 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::items
|
||
| 169 | */
|
||
| 170 | public function items($items, $callback = null) { |
||
| 171 | if ($callback) { |
||
| 172 | $items = array_map($callback, $items); |
||
| 173 | } |
||
| 174 | |||
| 175 | $out = ''; |
||
| 176 | $c = count($items); |
||
| 177 | |||
| 178 | for ($i = 0; $i < $c; $i++) { |
||
| 179 | $out .= $this->item(array(), $items[$i]); |
||
| 180 | } |
||
| 181 | return $out; |
||
| 182 | } |
||
| 183 | |||
| 184 | /**
|
||
| 185 | * Converts an array into an `<item />` element and its contents
|
||
| 186 | *
|
||
| 187 | * @param array $att The attributes of the `<item />` element
|
||
| 188 | * @param array $elements The list of elements contained in this `<item />`
|
||
| 189 | * @return string An RSS `<item />` element
|
||
| 190 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::item
|
||
| 191 | */
|
||
| 192 | public function item($att = array(), $elements = array()) { |
||
| 193 | $content = null; |
||
| 194 | |||
| 195 | if (isset($elements['link']) && !isset($elements['guid'])) { |
||
| 196 | $elements['guid'] = $elements['link']; |
||
| 197 | } |
||
| 198 | |||
| 199 | foreach ($elements as $key => $val) { |
||
| 200 | $attrib = array(); |
||
| 201 | |||
| 202 | $escape = true; |
||
| 203 | if (is_array($val) && isset($val['convertEntities'])) { |
||
| 204 | $escape = $val['convertEntities']; |
||
| 205 | unset($val['convertEntities']); |
||
| 206 | } |
||
| 207 | |||
| 208 | switch ($key) { |
||
| 209 | case 'pubDate' : |
||
| 210 | $val = $this->time($val); |
||
| 211 | break;
|
||
| 212 | case 'category' : |
||
| 213 | if (is_array($val) && !empty($val[0])) { |
||
| 214 | foreach ($val as $category) { |
||
| 215 | $attrib = array(); |
||
| 216 | if (is_array($category) && isset($category['domain'])) { |
||
| 217 | $attrib['domain'] = $category['domain']; |
||
| 218 | unset($category['domain']); |
||
| 219 | } |
||
| 220 | $categories[] = $this->elem($key, $attrib, $category); |
||
| 221 | } |
||
| 222 | $elements[$key] = implode('', $categories); |
||
| 223 | continue 2; |
||
| 224 | } elseif (is_array($val) && isset($val['domain'])) { |
||
| 225 | $attrib['domain'] = $val['domain']; |
||
| 226 | } |
||
| 227 | break;
|
||
| 228 | case 'link': |
||
| 229 | case 'guid': |
||
| 230 | case 'comments': |
||
| 231 | if (is_array($val) && isset($val['url'])) { |
||
| 232 | $attrib = $val; |
||
| 233 | unset($attrib['url']); |
||
| 234 | $val = $val['url']; |
||
| 235 | } |
||
| 236 | $val = $this->url($val, true); |
||
| 237 | break;
|
||
| 238 | case 'source': |
||
| 239 | if (is_array($val) && isset($val['url'])) { |
||
| 240 | $attrib['url'] = $this->url($val['url'], true); |
||
| 241 | $val = $val['title']; |
||
| 242 | } elseif (is_array($val)) { |
||
| 243 | $attrib['url'] = $this->url($val[0], true); |
||
| 244 | $val = $val[1]; |
||
| 245 | } |
||
| 246 | break;
|
||
| 247 | case 'enclosure': |
||
| 248 | if (is_string($val['url']) && is_file(WWW_ROOT . $val['url']) && file_exists(WWW_ROOT . $val['url'])) { |
||
| 249 | if (!isset($val['length']) && strpos($val['url'], '://') === false) { |
||
| 250 | $val['length'] = sprintf("%u", filesize(WWW_ROOT . $val['url'])); |
||
| 251 | } |
||
| 252 | if (!isset($val['type']) && function_exists('mime_content_type')) { |
||
| 253 | $val['type'] = mime_content_type(WWW_ROOT . $val['url']); |
||
| 254 | } |
||
| 255 | } |
||
| 256 | $val['url'] = $this->url($val['url'], true); |
||
| 257 | $attrib = $val; |
||
| 258 | $val = null; |
||
| 259 | break;
|
||
| 260 | default:
|
||
| 261 | $attrib = $att; |
||
| 262 | } |
||
| 263 | if ($val !== null && $escape) { |
||
| 264 | $val = h($val); |
||
| 265 | } |
||
| 266 | $elements[$key] = $this->elem($key, $attrib, $val); |
||
| 267 | } |
||
| 268 | if (!empty($elements)) { |
||
| 269 | $content = implode('', $elements); |
||
| 270 | } |
||
| 271 | return $this->elem('item', (array)$att, $content, !($content === null)); |
||
| 272 | } |
||
| 273 | |||
| 274 | /**
|
||
| 275 | * Converts a time in any format to an RSS time
|
||
| 276 | *
|
||
| 277 | * @param int|string|DateTime $time UNIX timestamp or valid time string or DateTime object.
|
||
| 278 | * @return string An RSS-formatted timestamp
|
||
| 279 | * @see TimeHelper::toRSS
|
||
| 280 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::time
|
||
| 281 | */
|
||
| 282 | public function time($time) { |
||
| 283 | return $this->Time->toRSS($time); |
||
| 284 | } |
||
| 285 | |||
| 286 | /**
|
||
| 287 | * Generates an XML element
|
||
| 288 | *
|
||
| 289 | * @param string $name The name of the XML element
|
||
| 290 | * @param array $attrib The attributes of the XML element
|
||
| 291 | * @param string|array $content XML element content
|
||
| 292 | * @param bool $endTag Whether the end tag of the element should be printed
|
||
| 293 | * @return string XML
|
||
| 294 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/rss.html#RssHelper::elem
|
||
| 295 | */
|
||
| 296 | public function elem($name, $attrib = array(), $content = null, $endTag = true) { |
||
| 297 | $namespace = null; |
||
| 298 | if (isset($attrib['namespace'])) { |
||
| 299 | $namespace = $attrib['namespace']; |
||
| 300 | unset($attrib['namespace']); |
||
| 301 | } |
||
| 302 | $cdata = false; |
||
| 303 | if (is_array($content) && isset($content['cdata'])) { |
||
| 304 | $cdata = true; |
||
| 305 | unset($content['cdata']); |
||
| 306 | } |
||
| 307 | if (is_array($content) && array_key_exists('value', $content)) { |
||
| 308 | $content = $content['value']; |
||
| 309 | } |
||
| 310 | $children = array(); |
||
| 311 | if (is_array($content)) { |
||
| 312 | $children = $content; |
||
| 313 | $content = null; |
||
| 314 | } |
||
| 315 | |||
| 316 | $xml = '<' . $name; |
||
| 317 | if (!empty($namespace)) { |
||
| 318 | $xml .= ' xmlns'; |
||
| 319 | if (is_array($namespace)) { |
||
| 320 | $xml .= ':' . $namespace['prefix']; |
||
| 321 | $namespace = $namespace['url']; |
||
| 322 | } |
||
| 323 | $xml .= '="' . $namespace . '"'; |
||
| 324 | } |
||
| 325 | $bareName = $name; |
||
| 326 | if (strpos($name, ':') !== false) { |
||
| 327 | list($prefix, $bareName) = explode(':', $name, 2); |
||
| 328 | switch ($prefix) { |
||
| 329 | case 'atom': |
||
| 330 | $xml .= ' xmlns:atom="http://www.w3.org/2005/Atom"'; |
||
| 331 | break;
|
||
| 332 | } |
||
| 333 | } |
||
| 334 | if ($cdata && !empty($content)) { |
||
| 335 | $content = '<![CDATA[' . $content . ']]>'; |
||
| 336 | } |
||
| 337 | $xml .= '>' . $content . '</' . $name . '>'; |
||
| 338 | $elem = Xml::build($xml, array('return' => 'domdocument')); |
||
| 339 | $nodes = $elem->getElementsByTagName($bareName); |
||
| 340 | if ($attrib) { |
||
| 341 | foreach ($attrib as $key => $value) { |
||
| 342 | $nodes->item(0)->setAttribute($key, $value); |
||
| 343 | } |
||
| 344 | } |
||
| 345 | foreach ($children as $child) { |
||
| 346 | $child = $elem->createElement($name, $child); |
||
| 347 | $nodes->item(0)->appendChild($child); |
||
| 348 | } |
||
| 349 | |||
| 350 | $xml = $elem->saveXml(); |
||
| 351 | $xml = trim(substr($xml, strpos($xml, '?>') + 2)); |
||
| 352 | return $xml; |
||
| 353 | } |
||
| 354 | |||
| 355 | } |