[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/src/includes/admin/converters/ -> Drupal7.php (source)

   1  <?php
   2  
   3  /**
   4   * bbPress Drupal7 Converter
   5   *
   6   * @package bbPress
   7   * @subpackage Converters
   8   */
   9  
  10  /**
  11   * Implementation of Drupal v7.x Forum converter.
  12   *
  13   * @since 2.5.0 bbPress (r5138)
  14   *
  15   * @link Codex Docs https://codex.bbpress.org/import-forums/drupal
  16   */
  17  class Drupal7 extends BBP_Converter_Base {
  18  
  19      /**
  20       * Main Constructor
  21       */
  22  	public function __construct() {
  23          parent::__construct();
  24      }
  25  
  26      /**
  27       * Sets up the field mappings
  28       */
  29  	public function setup_globals() {
  30  
  31          /** Forum Section *****************************************************/
  32  
  33          // Old forum id (Stored in postmeta)
  34          $this->field_map[] = array(
  35              'from_tablename' => 'taxonomy_term_data',
  36              'from_fieldname' => 'tid',
  37              'to_type'        => 'forum',
  38              'to_fieldname'   => '_bbp_old_forum_id'
  39          );
  40  
  41          // Forum parent id (If no parent, then 0, Stored in postmeta)
  42          $this->field_map[] = array(
  43              'from_tablename'  => 'taxonomy_term_hierarchy',
  44              'from_fieldname'  => 'parent',
  45              'join_tablename'  => 'taxonomy_term_data',
  46              'join_type'       => 'INNER',
  47              'join_expression' => 'USING (tid)',
  48              'from_expression' => 'LEFT JOIN taxonomy_vocabulary AS taxonomy_vocabulary USING (vid) WHERE module = "forum"',
  49              'to_type'         => 'forum',
  50              'to_fieldname'    => '_bbp_old_forum_parent_id'
  51          );
  52  
  53          // Forum title.
  54          $this->field_map[] = array(
  55              'from_tablename' => 'taxonomy_term_data',
  56              'from_fieldname' => 'name',
  57              'to_type'        => 'forum',
  58              'to_fieldname'   => 'post_title'
  59          );
  60  
  61          // Forum slug (Clean name to avoid conflicts)
  62          $this->field_map[] = array(
  63              'from_tablename'  => 'taxonomy_term_data',
  64              'from_fieldname'  => 'name',
  65              'to_type'         => 'forum',
  66              'to_fieldname'    => 'post_name',
  67              'callback_method' => 'callback_slug'
  68          );
  69  
  70          // Forum description.
  71          $this->field_map[] = array(
  72              'from_tablename'  => 'taxonomy_term_data',
  73              'from_fieldname'  => 'description',
  74              'to_type'         => 'forum',
  75              'to_fieldname'    => 'post_content',
  76              'callback_method' => 'callback_null'
  77          );
  78  
  79          // Forum display order (Starts from 1)
  80          $this->field_map[] = array(
  81              'from_tablename' => 'taxonomy_term_data',
  82              'from_fieldname' => 'weight',
  83              'to_type'        => 'forum',
  84              'to_fieldname'   => 'menu_order'
  85          );
  86  
  87          // Forum type (Set a default value 'forum', Stored in postmeta)
  88          $this->field_map[] = array(
  89              'to_type'      => 'forum',
  90              'to_fieldname' => '_bbp_forum_type',
  91              'default'      => 'forum'
  92          );
  93  
  94          // Forum status (Set a default value 'open', Stored in postmeta)
  95          $this->field_map[] = array(
  96              'to_type'      => 'forum',
  97              'to_fieldname' => '_bbp_status',
  98              'default'      => 'open'
  99          );
 100  
 101          // Forum dates.
 102          $this->field_map[] = array(
 103              'to_type'      => 'forum',
 104              'to_fieldname' => 'post_date',
 105              'default'      => date('Y-m-d H:i:s')
 106          );
 107          $this->field_map[] = array(
 108              'to_type'      => 'forum',
 109              'to_fieldname' => 'post_date_gmt',
 110              'default'      => date('Y-m-d H:i:s')
 111          );
 112          $this->field_map[] = array(
 113              'to_type'      => 'forum',
 114              'to_fieldname' => 'post_modified',
 115              'default'      => date('Y-m-d H:i:s')
 116          );
 117          $this->field_map[] = array(
 118              'to_type'      => 'forum',
 119              'to_fieldname' => 'post_modified_gmt',
 120              'default'      => date('Y-m-d H:i:s')
 121          );
 122  
 123          /** Topic Section *****************************************************/
 124  
 125          // Old topic id (Stored in postmeta)
 126          $this->field_map[] = array(
 127              'from_tablename' => 'forum_index',
 128              'from_fieldname' => 'nid',
 129              'to_type'        => 'topic',
 130              'to_fieldname'   => '_bbp_old_topic_id'
 131          );
 132  
 133          // Topic reply count (Stored in postmeta)
 134          $this->field_map[] = array(
 135              'from_tablename'  => 'forum_index',
 136              'from_fieldname'  => 'comment_count',
 137              'to_type'         => 'topic',
 138              'to_fieldname'    => '_bbp_reply_count',
 139              'callback_method' => 'callback_topic_reply_count'
 140          );
 141  
 142          // Topic total reply count (Includes unpublished replies, Stored in postmeta)
 143          $this->field_map[] = array(
 144              'from_tablename'  => 'forum_index',
 145              'from_fieldname'  => 'comment_count',
 146              'to_type'         => 'topic',
 147              'to_fieldname'    => '_bbp_total_reply_count',
 148              'callback_method' => 'callback_topic_reply_count'
 149          );
 150  
 151          // Topic parent forum id (If no parent, then 0. Stored in postmeta)
 152          $this->field_map[] = array(
 153              'from_tablename'  => 'forum_index',
 154              'from_fieldname'  => 'tid',
 155              'to_type'         => 'topic',
 156              'to_fieldname'    => '_bbp_forum_id',
 157              'callback_method' => 'callback_forumid'
 158          );
 159  
 160          // Topic author.
 161          // Note: We join the 'node' table because 'forum_index' table does not include author id.
 162          $this->field_map[] = array(
 163              'from_tablename'  => 'node',
 164              'from_fieldname'  => 'uid',
 165              'join_tablename'  => 'forum_index',
 166              'join_type'       => 'INNER',
 167              'join_expression' => 'ON node.nid = forum_index.nid',
 168              'to_type'         => 'topic',
 169              'to_fieldname'    => 'post_author',
 170              'callback_method' => 'callback_userid'
 171          );
 172  
 173          // Topic author name (Stored in postmeta as _bbp_anonymous_name)
 174          $this->field_map[] = array(
 175              'to_type'      => 'topic',
 176              'to_fieldname' => '_bbp_old_topic_author_name_id',
 177              'default'      => 'Anonymous'
 178          );
 179  
 180          // Is the topic anonymous (Stored in postmeta)
 181          $this->field_map[] = array(
 182              'from_tablename'  => 'node',
 183              'from_fieldname'  => 'uid',
 184              'join_tablename'  => 'forum_index',
 185              'join_type'       => 'INNER',
 186              'join_expression' => 'ON node.nid = forum_index.nid',
 187              'to_type'         => 'topic',
 188              'to_fieldname'    => '_bbp_old_is_topic_anonymous_id',
 189              'callback_method' => 'callback_check_anonymous'
 190          );
 191  
 192          // Topic content.
 193          // Note: We join the 'field_data_body' table because 'node' or 'forum_index' table does not include topic content.
 194          $this->field_map[] = array(
 195              'from_tablename'  => 'field_data_body',
 196              'from_fieldname'  => 'body_value',
 197              'join_tablename'  => 'node',
 198              'join_type'       => 'INNER',
 199              'join_expression' => 'ON field_data_body.revision_id = node.vid',
 200              'to_type'         => 'topic',
 201              'to_fieldname'    => 'post_content',
 202              'callback_method' => 'callback_html'
 203          );
 204  
 205          // Topic title.
 206          $this->field_map[] = array(
 207              'from_tablename' => 'forum_index',
 208              'from_fieldname' => 'title',
 209              'to_type'        => 'topic',
 210              'to_fieldname'   => 'post_title'
 211          );
 212  
 213          // Topic slug (Clean name to avoid conflicts)
 214          $this->field_map[] = array(
 215              'from_tablename'  => 'forum_index',
 216              'from_fieldname'  => 'title',
 217              'to_type'         => 'topic',
 218              'to_fieldname'    => 'post_name',
 219              'callback_method' => 'callback_slug'
 220          );
 221  
 222          // Topic parent forum id (If no parent, then 0)
 223          $this->field_map[] = array(
 224              'from_tablename'  => 'forum_index',
 225              'from_fieldname'  => 'tid',
 226              'to_type'         => 'topic',
 227              'to_fieldname'    => 'post_parent',
 228              'callback_method' => 'callback_forumid'
 229          );
 230  
 231          // Topic status (Publish or Unpublished, Drupal v7.x publish = 1, pending = 0)
 232          $this->field_map[] = array(
 233              'from_tablename'  => 'node',
 234              'from_fieldname'  => 'status',
 235              'join_tablename'  => 'forum_index',
 236              'join_type'       => 'INNER',
 237              'join_expression' => 'ON node.nid = forum_index.nid',
 238              'to_type'         => 'topic',
 239              'to_fieldname'    => 'post_status',
 240              'callback_method' => 'callback_status'
 241          );
 242  
 243          // Sticky status (Stored in postmeta)
 244          $this->field_map[] = array(
 245              'from_tablename'  => 'forum_index',
 246              'from_fieldname'  => 'sticky',
 247              'to_type'         => 'topic',
 248              'to_fieldname'    => '_bbp_old_sticky_status_id',
 249              'callback_method' => 'callback_sticky_status'
 250          );
 251  
 252          // Topic dates.
 253          $this->field_map[] = array(
 254              'from_tablename'  => 'forum_index',
 255              'from_fieldname'  => 'created',
 256              'to_type'         => 'topic',
 257              'to_fieldname'    => 'post_date',
 258              'callback_method' => 'callback_datetime'
 259          );
 260          $this->field_map[] = array(
 261              'from_tablename'  => 'forum_index',
 262              'from_fieldname'  => 'created',
 263              'to_type'         => 'topic',
 264              'to_fieldname'    => 'post_date_gmt',
 265              'callback_method' => 'callback_datetime'
 266          );
 267          $this->field_map[] = array(
 268              'from_tablename'  => 'forum_index',
 269              'from_fieldname'  => 'last_comment_timestamp',
 270              'to_type'         => 'topic',
 271              'to_fieldname'    => 'post_modified',
 272              'callback_method' => 'callback_datetime'
 273          );
 274          $this->field_map[] = array(
 275              'from_tablename'  => 'forum_index',
 276              'from_fieldname'  => 'last_comment_timestamp',
 277              'to_type'         => 'topic',
 278              'to_fieldname'    => 'post_modified_gmt',
 279              'callback_method' => 'callback_datetime'
 280          );
 281          $this->field_map[] = array(
 282              'from_tablename'  => 'forum_index',
 283              'from_fieldname'  => 'last_comment_timestamp',
 284              'to_type'         => 'topic',
 285              'to_fieldname'    => '_bbp_last_active_time',
 286              'callback_method' => 'callback_datetime'
 287          );
 288  
 289          // Topic status (Drupal v7.x Comments Enabled no = 0, closed = 1 & open = 2)
 290          $this->field_map[] = array(
 291              'from_tablename'  => 'node',
 292              'from_fieldname'  => 'comment',
 293              'join_tablename'  => 'forum_index',
 294              'join_type'       => 'INNER',
 295              'join_expression' => 'ON node.nid = forum_index.nid',
 296              'to_type'         => 'topic',
 297              'to_fieldname'    => '_bbp_old_closed_status_id',
 298              'callback_method' => 'callback_topic_status'
 299          );
 300  
 301          /** Tags Section ******************************************************/
 302  
 303          // Topic id.
 304          $this->field_map[] = array(
 305              'from_tablename'  => 'field_data_field_tags',
 306              'from_fieldname'  => 'entity_id',
 307              'to_type'         => 'tags',
 308              'to_fieldname'    => 'objectid',
 309              'callback_method' => 'callback_topicid'
 310          );
 311  
 312          // Taxonomy ID.
 313          $this->field_map[] = array(
 314              'from_tablename'  => 'field_data_field_tags',
 315              'from_fieldname'  => 'field_tags_tid',
 316              'to_type'         => 'tags',
 317              'to_fieldname'    => 'taxonomy'
 318          );
 319  
 320          // Term name.
 321          $this->field_map[] = array(
 322              'from_tablename'  => 'taxonomy_term_data',
 323              'from_fieldname'  => 'name',
 324              'join_tablename'  => 'field_data_field_tags',
 325              'join_type'       => 'INNER',
 326              'join_expression' => 'ON field_tags_tid = taxonomy_term_data.tid',
 327              'to_type'         => 'tags',
 328              'to_fieldname'    => 'name'
 329          );
 330  
 331          // Term slug.
 332          $this->field_map[] = array(
 333              'from_tablename'  => 'taxonomy_term_data',
 334              'from_fieldname'  => 'name',
 335              'join_tablename'  => 'field_data_field_tags',
 336              'join_type'       => 'INNER',
 337              'join_expression' => 'ON field_tags_tid = taxonomy_term_data.tid',
 338              'to_type'         => 'tags',
 339              'to_fieldname'    => 'slug',
 340              'callback_method' => 'callback_slug'
 341          );
 342  
 343          // Term description.
 344          $this->field_map[] = array(
 345              'from_tablename'  => 'taxonomy_term_data',
 346              'from_fieldname'  => 'description',
 347              'join_tablename'  => 'field_data_field_tags',
 348              'join_type'       => 'INNER',
 349              'join_expression' => 'ON field_tags_tid = taxonomy_term_data.tid',
 350              'to_type'         => 'tags',
 351              'to_fieldname'    => 'description'
 352          );
 353  
 354          /** Reply Section *****************************************************/
 355  
 356          // Old reply id (Stored in postmeta)
 357          $this->field_map[] = array(
 358              'from_tablename' => 'comment',
 359              'from_fieldname' => 'cid',
 360              'to_type'        => 'reply',
 361              'to_fieldname'   => '_bbp_old_reply_id'
 362          );
 363  
 364          // Reply parent forum id (If no parent, then 0. Stored in postmeta)
 365          $this->field_map[] = array(
 366              'from_tablename'  => 'comment',
 367              'from_fieldname'  => 'nid',
 368              'to_type'         => 'reply',
 369              'to_fieldname'    => '_bbp_forum_id',
 370              'callback_method' => 'callback_topicid_to_forumid'
 371          );
 372  
 373          // Reply parent topic id (If no parent, then 0. Stored in postmeta)
 374          $this->field_map[] = array(
 375              'from_tablename'  => 'comment',
 376              'from_fieldname'  => 'nid',
 377              'to_type'         => 'reply',
 378              'to_fieldname'    => '_bbp_topic_id',
 379              'callback_method' => 'callback_topicid'
 380          );
 381  
 382          // Reply parent reply id (If no parent, then 0. Stored in postmeta)
 383          $this->field_map[] = array(
 384              'from_tablename'  => 'comment',
 385              'from_fieldname'  => 'pid',
 386              'to_type'         => 'reply',
 387              'to_fieldname'    => '_bbp_old_reply_to_id'
 388          );
 389  
 390          // Reply author ip (Stored in postmeta)
 391          $this->field_map[] = array(
 392              'from_tablename' => 'comment',
 393              'from_fieldname' => 'hostname',
 394              'to_type'        => 'reply',
 395              'to_fieldname'   => '_bbp_author_ip'
 396          );
 397  
 398          // Reply author.
 399          $this->field_map[] = array(
 400              'from_tablename'  => 'comment',
 401              'from_fieldname'  => 'uid',
 402              'to_type'         => 'reply',
 403              'to_fieldname'    => 'post_author',
 404              'callback_method' => 'callback_userid'
 405          );
 406  
 407          // Reply status (Publish or Unpublished, Drupal v7.x publish = 1, pending = 0)
 408          $this->field_map[] = array(
 409              'from_tablename'  => 'comment',
 410              'from_fieldname'  => 'status',
 411              'to_type'         => 'reply',
 412              'to_fieldname'    => 'post_status',
 413              'callback_method' => 'callback_status'
 414          );
 415  
 416          // Reply author name (Stored in postmeta as _bbp_anonymous_name)
 417          $this->field_map[] = array(
 418              'from_tablename' => 'comment',
 419              'from_fieldname' => 'name',
 420              'to_type'        => 'reply',
 421              'to_fieldname'   => '_bbp_old_reply_author_name_id'
 422          );
 423  
 424          // Is the reply anonymous  (Stored in postmeta)
 425          $this->field_map[] = array(
 426              'from_tablename'  => 'comment',
 427              'from_fieldname'  => 'uid',
 428              'to_type'         => 'reply',
 429              'to_fieldname'    => '_bbp_old_is_reply_anonymous_id',
 430              'callback_method' => 'callback_check_anonymous'
 431          );
 432  
 433          // Reply content.
 434          // Note: We join the 'field_data_comment_body' table because 'comment' table does not include reply content.
 435          $this->field_map[] = array(
 436              'from_tablename'  => 'field_data_comment_body',
 437              'from_fieldname'  => 'comment_body_value',
 438              'join_tablename'  => 'comment',
 439              'join_type'       => 'INNER',
 440              'join_expression' => 'ON field_data_comment_body.entity_id = comment.cid',
 441              'to_type'         => 'reply',
 442              'to_fieldname'    => 'post_content',
 443              'callback_method' => 'callback_html'
 444          );
 445  
 446          // Reply parent topic id (If no parent, then 0)
 447          $this->field_map[] = array(
 448              'from_tablename'  => 'comment',
 449              'from_fieldname'  => 'nid',
 450              'to_type'         => 'reply',
 451              'to_fieldname'    => 'post_parent',
 452              'callback_method' => 'callback_topicid'
 453          );
 454  
 455          // Reply dates.
 456          $this->field_map[] = array(
 457              'from_tablename'  => 'comment',
 458              'from_fieldname'  => 'created',
 459              'to_type'         => 'reply',
 460              'to_fieldname'    => 'post_date',
 461              'callback_method' => 'callback_datetime'
 462          );
 463          $this->field_map[] = array(
 464              'from_tablename'  => 'comment',
 465              'from_fieldname'  => 'created',
 466              'to_type'         => 'reply',
 467              'to_fieldname'    => 'post_date_gmt',
 468              'callback_method' => 'callback_datetime'
 469          );
 470          $this->field_map[] = array(
 471              'from_tablename'  => 'comment',
 472              'from_fieldname'  => 'changed',
 473              'to_type'         => 'reply',
 474              'to_fieldname'    => 'post_modified',
 475              'callback_method' => 'callback_datetime'
 476          );
 477          $this->field_map[] = array(
 478              'from_tablename'  => 'comment',
 479              'from_fieldname'  => 'changed',
 480              'to_type'         => 'reply',
 481              'to_fieldname'    => 'post_modified_gmt',
 482              'callback_method' => 'callback_datetime'
 483          );
 484  
 485          /** User Section ******************************************************/
 486  
 487          // Store old user id (Stored in usermeta)
 488          // Don't import user uid = 0, this is Drupal 7's guest user
 489          $this->field_map[] = array(
 490              'from_tablename'  => 'users',
 491              'from_fieldname'  => 'uid',
 492              'from_expression' => 'WHERE uid != 0',
 493              'to_type'         => 'user',
 494              'to_fieldname'    => '_bbp_old_user_id'
 495          );
 496  
 497          // Store old user password (Stored in usermeta serialized with salt)
 498          $this->field_map[] = array(
 499              'from_tablename'  => 'users',
 500              'from_fieldname'  => 'pass',
 501              'to_type'         => 'user',
 502              'to_fieldname'    => '_bbp_password'
 503  //            'callback_method' => 'callback_savepass'
 504          );
 505  
 506          // Store old user salt (This is only used for the SELECT row info for the above password save)
 507          $this->field_map[] = array(
 508              'from_tablename' => 'users',
 509              'from_fieldname' => 'pass',
 510              'to_type'        => 'user',
 511              'to_fieldname'   => ''
 512          );
 513  
 514          // User password verify class (Stored in usermeta for verifying password)
 515          $this->field_map[] = array(
 516              'to_type'      => 'users',
 517              'to_fieldname' => '_bbp_class',
 518              'default'      => 'Drupal7'
 519          );
 520  
 521          // User name.
 522          $this->field_map[] = array(
 523              'from_tablename' => 'users',
 524              'from_fieldname' => 'name',
 525              'to_type'        => 'user',
 526              'to_fieldname'   => 'user_login'
 527          );
 528  
 529          // User nice name.
 530          $this->field_map[] = array(
 531              'from_tablename' => 'users',
 532              'from_fieldname' => 'name',
 533              'to_type'        => 'user',
 534              'to_fieldname'   => 'user_nicename'
 535          );
 536  
 537          // User email.
 538          $this->field_map[] = array(
 539              'from_tablename' => 'users',
 540              'from_fieldname' => 'mail',
 541              'to_type'        => 'user',
 542              'to_fieldname'   => 'user_email'
 543          );
 544  
 545          // User registered.
 546          $this->field_map[] = array(
 547              'from_tablename'  => 'users',
 548              'from_fieldname'  => 'created',
 549              'to_type'         => 'user',
 550              'to_fieldname'    => 'user_registered',
 551              'callback_method' => 'callback_datetime'
 552          );
 553  
 554          // Store Signature (Stored in usermeta)
 555          $this->field_map[] = array(
 556              'from_tablename'  => 'users',
 557              'from_fieldname'  => 'signature',
 558              'to_fieldname'    => '_bbp_drupal7_user_sig',
 559              'to_type'         => 'user',
 560              'callback_method' => 'callback_html'
 561          );
 562      }
 563  
 564      /**
 565       * This method allows us to indicates what is or is not converted for each
 566       * converter.
 567       */
 568  	public function info() {
 569          return '';
 570      }
 571  
 572      /**
 573       * This method is to save the salt and password together.  That
 574       * way when we authenticate it we can get it out of the database
 575       * as one value. Array values are auto sanitized by WordPress.
 576       */
 577  	public function callback_savepass( $field, $row ) {
 578          $pass_array = array( 'hash' => $field, 'salt' => $row['salt'] );
 579          return $pass_array;
 580      }
 581  
 582      /**
 583       * This method is to take the pass out of the database and compare
 584       * to a pass the user has typed in.
 585       */
 586  	public function authenticate_pass( $password, $serialized_pass ) {
 587          $pass_array = unserialize( $serialized_pass );
 588          return ( $pass_array['hash'] == md5( md5( $password ). $pass_array['salt'] ) );
 589      }
 590  
 591      /**
 592       * Translate the post status from Drupal v7.x numerics to WordPress's
 593       * strings.
 594       *
 595       * @param int $status Drupal v7.x numeric post status
 596       * @return string WordPress safe
 597       */
 598  	public function callback_status( $status = 1 ) {
 599          switch ( $status ) {
 600              case 0 :
 601                  $status = 'pending'; // bbp_get_pending_status_id()
 602                  break;
 603  
 604              case 1  :
 605              default :
 606                  $status = 'publish'; // bbp_get_public_status_id()
 607                  break;
 608          }
 609          return $status;
 610      }
 611  
 612      /**
 613       * Translate the post status from Drupal v7.x numerics to WordPress's strings.
 614       *
 615       * @param int $status Drupal v7.x numeric topic status
 616       * @return string WordPress safe
 617       */
 618  	public function callback_topic_status( $status = 2 ) {
 619          switch ( $status ) {
 620              case 1 :
 621                  $status = 'closed';
 622                  break;
 623  
 624              case 2  :
 625              default :
 626                  $status = 'publish';
 627                  break;
 628          }
 629          return $status;
 630      }
 631  
 632      /**
 633       * Translate the topic sticky status type from Drupal v7.x numerics to WordPress's strings.
 634       *
 635       * @param int $status Drupal v7.x numeric forum type
 636       * @return string WordPress safe
 637       */
 638  	public function callback_sticky_status( $status = 0 ) {
 639          switch ( $status ) {
 640              case 1 :
 641                  $status = 'sticky'; // Drupal Sticky 'topic_sticky = 1'
 642                  break;
 643  
 644              case 0  :
 645              default :
 646                  $status = 'normal'; // Drupal Normal Topic 'sticky = 0'
 647                  break;
 648          }
 649          return $status;
 650      }
 651  
 652      /**
 653       * Verify the topic/reply count.
 654       *
 655       * @param int $count Drupal v7.x topic/reply counts
 656       * @return string WordPress safe
 657       */
 658  	public function callback_topic_reply_count( $count = 1 ) {
 659          $count = absint( (int) $count - 1 );
 660          return $count;
 661      }
 662  }


Generated: Sat May 4 01:01:00 2024 Cross-referenced by PHPXref 0.7.1