PageRenderTime 61ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/code/cake/app/webroot/cp/wp-content/plugins/commentpress-core/commentpress-core/class_commentpress_nav.php

https://github.com/DigitalPaulScholtenProject/DPSP-Platform
PHP | 1413 lines | 351 code | 602 blank | 460 comment | 78 complexity | 17f423ffe6126c0d8c66fb5f84627cfe MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php /*
  2. ================================================================================
  3. Class CommentpressCoreNavigator
  4. ================================================================================
  5. AUTHOR: Christian Wach <needle@haystack.co.uk>
  6. --------------------------------------------------------------------------------
  7. NOTES
  8. =====
  9. This class is a wrapper for navigating pages in whatever hierarchy
  10. or relationship they have been assigned
  11. --------------------------------------------------------------------------------
  12. */
  13. /*
  14. ================================================================================
  15. Class Name
  16. ================================================================================
  17. */
  18. class CommentpressCoreNavigator {
  19. /*
  20. ============================================================================
  21. Properties
  22. ============================================================================
  23. */
  24. // parent object reference
  25. var $parent_obj;
  26. // next pages array
  27. var $next_pages = array();
  28. // previous pages array
  29. var $previous_pages = array();
  30. // next posts array
  31. var $next_posts = array();
  32. // previous posts array
  33. var $previous_posts = array();
  34. // page numbers array
  35. var $page_numbers = array();
  36. /**
  37. * @description: initialises this object
  38. * @param object $parent_obj a reference to the parent object
  39. * @return object
  40. * @todo:
  41. *
  42. */
  43. function __construct( $parent_obj ) {
  44. // store reference to parent
  45. $this->parent_obj = $parent_obj;
  46. // init
  47. $this->_init();
  48. // --<
  49. return $this;
  50. }
  51. /**
  52. * @description: PHP 4 constructor
  53. */
  54. function CommentpressCoreNavigator( $parent_obj ) {
  55. // is this php5?
  56. if ( version_compare( PHP_VERSION, "5.0.0", "<" ) ) {
  57. // call php5 constructor
  58. $this->__construct( $parent_obj );
  59. }
  60. // --<
  61. return $this;
  62. }
  63. /**
  64. * @description: set up all items associated with this object
  65. * @todo:
  66. *
  67. */
  68. function initialise() {
  69. // init page lists
  70. $this->_init_page_lists();
  71. // init posts lists
  72. $this->_init_posts_lists();
  73. }
  74. /**
  75. * @description: if needed, destroys all items associated with this object
  76. * @todo:
  77. *
  78. */
  79. function destroy() {
  80. }
  81. //##############################################################################
  82. /*
  83. ============================================================================
  84. PUBLIC METHODS
  85. ============================================================================
  86. */
  87. /**
  88. * @description: get next page link
  89. * @param boolean $with_comments requested page has comments - default false
  90. * @return object $page_data if successful, boolean false if not
  91. * @todo:
  92. *
  93. */
  94. function get_next_page( $with_comments = false ) {
  95. // do we have any next pages?
  96. if ( count( $this->next_pages ) > 0 ) {
  97. // are we asking for comments?
  98. if ( $with_comments ) {
  99. // loop
  100. foreach( $this->next_pages AS $next_page ) {
  101. // does it have comments?
  102. if ( $next_page->comment_count > 0 ) {
  103. // --<
  104. return $next_page;
  105. }
  106. }
  107. } else {
  108. // --<
  109. return $this->next_pages[0];
  110. }
  111. }
  112. // --<
  113. return false;
  114. }
  115. /**
  116. * @description: get previous page link
  117. * @param boolean $with_comments requested page has comments - default false
  118. * @return object $page_data if successful, boolean false if not
  119. * @todo:
  120. *
  121. */
  122. function get_previous_page( $with_comments = false ) {
  123. // do we have any previous pages?
  124. if ( count( $this->previous_pages ) > 0 ) {
  125. // are we asking for comments?
  126. if ( $with_comments ) {
  127. // loop
  128. foreach( $this->previous_pages AS $previous_page ) {
  129. // does it have comments?
  130. if ( $previous_page->comment_count > 0 ) {
  131. // --<
  132. return $previous_page;
  133. }
  134. }
  135. } else {
  136. // --<
  137. return $this->previous_pages[0];
  138. }
  139. }
  140. // --<
  141. return false;
  142. }
  143. /**
  144. * @description: get next post link
  145. * @param boolean $with_comments requested post has comments - default false
  146. * @return object $post_data if successful, boolean false if not
  147. * @todo:
  148. *
  149. */
  150. function get_next_post( $with_comments = false ) {
  151. // do we have any next posts?
  152. if ( count( $this->next_posts ) > 0 ) {
  153. // are we asking for comments?
  154. if ( $with_comments ) {
  155. // loop
  156. foreach( $this->next_posts AS $next_post ) {
  157. // does it have comments?
  158. if ( $next_post->comment_count > 0 ) {
  159. // --<
  160. return $next_post;
  161. }
  162. }
  163. } else {
  164. // --<
  165. return $this->next_posts[0];
  166. }
  167. }
  168. // --<
  169. return false;
  170. }
  171. /**
  172. * @description: get previous post link
  173. * @param boolean $with_comments requested post has comments - default false
  174. * @return object $post_data if successful, boolean false if not
  175. * @todo:
  176. *
  177. */
  178. function get_previous_post( $with_comments = false ) {
  179. // do we have any previous posts?
  180. if ( count( $this->previous_posts ) > 0 ) {
  181. // are we asking for comments?
  182. if ( $with_comments ) {
  183. // loop
  184. foreach( $this->previous_posts AS $previous_post ) {
  185. // does it have comments?
  186. if ( $previous_post->comment_count > 0 ) {
  187. // --<
  188. return $previous_post;
  189. }
  190. }
  191. } else {
  192. // --<
  193. return $this->previous_posts[0];
  194. }
  195. }
  196. // --<
  197. return false;
  198. }
  199. /**
  200. * @description: get first viewable child page
  201. * @param integer $page_id the page ID
  202. * @return integer $first_child ID of the first child page (or false if not found)
  203. * @todo:
  204. *
  205. */
  206. function get_first_child( $page_id ) {
  207. // init to look for published pages
  208. $defaults = array(
  209. 'post_parent' => $page_id,
  210. 'post_type' => 'page',
  211. 'numberposts' => -1,
  212. 'post_status' => 'publish',
  213. 'orderby' => 'menu_order',
  214. 'order' => 'ASC'
  215. );
  216. // get page children
  217. $kids =& get_children( $defaults );
  218. // do we have any?
  219. if ( empty( $kids ) ) {
  220. // no children
  221. return false;
  222. }
  223. // we got some...
  224. return $this->_get_first_child( $kids );
  225. }
  226. /**
  227. * @description: get list of 'book' pages
  228. * @param string $mode either 'structural' or 'readable'
  229. * @return array $pages all 'book' pages
  230. * @todo:
  231. *
  232. */
  233. function get_book_pages( $mode = 'readable' ) {
  234. // init
  235. $all_pages = array();
  236. // do we have a nav menu enabled?
  237. if ( has_nav_menu( 'toc' ) ) {
  238. // YES - a custom menu disables "book" navigation
  239. // --<
  240. return $all_pages;
  241. /*
  242. // -----------------------------------------------------------------
  243. // For posterity: here's what I considered when trying to tease out
  244. // page lists from menu items. However, menus can contain anything,
  245. // including external links, so the effort to parse the menu doesn't
  246. // seem to be worthwhile.
  247. // -----------------------------------------------------------------
  248. // check menu locations
  249. if ( ( $locations = get_nav_menu_locations() ) AND isset( $locations[ $menu_name ] ) ) {
  250. // get the menu object
  251. $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
  252. // default args for reference
  253. $args = array(
  254. 'order' => 'ASC',
  255. 'orderby' => 'menu_order',
  256. 'post_type' => 'nav_menu_item',
  257. 'post_status' => 'publish',
  258. 'output' => ARRAY_A,
  259. 'output_key' => 'menu_order',
  260. 'nopaging' => true,
  261. 'update_post_term_cache' => false
  262. );
  263. // get the page references
  264. $menu_items = wp_get_nav_menu_items( $menu->term_id, $args );
  265. // init
  266. $pages_to_get = array();
  267. // if we get some
  268. if ( $menu_items ) {
  269. // convert to array of pages
  270. foreach ( $menu_items AS $menu_item ) {
  271. // is it a WP item?
  272. if ( isset( $menu_item->object_id ) ) {
  273. // construct array of WP pages in menu
  274. $pages_to_get[] = $menu_item->object_id;
  275. }
  276. }
  277. print_r( array( 'menu_items' => $menu_items, 'pages_to_get' => $pages_to_get ) ); die();
  278. // set list pages defaults
  279. $defaults = array(
  280. 'child_of' => 0,
  281. 'sort_order' => 'ASC',
  282. 'sort_column' => 'menu_order, post_title',
  283. 'hierarchical' => 1,
  284. 'exclude' => '',
  285. 'include' => implode( ',', $pages_to_get ),
  286. 'meta_key' => '',
  287. 'meta_value' => '',
  288. 'authors' => '',
  289. 'parent' => -1,
  290. 'exclude_tree' => ''
  291. );
  292. // get them
  293. $all_pages = get_pages( $defaults );
  294. }
  295. }
  296. */
  297. } else {
  298. // -----------------------------------------------------------------
  299. // construct "book" navigation based on pages
  300. // -----------------------------------------------------------------
  301. // default to no excludes
  302. $excludes = '';
  303. // get special pages
  304. $special_pages = $this->parent_obj->db->option_get( 'cp_special_pages' );
  305. // are we in a BuddyPress scenario?
  306. if ( $this->parent_obj->is_buddypress() ) {
  307. // BuddyPress creates its own registration page at /register and
  308. // redirects ordinary WP registration page requests to it. It also
  309. // seems to exclude it from wp_list_pages(), see: $cp->display->list_pages()
  310. // check if registration is allowed
  311. if ( '1' == get_option('users_can_register') AND is_main_site() ) {
  312. // find the registration page by its slug
  313. $reg_page = get_page_by_path( 'register' );
  314. // did we get one?
  315. if ( is_object( $reg_page ) AND isset( $reg_page->ID ) ) {
  316. // yes - exclude it as well
  317. $special_pages[] = $reg_page->ID;
  318. }
  319. }
  320. }
  321. // are there any?
  322. if ( is_array( $special_pages ) AND count( $special_pages ) > 0 ) {
  323. // format them for the exclude param
  324. $excludes = implode( ',', $special_pages );
  325. }
  326. // set list pages defaults
  327. $defaults = array(
  328. 'child_of' => 0,
  329. 'sort_order' => 'ASC',
  330. 'sort_column' => 'menu_order, post_title',
  331. 'hierarchical' => 1,
  332. 'exclude' => $excludes,
  333. 'include' => '',
  334. 'meta_key' => '',
  335. 'meta_value' => '',
  336. 'authors' => '',
  337. 'parent' => -1,
  338. 'exclude_tree' => ''
  339. );
  340. // get them
  341. $all_pages = get_pages( $defaults );
  342. // if we have any pages...
  343. if ( count( $all_pages ) > 0 ) {
  344. // if chapters are not pages...
  345. if ( $this->parent_obj->db->option_get( 'cp_toc_chapter_is_page' ) != '1' ) {
  346. // do we want all readable pages?
  347. if ( $mode == 'readable' ) {
  348. // filter chapters out
  349. $all_pages = $this->_filter_chapters( $all_pages );
  350. }
  351. }
  352. // if Theme My Login is present...
  353. if ( defined( 'TML_ABSPATH' ) ) {
  354. // filter its page out
  355. $all_pages = $this->_filter_theme_my_login_page( $all_pages );
  356. }
  357. }
  358. } // end check for custom menu
  359. //print_r( $all_pages ); die();
  360. // --<
  361. return $all_pages;
  362. }
  363. /**
  364. * @description: get first readable 'book' page
  365. * @return integer $id ID of the first page (or false if not found)
  366. * @todo:
  367. *
  368. */
  369. function get_first_page() {
  370. // init
  371. $id = false;
  372. // get all pages including chapters
  373. $all_pages = $this->get_book_pages( 'structural' );
  374. // if we have any pages...
  375. if ( count( $all_pages ) > 0 ) {
  376. // get first id
  377. $id = $all_pages[0]->ID;
  378. }
  379. // --<
  380. return $id;
  381. }
  382. /**
  383. * @description: get page number
  384. * @param integer $page_id the page ID
  385. * @return integer $number number of the page
  386. * @todo:
  387. *
  388. */
  389. function get_page_number( $page_id ) {
  390. // init
  391. $num = 0;
  392. // access post
  393. global $post;
  394. // are parent pages viewable?
  395. $viewable = ( $this->parent_obj->db->option_get( 'cp_toc_chapter_is_page' ) == '1' ) ? true : false;
  396. // if they are...
  397. if ( $viewable ) {
  398. // get page number from array
  399. $num = $this->_get_page_number( $page_id );
  400. } else {
  401. // get id of first viewable child
  402. $first_child = $this->get_first_child( $post->ID );
  403. // if this is a childless page
  404. if ( !$first_child ) {
  405. // get page number from array
  406. $num = $this->_get_page_number( $page_id );
  407. }
  408. }
  409. // --<
  410. return $num;
  411. }
  412. /**
  413. * @description: get page number
  414. * @param integer $page_id the page ID
  415. * @return integer $number number of the page
  416. * @todo:
  417. *
  418. */
  419. function _get_page_number( $page_id ) {
  420. // init
  421. $num = 0;
  422. // get from array
  423. if ( array_key_exists( $page_id, $this->page_numbers ) ) {
  424. // get it
  425. $num = $this->page_numbers[ $page_id ];
  426. }
  427. // --<
  428. return $num;
  429. }
  430. /**
  431. * @description: redirect to child
  432. * @todo:
  433. *
  434. */
  435. function redirect_to_child() {
  436. // only on pages
  437. if ( !is_page() ) { return; }
  438. // access post object
  439. global $post;
  440. // do we have one?
  441. if ( !is_object( $post ) ) {
  442. // --<
  443. die( 'no post object' );
  444. }
  445. // are parent pages viewable?
  446. $viewable = ( $this->parent_obj->db->option_get( 'cp_toc_chapter_is_page' ) == '1' ) ? true : false;
  447. // get id of first child
  448. $first_child = $this->get_first_child( $post->ID );
  449. // our conditions
  450. if ( $first_child AND !$viewable ) {
  451. // get link
  452. $redirect = get_permalink( $first_child );
  453. // do the redirect
  454. //header( "HTTP/1.1 301 Moved Permanently" );
  455. header( "Location: $redirect" );
  456. }
  457. }
  458. //##############################################################################
  459. /*
  460. ============================================================================
  461. PRIVATE METHODS
  462. ============================================================================
  463. */
  464. /**
  465. * @description: object initialisation
  466. * @todo:
  467. *
  468. */
  469. function _init() {
  470. // is_page() and is_single() are not yet defined, so we init this object when
  471. // wp_head() is fired - see initialise() above
  472. }
  473. /**
  474. * @description: set up page list
  475. * @todo:
  476. *
  477. */
  478. function _init_page_lists() {
  479. // if we're navigating pages
  480. if( is_page() ) {
  481. // get all pages
  482. $all_pages = $this->get_book_pages( 'readable' );
  483. // if we have any pages...
  484. if ( count( $all_pages ) > 0 ) {
  485. // generate page numbers
  486. $this->_generate_page_numbers( $all_pages );
  487. // access post object
  488. global $post;
  489. // init the key we want
  490. $page_key = false;
  491. // loop
  492. foreach( $all_pages AS $key => $page_obj ) {
  493. // is it the currently viewed page?
  494. if ( $page_obj->ID == $post->ID ) {
  495. // set page key
  496. $page_key = $key;
  497. // kick out to preserve key
  498. break;
  499. }
  500. }
  501. // if we don't get a key...
  502. if ( $page_key === false ) {
  503. // the current page is a chapter and is not a page
  504. $this->next_pages = array();
  505. // --<
  506. return;
  507. }
  508. // will there be a next array?
  509. if ( isset( $all_pages[$key + 1] ) ) {
  510. // get all subsequent pages
  511. $this->next_pages = array_slice( $all_pages, $key + 1 );
  512. }
  513. // will there be a previous array?
  514. if ( isset( $all_pages[$key - 1] ) ) {
  515. // get all previous pages
  516. $this->previous_pages = array_reverse( array_slice( $all_pages, 0, $key ) );
  517. }
  518. } // end have array check
  519. } // end is_page() check
  520. }
  521. /**
  522. * @description: set up posts list
  523. * @todo:
  524. *
  525. */
  526. function _init_posts_lists() {
  527. // if we're navigating posts
  528. if( is_single() ) {
  529. // set defaults
  530. $defaults = array(
  531. 'numberposts' => -1,
  532. 'orderby' => 'date'
  533. );
  534. // get them
  535. $all_posts = get_posts( $defaults );
  536. // if we have any posts...
  537. if ( count( $all_posts ) > 0 ) {
  538. // access post object
  539. global $post;
  540. // loop
  541. foreach( $all_posts AS $key => $post_obj ) {
  542. // is it ours?
  543. if ( $post_obj->ID == $post->ID ) {
  544. // kick out to preserve key
  545. break;
  546. }
  547. }
  548. // will there be a next array?
  549. if ( isset( $all_posts[$key + 1] ) ) {
  550. // get all subsequent posts
  551. $this->next_posts = array_slice( $all_posts, $key + 1 );
  552. }
  553. // will there be a previous array?
  554. if ( isset( $all_posts[$key - 1] ) ) {
  555. // get all previous posts
  556. $this->previous_posts = array_reverse( array_slice( $all_posts, 0, $key ) );
  557. }
  558. } // end have array check
  559. } // end is_single() check
  560. }
  561. /**
  562. * @description: strip out all but lowest level pages
  563. * @param array $pages array of page objects
  564. * @return array $subpages all subpages
  565. * @todo: this only works one level deep?
  566. *
  567. */
  568. function _filter_chapters( $pages ) {
  569. // init return
  570. $subpages = array();
  571. // if we have any...
  572. if ( count( $pages ) > 0 ) {
  573. // loop
  574. foreach( $pages AS $key => $page_obj ) {
  575. // init to look for published pages
  576. $defaults = array(
  577. 'post_parent' => $page_obj->ID,
  578. 'post_type' => 'page',
  579. 'numberposts' => -1,
  580. 'post_status' => 'publish'
  581. );
  582. // get page children
  583. $kids =& get_children( $defaults );
  584. // do we have any?
  585. if ( empty( $kids ) ) {
  586. // add to our return array
  587. $subpages[] = $page_obj;
  588. }
  589. }
  590. } // end have array check
  591. // --<
  592. return $subpages;
  593. }
  594. /**
  595. * @description: get first published child, however deep
  596. * @param array $pages array of page objects
  597. * @return array $subpages all subpages
  598. * @todo:
  599. *
  600. */
  601. function _get_first_child( $pages ) {
  602. // if we have any...
  603. if ( count( $pages ) > 0 ) {
  604. // loop
  605. foreach( $pages AS $key => $page_obj ) {
  606. // init to look for published pages
  607. $defaults = array(
  608. 'post_parent' => $page_obj->ID,
  609. 'post_type' => 'page',
  610. 'numberposts' => -1,
  611. 'post_status' => 'publish',
  612. 'orderby' => 'menu_order',
  613. 'order' => 'ASC'
  614. //sort_column=menu_order,post_title
  615. );
  616. // get page children
  617. $kids =& get_children( $defaults );
  618. // do we have any?
  619. if ( !empty( $kids ) ) {
  620. // go deeper
  621. return $this->_get_first_child( $kids );
  622. } else {
  623. // return first
  624. return $page_obj->ID;
  625. }
  626. }
  627. } // end have array check
  628. // --<
  629. return false;
  630. }
  631. /**
  632. * @description: generates page numbers
  633. * @param array $pages array of page objects in the 'book'
  634. * @todo: refine by section, page meta value etc
  635. *
  636. */
  637. function _generate_page_numbers( $pages ) {
  638. // if we have any...
  639. if ( count( $pages ) > 0 ) {
  640. // init with page 1
  641. $num = 1;
  642. // loop
  643. foreach( $pages AS $page_obj ) {
  644. // get number format... the way this works in publications is that
  645. // only prefaces are numbered with roman numerals. So, we only allow
  646. // the first top level page to have the option of roman numerals.
  647. // if set, all child pages will be set to roman.
  648. // once we run out of roman numerals, $num is reset to 1
  649. // default to arabic
  650. $format = 'arabic';
  651. // set key
  652. $key = '_cp_number_format';
  653. // if the custom field already has a value...
  654. if ( get_post_meta( $page_obj->ID, $key, true ) !== '' ) {
  655. // get it
  656. $format = get_post_meta( $page_obj->ID, $key, true );
  657. } else {
  658. // get top level parent
  659. $top_page_id = $this->_get_top_parent_id( $page_obj->ID );
  660. // if the custom field has a value...
  661. if ( get_post_meta( $top_page_id, $key, true ) !== '' ) {
  662. // get it
  663. $format = get_post_meta( $top_page_id, $key, true );
  664. }
  665. }
  666. // if it's roman
  667. if ( $format == 'roman' ) {
  668. // convert arabic to roman
  669. $this->page_numbers[ $page_obj->ID ] = $this->_number_to_roman( $num );
  670. } else {
  671. // if flag not set
  672. if ( !isset( $flag ) ) {
  673. // reset num
  674. $num = 1;
  675. // set flag
  676. $flag = true;
  677. }
  678. // store roman
  679. $this->page_numbers[ $page_obj->ID ] = $num;
  680. }
  681. // increment
  682. $num++;
  683. }
  684. //print_r( $this->page_numbers ); die();
  685. }
  686. }
  687. /**
  688. * @description: utility to remove the Theme My Login page
  689. * @return boolean $success
  690. * @todo: pass the array
  691. *
  692. */
  693. function _filter_theme_my_login_page( $pages ) {
  694. // init return
  695. $clean = array();
  696. // if we have any...
  697. if ( count( $pages ) > 0 ) {
  698. // loop
  699. foreach( $pages AS $page_obj ) {
  700. // do we have any?
  701. if ( !$this->_detect_login_page( $page_obj ) ) {
  702. // add to our return array
  703. $clean[] = $page_obj;
  704. }
  705. }
  706. } // end have array check
  707. // --<
  708. return $clean;
  709. }
  710. /**
  711. * @description: utility to detect the Theme My Login page
  712. * @return boolean $success
  713. * @todo:
  714. *
  715. */
  716. function _detect_login_page( $page_obj ) {
  717. // compat with Theme My Login
  718. if(
  719. $page_obj->post_name == 'login' AND
  720. $page_obj->post_content == '[theme-my-login]'
  721. ) {
  722. // --<
  723. return true;
  724. }
  725. // --<
  726. return false;
  727. }
  728. /**
  729. * PHP Roman Numeral Library
  730. *
  731. * Copyright (c) 2008, reusablecode.blogspot.com; some rights reserved.
  732. *
  733. * This work is licensed under the Creative Commons Attribution License. To view
  734. * a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or
  735. * send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California
  736. * 94305, USA.
  737. *
  738. * @description: utility to convert arabic to roman numerals
  739. * @return boolean $result the roman equivalent
  740. * @todo:
  741. *
  742. */
  743. function _number_to_roman( $arabic ) {
  744. $ones = array("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX");
  745. $tens = array("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC");
  746. $hundreds = array("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM");
  747. $thousands = array("", "M", "MM", "MMM", "MMMM");
  748. if ( $arabic > 4999 ) {
  749. // For large numbers (five thousand and above), a bar is placed above a base numeral to indicate multiplication by 1000.
  750. // Since it is not possible to illustrate this in plain ASCII, this function will refuse to convert numbers above 4999.
  751. die("Cannot represent numbers larger than 4999 in plain ASCII.");
  752. } elseif ( $arabic == 0 ) {
  753. // About 725, Bede or one of his colleagues used the letter N, the initial of nullae,
  754. // in a table of epacts, all written in Roman numerals, to indicate zero.
  755. return "N";
  756. } else {
  757. $roman = $thousands[($arabic - fmod($arabic, 1000)) / 1000];
  758. $arabic = fmod($arabic, 1000);
  759. $roman .= $hundreds[($arabic - fmod($arabic, 100)) / 100];
  760. $arabic = fmod($arabic, 100);
  761. $roman .= $tens[($arabic - fmod($arabic, 10)) / 10];
  762. $arabic = fmod($arabic, 10);
  763. $roman .= $ones[($arabic - fmod($arabic, 1)) / 1];
  764. $arabic = fmod($arabic, 1);
  765. return $roman;
  766. }
  767. }
  768. /**
  769. * @description: get top parent page id
  770. * @param integer $post_id the queried page id
  771. * @return integer $post_id
  772. * @todo:
  773. *
  774. */
  775. function _get_top_parent_id( $post_id ){
  776. // get page data
  777. $_page = get_page( $post_id );
  778. // is the top page?
  779. if ( $_page->post_parent == 0 ) {
  780. // yes -> return the id
  781. return $_page->ID;
  782. } else {
  783. // no -> recurse upwards
  784. return $this->_get_top_parent_id( $_page->post_parent );
  785. }
  786. }
  787. //##############################################################################
  788. } // class ends
  789. ?>