[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

title

Body

[close]

/wp-includes/ -> atomlib.php (source)

   1  <?php
   2  /**
   3   * Atom Syndication Format PHP Library
   4   *
   5   * @package AtomLib
   6   * @link http://code.google.com/p/phpatomlib/
   7   *
   8   * @author Elias Torres <elias@torrez.us>
   9   * @version 0.4
  10   * @since 2.3.0
  11   */
  12  
  13  /**
  14   * Structure that store common Atom Feed Properties
  15   *
  16   * @package AtomLib
  17   */
  18  class AtomFeed {
  19      /**
  20       * Stores Links
  21       * @var array
  22       * @access public
  23       */
  24      var $links = array();
  25      /**
  26       * Stores Categories
  27       * @var array
  28       * @access public
  29       */
  30      var $categories = array();
  31      /**
  32       * Stores Entries
  33       *
  34       * @var array
  35       * @access public
  36       */
  37      var $entries = array();
  38  }
  39  
  40  /**
  41   * Structure that store Atom Entry Properties
  42   *
  43   * @package AtomLib
  44   */
  45  class AtomEntry {
  46      /**
  47       * Stores Links
  48       * @var array
  49       * @access public
  50       */
  51      var $links = array();
  52      /**
  53       * Stores Categories
  54       * @var array
  55       * @access public
  56       */
  57      var $categories = array();
  58  }
  59  
  60  /**
  61   * AtomLib Atom Parser API
  62   *
  63   * @package AtomLib
  64   */
  65  class AtomParser {
  66  
  67      var $NS = 'http://www.w3.org/2005/Atom';
  68      var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights');
  69      var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft');
  70  
  71      var $debug = false;
  72  
  73      var $depth = 0;
  74      var $indent = 2;
  75      var $in_content;
  76      var $ns_contexts = array();
  77      var $ns_decls = array();
  78      var $content_ns_decls = array();
  79      var $content_ns_contexts = array();
  80      var $is_xhtml = false;
  81      var $is_html = false;
  82      var $is_text = true;
  83      var $skipped_div = false;
  84  
  85      var $FILE = "php://input";
  86  
  87      var $feed;
  88      var $current;
  89  
  90      /**
  91       * PHP5 constructor.
  92       */
  93      function __construct() {
  94  
  95          $this->feed = new AtomFeed();
  96          $this->current = null;
  97          $this->map_attrs_func = array( __CLASS__, 'map_attrs' );
  98          $this->map_xmlns_func = array( __CLASS__, 'map_xmlns' );
  99      }
 100  
 101      /**
 102       * PHP4 constructor.
 103       */
 104  	public function AtomParser() {
 105          self::__construct();
 106      }
 107  
 108      /**
 109       * Map attributes to key="val"
 110       *
 111       * @param string $k Key
 112       * @param string $v Value
 113       * @return string
 114       */
 115  	public static function map_attrs($k, $v) {
 116          return "$k=\"$v\"";
 117      }
 118  
 119      /**
 120       * Map XML namespace to string.
 121       *
 122       * @param indexish $p XML Namespace element index
 123       * @param array $n Two-element array pair. [ 0 => {namespace}, 1 => {url} ]
 124       * @return string 'xmlns="{url}"' or 'xmlns:{namespace}="{url}"'
 125       */
 126  	public static function map_xmlns($p, $n) {
 127          $xd = "xmlns";
 128          if( 0 < strlen($n[0]) ) {
 129              $xd .= ":{$n[0]}";
 130          }
 131          return "{$xd}=\"{$n[1]}\"";
 132      }
 133  
 134      function _p($msg) {
 135          if($this->debug) {
 136              print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n";
 137          }
 138      }
 139  
 140      function error_handler($log_level, $log_text, $error_file, $error_line) {
 141          $this->error = $log_text;
 142      }
 143  
 144      function parse() {
 145  
 146          set_error_handler(array(&$this, 'error_handler'));
 147  
 148          array_unshift($this->ns_contexts, array());
 149  
 150          if ( ! function_exists( 'xml_parser_create_ns' ) ) {
 151              trigger_error( __( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." ) );
 152              return false;
 153          }
 154  
 155          $parser = xml_parser_create_ns();
 156          xml_set_object($parser, $this);
 157          xml_set_element_handler($parser, "start_element", "end_element");
 158          xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
 159          xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
 160          xml_set_character_data_handler($parser, "cdata");
 161          xml_set_default_handler($parser, "_default");
 162          xml_set_start_namespace_decl_handler($parser, "start_ns");
 163          xml_set_end_namespace_decl_handler($parser, "end_ns");
 164  
 165          $this->content = '';
 166  
 167          $ret = true;
 168  
 169          $fp = fopen($this->FILE, "r");
 170          while ($data = fread($fp, 4096)) {
 171              if($this->debug) $this->content .= $data;
 172  
 173              if(!xml_parse($parser, $data, feof($fp))) {
 174                  /* translators: 1: Error message, 2: Line number. */
 175                  trigger_error(sprintf(__('XML Error: %1$s at line %2$s')."\n",
 176                      xml_error_string(xml_get_error_code($parser)),
 177                      xml_get_current_line_number($parser)));
 178                  $ret = false;
 179                  break;
 180              }
 181          }
 182          fclose($fp);
 183  
 184          xml_parser_free($parser);
 185  
 186          restore_error_handler();
 187  
 188          return $ret;
 189      }
 190  
 191      function start_element($parser, $name, $attrs) {
 192  
 193          $tag = array_pop(explode(":", $name));
 194  
 195          switch($name) {
 196              case $this->NS . ':feed':
 197                  $this->current = $this->feed;
 198                  break;
 199              case $this->NS . ':entry':
 200                  $this->current = new AtomEntry();
 201                  break;
 202          };
 203  
 204          $this->_p("start_element('$name')");
 205          #$this->_p(print_r($this->ns_contexts,true));
 206          #$this->_p('current(' . $this->current . ')');
 207  
 208          array_unshift($this->ns_contexts, $this->ns_decls);
 209  
 210          $this->depth++;
 211  
 212          if(!empty($this->in_content)) {
 213  
 214              $this->content_ns_decls = array();
 215  
 216              if($this->is_html || $this->is_text)
 217                  trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup.");
 218  
 219              $attrs_prefix = array();
 220  
 221              // resolve prefixes for attributes
 222              foreach($attrs as $key => $value) {
 223                  $with_prefix = $this->ns_to_prefix($key, true);
 224                  $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value);
 225              }
 226  
 227              $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix)));
 228              if(strlen($attrs_str) > 0) {
 229                  $attrs_str = " " . $attrs_str;
 230              }
 231  
 232              $with_prefix = $this->ns_to_prefix($name);
 233  
 234              if(!$this->is_declared_content_ns($with_prefix[0])) {
 235                  array_push($this->content_ns_decls, $with_prefix[0]);
 236              }
 237  
 238              $xmlns_str = '';
 239              if(count($this->content_ns_decls) > 0) {
 240                  array_unshift($this->content_ns_contexts, $this->content_ns_decls);
 241                  $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0])));
 242                  if(strlen($xmlns_str) > 0) {
 243                      $xmlns_str = " " . $xmlns_str;
 244                  }
 245              }
 246  
 247              array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">"));
 248  
 249          } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) {
 250              $this->in_content = array();
 251              $this->is_xhtml = $attrs['type'] == 'xhtml';
 252              $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html';
 253              $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text';
 254              $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type']));
 255  
 256              if(in_array('src',array_keys($attrs))) {
 257                  $this->current->$tag = $attrs;
 258              } else {
 259                  array_push($this->in_content, array($tag,$this->depth, $type));
 260              }
 261          } else if($tag == 'link') {
 262              array_push($this->current->links, $attrs);
 263          } else if($tag == 'category') {
 264              array_push($this->current->categories, $attrs);
 265          }
 266  
 267          $this->ns_decls = array();
 268      }
 269  
 270      function end_element($parser, $name) {
 271  
 272          $tag = array_pop(explode(":", $name));
 273  
 274          $ccount = count($this->in_content);
 275  
 276          # if we are *in* content, then let's proceed to serialize it
 277          if(!empty($this->in_content)) {
 278              # if we are ending the original content element
 279              # then let's finalize the content
 280              if($this->in_content[0][0] == $tag &&
 281                  $this->in_content[0][1] == $this->depth) {
 282                  $origtype = $this->in_content[0][2];
 283                  array_shift($this->in_content);
 284                  $newcontent = array();
 285                  foreach($this->in_content as $c) {
 286                      if(count($c) == 3) {
 287                          array_push($newcontent, $c[2]);
 288                      } else {
 289                          if($this->is_xhtml || $this->is_text) {
 290                              array_push($newcontent, $this->xml_escape($c));
 291                          } else {
 292                              array_push($newcontent, $c);
 293                          }
 294                      }
 295                  }
 296                  if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) {
 297                      $this->current->$tag = array($origtype, join('',$newcontent));
 298                  } else {
 299                      $this->current->$tag = join('',$newcontent);
 300                  }
 301                  $this->in_content = array();
 302              } else if($this->in_content[$ccount-1][0] == $tag &&
 303                  $this->in_content[$ccount-1][1] == $this->depth) {
 304                  $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>";
 305              } else {
 306                  # else, just finalize the current element's content
 307                  $endtag = $this->ns_to_prefix($name);
 308                  array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>"));
 309              }
 310          }
 311  
 312          array_shift($this->ns_contexts);
 313  
 314          $this->depth--;
 315  
 316          if($name == ($this->NS . ':entry')) {
 317              array_push($this->feed->entries, $this->current);
 318              $this->current = null;
 319          }
 320  
 321          $this->_p("end_element('$name')");
 322      }
 323  
 324      function start_ns($parser, $prefix, $uri) {
 325          $this->_p("starting: " . $prefix . ":" . $uri);
 326          array_push($this->ns_decls, array($prefix,$uri));
 327      }
 328  
 329      function end_ns($parser, $prefix) {
 330          $this->_p("ending: #" . $prefix . "#");
 331      }
 332  
 333      function cdata($parser, $data) {
 334          $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#");
 335          if(!empty($this->in_content)) {
 336              array_push($this->in_content, $data);
 337          }
 338      }
 339  
 340      function _default($parser, $data) {
 341          # when does this gets called?
 342      }
 343  
 344  
 345      function ns_to_prefix($qname, $attr=false) {
 346          # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div')
 347          $components = explode(":", $qname);
 348  
 349          # grab the last one (e.g 'div')
 350          $name = array_pop($components);
 351  
 352          if(!empty($components)) {
 353              # re-join back the namespace component
 354              $ns = join(":",$components);
 355              foreach($this->ns_contexts as $context) {
 356                  foreach($context as $mapping) {
 357                      if($mapping[1] == $ns && strlen($mapping[0]) > 0) {
 358                          return array($mapping, "$mapping[0]:$name");
 359                      }
 360                  }
 361              }
 362          }
 363  
 364          if($attr) {
 365              return array(null, $name);
 366          } else {
 367              foreach($this->ns_contexts as $context) {
 368                  foreach($context as $mapping) {
 369                      if(strlen($mapping[0]) == 0) {
 370                          return array($mapping, $name);
 371                      }
 372                  }
 373              }
 374          }
 375      }
 376  
 377      function is_declared_content_ns($new_mapping) {
 378          foreach($this->content_ns_contexts as $context) {
 379              foreach($context as $mapping) {
 380                  if($new_mapping == $mapping) {
 381                      return true;
 382                  }
 383              }
 384          }
 385          return false;
 386      }
 387  
 388      function xml_escape($string)
 389      {
 390               return str_replace(array('&','"',"'",'<','>'),
 391                  array('&amp;','&quot;','&apos;','&lt;','&gt;'),
 392                  $string );
 393      }
 394  }


Generated: Sat Nov 23 20:47:33 2019 Cross-referenced by PHPXref 0.7