wiki
[ class tree: wiki ] [ index: wiki ] [ all elements ]

Source for file BitPage.php

Documentation is available at BitPage.php

  1. <?php
  2. /**
  3.  * @package wiki
  4.  * @author spider <spider@steelsun.com>
  5.  *
  6.  *  Copyright (c) 2004 bitweaver.org
  7.  *  Copyright (c) 2003 tikwiki.org
  8.  *  Copyright (c) 2002-2003, Luis Argerich, Garland Foster, Eduardo Polidor, et. al.
  9.  *  All Rights Reserved. See below for details and a complete list of authors.
  10.  *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
  11.  */
  12.  
  13. /**
  14.  * required setup
  15.  */
  16. require_once( LIBERTY_PKG_PATH.'LibertyMime.php' );
  17.  
  18. /**
  19.  * @package wiki
  20.  */
  21. class BitPage extends LibertyMime {
  22.     var $mPageId;
  23.     var $mPageName;
  24.  
  25.     function BitPage( $pPageId=NULL, $pContentId=NULL ) {
  26.         parent::__construct();
  27.         $this->registerContentType( BITPAGE_CONTENT_TYPE_GUID, array(
  28.                 'content_type_guid' => BITPAGE_CONTENT_TYPE_GUID,
  29.                 'content_name' => 'Wiki Page',
  30.                 'handler_class' => 'BitPage',
  31.                 'handler_package' => 'wiki',
  32.                 'handler_file' => 'BitPage.php',
  33.                 'maintainer_url' => 'http://www.bitweaver.org'
  34.             ) );
  35.         $this->mPageId = (int)$pPageId;
  36.         $this->mContentId = (int)$pContentId;
  37.         $this->mContentTypeGuid = BITPAGE_CONTENT_TYPE_GUID;
  38.  
  39.         // Permission setup
  40.         $this->mViewContentPerm  = 'p_wiki_view_page';
  41.         $this->mCreateContentPerm = 'p_wiki_create_page';
  42.         $this->mUpdateContentPerm  = 'p_wiki_update_page';
  43.         $this->mAdminContentPerm = 'p_wiki_admin';
  44.     }
  45.  
  46.     public static function findContentIdByPageId( $pPageId ) {
  47.         global $gBitDb;
  48.         $ret = NULL;
  49.         if( BitBase::verifyId( $pPageId ) ) {
  50.             $ret = $gBitDb->getOne( "SELECT `content_id` FROM `".BIT_DB_PREFIX."wiki_pages` WHERE `page_id`=?", array( (int)$pPageId ) );
  51.         }
  52.         return $ret;
  53.     }
  54.  
  55.     function findByPageName( $pPageName, $pUserId=NULL ) {
  56.         $userWhere = '';
  57.         $bindVars = array( $pPageName, $this->mContentTypeGuid );
  58.         if( @BitBase::verifyId( $pUserId ) ) {
  59.             $userWhere = " AND lc.`user_id`=?";
  60.             array_push( $bindVars, $pUserId );
  61.         }
  62.         $ret = $this->mDb->getOne("select `page_id` from `".BIT_DB_PREFIX."wiki_pages` wp INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`) where lc.`title`=? AND lc.`content_type_guid`=? $userWhere", $bindVars );
  63.         return $ret;
  64.     }
  65.  
  66.     /**
  67.      * Determines if a wiki page (row in wiki_pages) exists, and returns a hash of important info. If N pages exists with $pPageName, returned existsHash has a row for each unique pPageName row.
  68.      * @param pPageName name of the wiki page
  69.      * @param pCaseSensitive look for case sensitive names
  70.      * @param pContentId if you insert the content id of the currently viewed content, non-existing links can be created immediately
  71.      */
  72.     public static function pageExists( $pPageName, $pCaseSensitive=FALSE, $pContentId=NULL ) {
  73.         global $gBitSystem;
  74.         $ret = NULL;
  75.  
  76.         if( $gBitSystem->isPackageActive( 'wiki' ) ) {
  77.             $columnExpression = $gBitSystem->mDb->getCaseLessColumn('lc.title');
  78.  
  79.             $pageWhere = $pCaseSensitive ? 'lc.`title`' : $columnExpression;
  80.             $bindVars = array( ($pCaseSensitive ? $pPageName : strtoupper( $pPageName ) ) );
  81.             $query = "SELECT `page_id`, wp.`content_id`, lcds.`data` AS `summary`, lc.`last_modified`, lc.`title`
  82.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  83.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=wp.`content_id`)
  84.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_data` lcds ON (lc.`content_id` = lcds.`content_id` AND lcds.`data_type`='summary')
  85.                 WHERE $pageWhere = ?";
  86.             if( !$ret = $gBitSystem->mDb->getAll( $query, $bindVars ) ) {
  87.                 $query = "SELECT `page_id`, wp.`content_id`, lcds.`data` AS `summary`, lc.`last_modified`, lc.`title`, lal.`alias_title`
  88.                     FROM `".BIT_DB_PREFIX."wiki_pages` wp
  89.                         INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=wp.`content_id`)
  90.                         INNER JOIN `".BIT_DB_PREFIX."liberty_aliases` lal ON (lc.`content_id`=lal.`content_id`)
  91.                         LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_data` lcds ON (lc.`content_id` = lcds.`content_id` AND lcds.`data_type`='summary')
  92.                     WHERE ".$gBitSystem->mDb->getCaseLessColumn('lal.alias_title')." = ?";
  93.                 $ret = $gBitSystem->mDb->getAll( $query, $bindVars );
  94.             }
  95.         }
  96.         return $ret;
  97.     }
  98.  
  99.     /**
  100.      * load
  101.      *
  102.      * @access public
  103.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  104.      */
  105.     function load( $pContentId=NULL, $pPluginParams = TRUE ) {
  106.         if( $this->verifyId( $this->mPageId ) || $this->verifyId( $this->mContentId ) ) {
  107.             global $gBitSystem;
  108.  
  109.             $lookupColumn = @BitBase::verifyId( $this->mPageId ) ? 'page_id' : 'content_id';
  110.             $parse = ( !isset( $pPluginParams['parse'] ) or $pPluginParams['parse'] ) ? true : false;
  111.             $bindVars = array(); $selectSql = ''; $joinSql = ''; $whereSql = '';
  112.             array_push( $bindVars, $lookupId = @BitBase::verifyId( $this->mPageId )? $this->mPageId : $this->mContentId );
  113.             $this->getServicesSql( 'content_load_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
  114.  
  115.             $query = "
  116.                 SELECT wp.*, lc.*, lcds.`data` AS `summary`,
  117.                 uue.`login` AS modifier_user, uue.`real_name` AS modifier_real_name,
  118.                 uuc.`login` AS creator_user, uuc.`real_name` AS creator_real_name $selectSql
  119.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  120.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`) $joinSql
  121.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_data` lcds ON (lc.`content_id` = lcds.`content_id` AND lcds.`data_type`='summary')
  122.                     LEFT JOIN `".BIT_DB_PREFIX."users_users` uue ON (uue.`user_id` = lc.`modifier_user_id`)
  123.                     LEFT JOIN `".BIT_DB_PREFIX."users_users` uuc ON (uuc.`user_id` = lc.`user_id`)
  124.                 WHERE wp.`$lookupColumn`=? $whereSql";
  125.             if( $this->mInfo = $this->mDb->getRow( $query, $bindVars ) ) {
  126.                 $this->mContentId = $this->mInfo['content_id'];
  127.                 $this->mPageId = $this->mInfo['page_id'];
  128.                 $this->mPageName = $this->mInfo['title'];
  129.                 $this->mInfo['display_url'] = $this->getDisplayUrl( $this->mPageName );
  130.  
  131.                 // TODO: this is a bad habbit and should not be done BitUser::getDisplayName sorts out what name to display
  132.                 $this->mInfo['creator'] = (isset( $this->mInfo['creator_real_name'] ) ? $this->mInfo['creator_real_name'] : $this->mInfo['creator_user'] );
  133.                 $this->mInfo['editor'] = (isset( $this->mInfo['modifier_real_name'] ) ? $this->mInfo['modifier_real_name'] : $this->mInfo['modifier_user'] );
  134.  
  135.                 // Save some work if wiki_attachments are not active
  136.                 // get prefs before we parse the data that we know how to parse the data
  137.                 if( $gBitSystem->isFeatureActive( 'wiki_attachments' ) ) {
  138.                     LibertyMime::load();
  139.                 } else {
  140.                     LibertyContent::load();
  141.                 }
  142.  
  143.                 if ( $parse ) {
  144.                     $this->mInfo['parsed_data'] = $this->parseData();
  145.                 }
  146.             } else {
  147.                 $this->mPageId = NULL;
  148.             }
  149.         }
  150.         return( count( $this->mInfo ) );
  151.     }
  152.  
  153.     /**
  154.     * This is the ONLY method that should be called in order to store (create or update) a wiki page!
  155.     * It is very smart and will figure out what to do for you. It should be considered a black box.
  156.     *
  157.     * @param array pParams hash of values that will be used to store the page
  158.     *
  159.     * @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
  160.     *
  161.     * @access public
  162.     ***/
  163.     function store( &$pParamHash ) {
  164.         $this->mDb->StartTrans();
  165.  
  166.         if( $this->verify( $pParamHash ) && LibertyMime::store( $pParamHash ) ) {
  167.             $pParamHash['page_store']['wiki_page_size'] = !empty( $pParamHash['edit'] ) ? strlen( $pParamHash['edit'] ) : 0;
  168.  
  169.             $table = BIT_DB_PREFIX."wiki_pages";
  170.             if( $this->verifyId( $this->mPageId ) ) {
  171.                 $result = $this->mDb->associateUpdate( $table, $pParamHash['page_store'], array( "page_id" => $this->mPageId ) );
  172.             } else {
  173.                 $pParamHash['page_store']['content_id'] = $pParamHash['content_id'];
  174.                 if( @$this->verifyId( $pParamHash['page_id'] ) ) {
  175.                     // if pParamHash['page_id'] is set, some is requesting a particular page_id. Use with caution!
  176.                     $pParamHash['page_store']['page_id'] = $pParamHash['page_id'];
  177.                 } else {
  178.                     $pParamHash['page_store']['page_id'] = $this->mDb->GenID( 'wiki_pages_page_id_seq');
  179.                 }
  180.                 $this->mPageId = $pParamHash['page_store']['page_id'];
  181.  
  182.                 $result = $this->mDb->associateInsert( $table, $pParamHash['page_store'] );
  183.             }
  184.             // Access new data for notifications
  185.             $this->load();
  186.  
  187.             if( isset( $mailEvents ) ) {
  188.                 global $notificationlib, $gBitUser, $gBitSystem, $gBitSmarty;
  189.                 include_once( KERNEL_PKG_PATH.'notification_lib.php' );
  190.                 $notificationlib->post_content_event($this->mContentId, $this->mInfo['content_type_guid'], 'wiki', $this->mInfo['title'], $this->mInfo['modifier_user'], $this->mInfo['edit_comment'], $this->mInfo['data']);
  191.  
  192.                 if( $gBitSystem->isFeatureActive( 'users_watches') ) {
  193.                     $nots = $gBitUser->get_event_watches( 'wiki_page_changed', $this->mPageId );
  194.  
  195.                     foreach ($nots as $not) {
  196. #                        if ($wiki_watch_editor != 'y' && $not['user_id'] == $user)
  197. #                            break;
  198.                         $gBitSmarty->assign('mail_site', $_SERVER["SERVER_NAME"]);
  199.  
  200.                         $gBitSmarty->assign('mail_page', $this->mInfo['title']);
  201.                         $gBitSmarty->assign('mail_date', $gBitSystem->getUTCTime());
  202.                         $gBitSmarty->assign('mail_user', $this->mInfo['modifier_user']);
  203.                         $gBitSmarty->assign('mail_comment', $this->mInfo['edit_comment']);
  204.                         $gBitSmarty->assign('mail_last_version', $this->mInfo['version'] - 1);
  205.                         $gBitSmarty->assign('mail_data', $this->mInfo['data']);
  206.                         $gBitSmarty->assign('mail_hash', $not['hash']);
  207.                         $foo = parse_url($_SERVER["REQUEST_URI"]);
  208.                         $machine = httpPrefix();
  209.                         $gBitSmarty->assign('mail_machine', $machine);
  210.                         $parts = explode('/', $foo['path']);
  211.  
  212.                         if (count($parts) > 1)
  213.                             unset ($parts[count($parts) - 1]);
  214.  
  215.                         $gBitSmarty->assign('mail_machine_raw', httpPrefix(). implode('/', $parts));
  216.                         $gBitSmarty->assign('mail_pagedata', $this->mInfo['data']);
  217.                         $mail_data = $gBitSmarty->fetch('bitpackage:wiki/user_watch_wiki_page_changed.tpl');
  218.                         $email_to = $not['email'];
  219.                         @mail($email_to, tra('Wiki page'). ' ' . $this->mInfo['title'] . ' ' . tra('changed'), $mail_data, "From: ".$gBitSystem->getConfig( 'site_sender_email' )."\r\nContent-type: text/plain;charset=utf-8\r\n");
  220.                     }
  221.                 }
  222.             }
  223.         }
  224.         $this->mDb->CompleteTrans();
  225.         return( count( $this->mErrors ) == 0 );
  226.     }
  227.  
  228.     /**
  229.     * verify This function is responsible for data integrity and validation before any operations are performed with the $pParamHash
  230.     * NOTE: This is a PRIVATE METHOD!!!! do not call outside this class, under penalty of death!
  231.     *
  232.     * @param array pParams reference to hash of values that will be used to store the page, they will be modified where necessary
  233.     *
  234.     * @return bool TRUE on success, FALSE if verify failed. If FALSE, $this->mErrors will have reason why
  235.     *
  236.     * @access private
  237.     ***/
  238.     function verify( &$pParamHash ) {
  239.         global $gBitUser, $gBitSystem;
  240.  
  241.         // make sure we're all loaded up of we have a mPageId
  242.         if( $this->verifyId( $this->mPageId ) && empty( $this->mInfo ) ) {
  243.             $this->load();
  244.         }
  245.  
  246.         if( isset( $this->mInfo['content_id'] ) && $this->verifyId( $this->mInfo['content_id'] ) ) {
  247.             $pParamHash['content_id'] = $this->mInfo['content_id'];
  248.         }
  249.  
  250.         // It is possible a derived class set this to something different
  251.         if( empty( $pParamHash['content_type_guid'] ) ) {
  252.             $pParamHash['content_type_guid'] = $this->mContentTypeGuid;
  253.         }
  254.  
  255.         if( @$this->verifyId( $pParamHash['content_id'] ) ) {
  256.             $pParamHash['page_store']['content_id'] = $pParamHash['content_id'];
  257.         }
  258.  
  259.         // check for name issues, first truncate length if too long
  260.         if( empty( $pParamHash['title'] ) ) {
  261.             $this->mErrors['title'] = 'You must specify a title';
  262.         } elseif( !empty( $pParamHash['title']) || !empty($this->mPageName))  {
  263.             if( !$this->verifyId( $this->mPageId ) ) {
  264.                 if( empty( $pParamHash['title'] ) ) {
  265.                     $this->mErrors['title'] = 'You must enter a name for this page.';
  266.                 } else {
  267.                     $pParamHash['content_store']['title'] = substr( $pParamHash['title'], 0, 160 );
  268.                     if ($gBitSystem->isFeatureActive( 'wiki_allow_dup_page_names')) {
  269.                         # silently allow pages with duplicate names to be created
  270.                     } else {
  271.                         if( $this->pageExists( $pParamHash['title'] ) ) {
  272.                             $this->mErrors['title'] = 'Page "'.$pParamHash['title'].'" already exists. Please choose a different name.';
  273.                         }
  274.                     }
  275.                 }
  276.             } else {
  277.                 $pParamHash['content_store']['title'] = ( isset( $pParamHash['title'] ) ) ? substr( $pParamHash['title'], 0, 160 ) : $this->mPageName;
  278.                 if ($gBitSystem->isFeatureActive( 'wiki_allow_dup_page_names')) {
  279.                     # silently allow pages with duplicate names to be created
  280.                 } else {
  281.                     if( $gBitUser->hasPermission( 'p_wiki_rename_page' )
  282.                     && (isset( $this->mInfo['title'] )
  283.                     && ($pParamHash['title'] != $this->mInfo['title'])) ) {
  284.                         if( $this->pageExists( $pParamHash['title'] ) ) {
  285.                             $this->mErrors['title'] = 'Page "'.$pParamHash['title'].'" already exists. Please choose a different name.';
  286.                         }
  287.                     }
  288.                 }
  289.             }
  290.         }
  291.  
  292.         if( empty( $pParamHash['edit_comment'] ) ) {
  293.             $pParamHash['page_store']['edit_comment'] = NULL;
  294.         } else {
  295.             $pParamHash['page_store']['edit_comment'] = substr( $pParamHash['edit_comment'], 0, 200 );
  296.         }
  297.  
  298.         if( !empty( $pParamHash['minor'] ) && $this->isValid() ) {
  299.             // we can only minor save over our own versions
  300.             if( !$gBitUser->isRegistered() || ($this->mInfo['modifier_user_id'] != $gBitUser->mUserId && !$gBitUser->isAdmin()) ) {
  301.                 unset( $pParamHash['minor'] );
  302.             }
  303.         }
  304.  
  305.         // if we have an error we get them all by checking parent classes for additional errors
  306.         if( count( $this->mErrors ) > 0 ){
  307.             parent::verify( $pParamHash );
  308.         }
  309.  
  310.         return( count( $this->mErrors ) == 0 );
  311.     }
  312.  
  313.     /**
  314.      * Remove page from database
  315.      */
  316.     function expunge() {
  317.         $ret = FALSE;
  318.         if( $this->isValid() ) {
  319.             $this->mDb->StartTrans();
  320.             $this->expungeVersion(); // will nuke all versions
  321.             $query = "DELETE FROM `".BIT_DB_PREFIX."wiki_pages` WHERE `content_id` = ?";
  322.             $result = $this->mDb->query( $query, array( $this->mContentId ) );
  323.             if( LibertyMime::expunge() ) {
  324.                 $ret = TRUE;
  325.                 $this->mDb->CompleteTrans();
  326.             } else {
  327.                 $this->mDb->RollbackTrans();
  328.             }
  329.         }
  330.         return $ret;
  331.     }
  332.  
  333.     function isUserPage() {
  334.         $ret = FALSE;
  335.         if( $this->mPageName ) {
  336.             $ret = preg_match( '/^UserPage(.*)/', $this->mPageName, $matches );
  337.         }
  338.         return $ret;
  339.     }
  340.  
  341.     function isValid() {
  342.         return( $this->verifyId( $this->mPageId ) );
  343.     }
  344.  
  345.     function isLocked() {
  346.         $ret = FALSE;
  347.         if( $this->verifyId( $this->mPageId ) ) {
  348.             if( empty( $this->mInfo ) ) {
  349.                 $this->load();
  350.             }
  351.             $ret = $this->getField( 'flag' ) == 'L';
  352.         }
  353.         return( $ret );
  354.     }
  355.  
  356.     function isCommentable() {
  357.         global $gBitSystem;
  358.         return( $gBitSystem->isFeatureActive( 'wiki_comments' ));
  359.     }
  360.  
  361.     function setLock( $pLock, $pModUserId=NULL ) {
  362.         if( $this->verifyId( $this->mPageId ) ) {
  363.             $bindVars = array();
  364.             $userSql = '';
  365.             if( $pModUserId ) {
  366.                 $userSql = "`modifier_user_id`=?, ";
  367.                 array_push( $bindVars, $pModUserId );
  368.             }
  369.             array_push( $bindVars, $pLock, $this->mPageId );
  370.             $query = "update `".BIT_DB_PREFIX."wiki_pages` SET $userSql `flag`=? where `page_id`=?";
  371.             $result = $this->mDb->query($query, $bindVars );
  372.             $this->mInfo['flag'] = $pLock;
  373.         }
  374.         return true;
  375.     }
  376.  
  377.     function lock( $pModUserId=NULL ) {
  378.         return( $this->setLock( 'L', $pModUserId ) );
  379.     }
  380.  
  381.     function unlock( $pModUserId=NULL ) {
  382.         return( $this->setLock( NULL, $pModUserId ) );
  383.     }
  384.  
  385.     // *********  Footnote functions for the wiki ********** //
  386.     /**
  387.      *  Store footnote
  388.      */
  389.     function storeFootnote($pUserId, $pData) {
  390.         if( $this->verifyId( $this->mPageId ) ) {
  391.             $querydel = "delete from `".BIT_DB_PREFIX."wiki_footnotes` where `user_id`=? and `page_id`=?";
  392.             $this->mDb->query( $querydel, array( $pUserId, $this->mPageId ) );
  393.             $query = "insert into `".BIT_DB_PREFIX."wiki_footnotes`(`user_id`,`page_id`,`data`) values(?,?,?)";
  394.             $this->mDb->query( $query, array( $pUserId, $this->mPageId, $pData ) );
  395.         }
  396.     }
  397.  
  398.     /**
  399.      *  Delete footnote
  400.      */
  401.     function expungeFootnote( $pUserId ) {
  402.         if( $this->verifyId( $this->mPageId ) ) {
  403.             $query = "delete from `".BIT_DB_PREFIX."wiki_footnotes` where `user_id`=? and `page_id`=?";
  404.             $this->mDb->query($query,array($pUserId,$this->mPageId));
  405.         }
  406.     }
  407.  
  408.     /**
  409.      *  Get footnote
  410.      */
  411.     function getFootnote( $pUserId ) {
  412.         if( $this->verifyId( $this->mPageId ) ) {
  413.             $count = $this->mDb->getOne( "select count(*) from `".BIT_DB_PREFIX."wiki_footnotes` where `user_id`=? and `page_id`=?", array( $pUserId, $this->mPageId ) );
  414.             if( $count ) {
  415.                 return $this->mDb->getOne("select `data` from `".BIT_DB_PREFIX."wiki_footnotes` where `user_id`=? and `page_id`=?",array( $pUserId, $this->mPageId ) );
  416.             }
  417.         }
  418.     }
  419.  
  420.     /**
  421.     * Generates a link to a wiki page within lists of pages
  422.     * @return the link to display the page.
  423.     */
  424.     function getListLink( $pParamHash ) {
  425.         return BitPage::getPageLink( $pParamHash['title'], NULL );
  426.     }
  427.  
  428.  
  429.     /**
  430.     * Returns include file that will
  431.     * @return the fully specified path to file to be included
  432.     */
  433.     function getRenderFile() {
  434.         return WIKI_PKG_PATH."display_bitpage_inc.php";
  435.     }
  436.  
  437.  
  438.     /**
  439.      * Returns the center template for the view selected
  440.      */
  441.     function getViewTemplate( $pAction ){
  442.         $ret = null;
  443.         switch ( $pAction ){
  444.             case "view":
  445.                 $ret = "bitpackage:wiki/center_wiki_page.tpl";
  446.                 break;
  447.             case "list":
  448.                 $ret = "bitpackage:liberty/center_".$pAction."_generic.tpl";
  449.                 break;
  450.         }
  451.         return $ret;
  452.     }
  453.  
  454.  
  455.     /**
  456.     * Generates the URL to this wiki page
  457.     * @param pExistsHash the hash that was returned by LibertyContent::pageExists
  458.     * @return the link to display the page.
  459.     */
  460.     public static function getDisplayUrlFromHash( &$pParamHash ) {
  461.         global $gBitSystem;
  462.         if( !empty( $pParamHash['title'] ) ) {
  463.             if( $gBitSystem->isFeatureActive( 'pretty_urls' ) || $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ) {
  464.                 $rewrite_tag = $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ? 'view/':'';
  465.                 $prettyPageName = preg_replace( '/ /', '+', $pParamHash['title'] );
  466.                 $ret = WIKI_PKG_URL.$rewrite_tag.$prettyPageName;
  467.             } else {
  468.                 $ret = WIKI_PKG_URL.'index.php?page='.urlencode( $pParamHash['title'] );
  469.             }
  470.         } else {
  471.             $ret = parent::getDisplayUrlFromHash( $pParamHash );
  472.         }
  473.  
  474.         return $ret;
  475.     }
  476.  
  477.     /**
  478.     * Returns HTML link to display a page if it exists, or to create if not
  479.     * @param pExistsHash the hash that was returned by LibertyContent::pageExists
  480.     * @return the link to display the page.
  481.     */
  482.     public static function getPageLink( $pLinkText=NULL, $pMixed=NULL, $pAnchor=NULL ) {
  483.         global $gBitSystem, $gBitUser;
  484.         $ret = $pLinkText;
  485.         if( $gBitSystem->isPackageActive( 'wiki' ) ) {
  486.             if( !empty( $pMixed ) && is_array( $pMixed ) ) {
  487.                 if( is_array( current( $pMixed ) ) ) {
  488.                     $exists = $pMixed[0];
  489.                     $multiple = TRUE;
  490.                 } else {
  491.                     $exists = $pMixed;
  492.                     $multiple = FALSE;
  493.                 }
  494.  
  495.                 // we have a multi-demensional array (likely returned from LibertyContent::pageExists() ) - meaning we potentially have multiple pages with the same name
  496.                 if( $multiple ) {
  497.                     $desc = tra( 'Multiple pages with this name' );
  498.                 } else {
  499.                     $desc = empty( $exists['summary'] ) ? $exists['title'] : $exists['summary'];
  500.                 }
  501.                 $ret = '<a title="'.htmlspecialchars( $desc ).'" href="'.BitPage::getDisplayUrlFromHash( $exists ).'">'.htmlspecialchars( $exists['title'] ).'</a>';
  502.             } else {
  503.                 if( $gBitUser->hasPermission( 'p_wiki_create_page' ) ) {
  504.                     $ret = '<a title="'.tra( "Create the page" ).': '.htmlspecialchars( $pLinkText ).'" href="'.WIKI_PKG_URL.'edit.php?page='.urlencode( $pLinkText ).'" class="create">'.htmlspecialchars( $pLinkText ).'</a>';
  505.                 } else {
  506.                     $ret = $pLinkText;
  507.                 }
  508.             }
  509.         }
  510.         return $ret;
  511.     }
  512.  
  513.     /**
  514.     * Returns content_id's that link to this page
  515.     * @return hash of content
  516.     */
  517.     function getBacklinks() {
  518.         if( $this->isValid() ) {
  519.             $to_title = $this->mInfo['title'];
  520.             $query = "SELECT lcl.`from_content_id`, lc.`title`
  521.                       FROM `".BIT_DB_PREFIX."liberty_content_links` lcl INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lcl.`from_content_id`=lc.`content_id`)
  522.                       WHERE lcl.`to_title` = ? ORDER BY lcl.POS";
  523.             $ret = $this->mDb->getAssoc( $query, array( $to_title ) );
  524.             return $ret;
  525.         }
  526.     }
  527.  
  528.  
  529.     /**
  530.      * Roll back to a specific version of a page
  531.      * @param pVersion Version number to roll back to
  532.      * @param comment Comment text to be added to the action log
  533.      * @return TRUE if completed successfully
  534.      */
  535.     function rollbackVersion( $pVersion, $comment = '' ) {
  536.         global $gBitSystem;
  537.         $ret = FALSE;
  538.         if( parent::rollbackVersion( $pVersion, $comment ) ) {
  539.             $action = "Changed actual version to $pVersion";
  540.             $t = $gBitSystem->getUTCTime();
  541.             $query = "insert into `".BIT_DB_PREFIX."liberty_action_log`(`log_message`,`content_id`,`last_modified`,`user_id`,`ip`,`error_message`) values(?,?,?,?,?,?)";
  542.             $result = $this->mDb->query($query,array($action,$this->mContentId,$t,ROOT_USER_ID,$_SERVER["REMOTE_ADDR"],$comment));
  543.             $ret = TRUE;
  544.         }
  545.         return $ret;
  546.     }
  547.  
  548.     /**
  549.      * getList
  550.      *
  551.      * @param array $pListHash array of list parameters
  552.      * @param boolean $pListHash['orphans_only'] only return orphan wiki pages
  553.      * @param boolean $pListHash['extras'] load extra infrmation such as backlinks and links
  554.      * @param boolean $pListHash['get_data'] return the wiki page data along with the listed information
  555.      * @param string $pListHash['find_title'] filter by the page title
  556.      * @param string $pListHash['find_author'] filter by the login name of the page author
  557.      * @param string $pListHash['find_last_editor'] filter by the login name of the last editor of the page
  558.      * @access public
  559.      * @return array of wiki pages
  560.      */
  561.     function getList( &$pListHash ) {
  562.         global $gBitSystem, $gBitUser;
  563.         LibertyContent::prepGetList( $pListHash );
  564.  
  565.         if( $pListHash['sort_mode'] == 'size_asc' || $pListHash['sort_mode'] == 'size_desc' ) {
  566.             $pListHash['sort_mode'] = str_replace( 'size', 'wiki_page_size', $pListHash['sort_mode'] );
  567.         }
  568.  
  569.         $specialSort = array(
  570.             'versions_desc',
  571.             'versions_asc',
  572.             'links_asc',
  573.             'links_desc',
  574.             'backlinks_asc',
  575.             'backlinks_desc'
  576.         );
  577.  
  578.         if( in_array( $pListHash['sort_mode'], $specialSort )) {
  579.             $originalListHash         = $pListHash;
  580.             // now we can set the new values in the pListHash
  581.             $pListHash['sort_mode']   = 'modifier_user_desc';
  582.             $pListHash['offset']      = 0;
  583.             $pListHash['max_records'] = -1;
  584.         }
  585.  
  586.         $whereSql = $joinSql = $selectSql = '';
  587.         $bindVars = array();
  588.         $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars, NULL, $pListHash );
  589.  
  590.         if ( !empty( $pListHash['content_type_guid'] ) ) {
  591.             $whereSql .= " AND lc.`content_type_guid`=? ";
  592.             $bindVars[] = $pListHash['content_type_guid'];
  593.         }
  594.  
  595.         // make find_title compatible with {minifind}
  596.         if( empty( $pListHash['find_title'] )) {
  597.             $pListHash['find_title'] = $pListHash['find'];
  598.         }
  599.  
  600.         // use an array or string to search for wiki page titles
  601.         if( is_array( $pListHash['find_title'] )) {
  602.             $whereSql .= " AND lc.`title` IN (".implode(',',array_fill( 0, count( $pListHash['find_title'] ), '?' )).")";
  603.             $bindVars = array_merge( $bindVars, $pListHash['find_title'] );
  604.         } elseif( !empty( $pListHash['find_title'] ) && is_string( $pListHash['find_title'] )) {
  605.             $whereSql .= " AND UPPER(lc.`title`) LIKE ? ";
  606.             $bindVars = array_merge( $bindVars, array( '%'.strtoupper( $pListHash['find_title'] ) . '%' ));
  607.         }
  608.  
  609.         // limit by user id
  610.         if( @BitBase::verifyId( $pListHash['user_id'] )) {
  611.             $whereSql .= " AND lc.`user_id` = ? ";
  612.             $bindVars = array_merge( $bindVars, array( $pListHash['user_id'] ));
  613.         }
  614.  
  615.         // filter pages by author login
  616.         if( !empty( $pListHash['find_author'] )) {
  617.             $whereSql .= " AND UPPER(uuc.`login`) = ? ";
  618.             $bindVars = array_merge( $bindVars, array( strtoupper( $pListHash['find_author'] )));
  619.         }
  620.  
  621.         // filter pages by last editor
  622.         if( !empty( $pListHash['find_last_editor'] )) {
  623.             $whereSql .= " AND UPPER(uue.`login`) = ? ";
  624.             $bindVars = array_merge( $bindVars, array( strtoupper( $pListHash['find_last_editor'] )));
  625.         }
  626.  
  627.         $get_data = '';
  628.         if( !empty( $pListHash['get_data'] )) {
  629.             $get_data = ', lc.`data`';
  630.         }
  631.  
  632.         if( empty( $pListHash['orphans_only'] )) {
  633.             $whereSql =  preg_replace('/^ AND */',' WHERE ', $whereSql);
  634.             $query = "SELECT
  635.                     uue.`login` AS modifier_user, uue.`real_name` AS modifier_real_name, uuc.`login` AS creator_user, uuc.`real_name` AS creator_real_name,
  636.                     wp.`page_id`, wp.`wiki_page_size` as `len`, lcds.`data` AS `summary`, wp.`edit_comment`, wp.`content_id`, wp.`flag`,
  637.                     lc.`title`, lc.`format_guid`, lc.`last_modified`, lc.`created`, lc.`ip`, lc.`version`,
  638.                     lch.`hits` $get_data $selectSql
  639.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  640.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`)
  641.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uuc ON ( uuc.`user_id` = lc.`user_id` )
  642.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uue ON ( uue.`user_id` = lc.`modifier_user_id` )
  643.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_data` lcds ON (lc.`content_id` = lcds.`content_id` AND lcds.`data_type`='summary')
  644.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON (lc.`content_id` = lch.`content_id`)
  645.                     $joinSql
  646.                 $whereSql
  647.                 ORDER BY ".$this->mDb->convertSortmode( $pListHash['sort_mode'] );
  648.             $query_cant = "
  649.                 SELECT COUNT(*)
  650.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  651.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`)
  652.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uuc ON ( uuc.`user_id` = lc.`user_id` )
  653.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uue ON ( uue.`user_id` = lc.`modifier_user_id` )
  654.                     $joinSql
  655.                 $whereSql
  656.                 ";
  657.         } else {
  658.             $whereSql .= ' AND lcl.`to_content_id` is NULL ';
  659.             $whereSql =  preg_replace('/^ AND */',' WHERE ', $whereSql);
  660.             $query = "SELECT
  661.                     uue.`login` AS modifier_user, uue.`real_name` AS modifier_real_name, uuc.`login` AS creator_user, uuc.`real_name` AS creator_real_name,
  662.                     wp.`page_id`, wp.`wiki_page_size` AS `len`,lcds.`data` AS `summary`, wp.`edit_comment`, wp.`content_id`, wp.`flag`,
  663.                     lc.`title`, lc.`format_guid`, lc.`last_modified`, lc.`created`, lc.`ip`, lc.`version`,
  664.                     lch.`hits` $get_data $selectSql
  665.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  666.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`)
  667.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uuc ON ( uuc.`user_id` = lc.`user_id` )
  668.                     INNER JOIN `".BIT_DB_PREFIX."users_users` uue ON ( uue.`user_id` = lc.`user_id` )
  669.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_links` lcl ON (wp.`content_id` = lcl.`to_content_id`)
  670.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_hits` lch ON (lc.`content_id` = lch.`content_id`)
  671.                     LEFT OUTER JOIN `".BIT_DB_PREFIX."liberty_content_data` lcds ON (lc.`content_id` = lcds.`content_id` AND lcds.`data_type`='summary')
  672.                     $joinSql
  673.                 $whereSql
  674.                 ORDER BY ".$this->mDb->convertSortmode( $pListHash['sort_mode'] );
  675.             $query_cant = "
  676.                 SELECT COUNT(*)
  677.                 FROM `".BIT_DB_PREFIX."wiki_pages` wp
  678.                     LEFT JOIN `".BIT_DB_PREFIX."liberty_content_links` lcl ON (wp.`content_id` = lcl.`to_content_id`)
  679.                     INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`)
  680.                     $joinSql
  681.                 $whereSql";
  682.         }
  683.  
  684.         // If sort mode is versions then offset is 0, max_records is -1 (again) and sort_mode is nil
  685.         // If sort mode is links then offset is 0, max_records is -1 (again) and sort_mode is nil
  686.         // If sort mode is backlinks then offset is 0, max_records is -1 (again) and sort_mode is nil
  687.  
  688.         $ret = array();
  689.         $this->mDb->StartTrans();
  690.  
  691.         # get count of total number of items available
  692.         $cant = $this->mDb->getOne( $query_cant, $bindVars );
  693.         $pListHash["cant"] = $cant;
  694.  
  695.         # Check for offset out of range
  696.         if ( $pListHash['offset'] < 0 ) {
  697.             $pListHash['offset'] = 0;
  698.         } elseif ( $pListHash['offset']    > $pListHash["cant"] ) {
  699.             $lastPageNumber = ceil ( $pListHash["cant"] / $pListHash['max_records'] ) - 1;
  700.             $pListHash['offset'] = $pListHash['max_records'] * $lastPageNumber;
  701.         }
  702.  
  703.         $result = $this->mDb->query( $query, $bindVars, $pListHash['max_records'], $pListHash['offset'] );
  704.         $this->mDb->CompleteTrans();
  705.         while( $res = $result->fetchRow() ) {
  706.             $aux = array();
  707.             $aux = $res;
  708.             $aux['creator'] = (isset( $res['creator_real_name'] ) ? $res['creator_real_name'] : $res['creator_user'] );
  709.             $aux['editor'] = (isset( $res['modifier_real_name'] ) ? $res['modifier_real_name'] : $res['modifier_user'] );
  710.             $aux['flag'] = $res["flag"] == 'L' ? 'locked' : 'unlocked';
  711.             $aux['display_url'] = static::getDisplayUrlFromHash( $aux );
  712.             // display_link does not seem to be used when getList is called
  713.             //$aux['display_link'] = $this->getDisplayLink( $aux['title'] ); //WIKI_PKG_URL."index.php?page_id=".$res['page_id'];
  714.             if( !empty( $pListHash['extras'] )) {
  715.                 // USE SPARINGLY!!! This gets expensive fast
  716. //                $aux['versions"]  = $this->mDb->getOne( "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."liberty_content_history` WHERE `page_id`=?", array( $res["page_id"] ));
  717.                 $aux['links']     = $this->mDb->getOne( "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE `from_content_id`=?", array( $res["content_id"] ));
  718.                 $aux['backlinks'] = $this->mDb->getOne( "select COUNT(*) FROM `".BIT_DB_PREFIX."liberty_content_links` WHERE `to_title`=?", array( $aux['title'] ));
  719.             }
  720.             $ret[] = $aux;
  721.         }
  722.  
  723.         // apply the custom sorting options if needed
  724.         if( !empty( $originalListHash )) {
  725.             if( $originalListHash['sort_mode'] == 'versions_asc' && !empty( $ret['versions'] )) {
  726.                 usort( $ret, 'compare_versions');
  727.             } elseif( $originalListHash['sort_mode'] == 'versions_desc' && !empty( $ret['versions'] )) {
  728.                 usort( $ret, 'r_compare_versions');
  729.             } elseif( $originalListHash['sort_mode'] == 'links_desc' && !empty( $ret['links'] )) {
  730.                 usort( $ret, 'compare_links');
  731.             } elseif( $originalListHash['sort_mode'] == 'links_asc' && !empty( $ret['links'] )) {
  732.                 usort( $ret, 'r_compare_links');
  733.             } elseif( $originalListHash['sort_mode'] == 'backlinks_desc' && !empty( $ret['backlinks'] )) {
  734.                 usort($ret, 'compare_backlinks');
  735.             } elseif( $originalListHash['sort_mode'] == 'backlinks_asc' && !empty( $ret['backlinks'] )) {
  736.                 usort($ret, 'r_compare_backlinks');
  737.             }
  738.  
  739.             // return only requested values
  740.             if( in_array( $originalListHash['sort_mode'], $specialSort )) {
  741.                 $ret = array_slice( $ret, $originalListHash['offset'], $originalListHash['max_records'] );
  742.             }
  743.  
  744.             // load original listHash
  745.             $pListHash = $originalListHash;
  746.         }
  747.  
  748.         LibertyContent::postGetList( $pListHash );
  749.  
  750.         return $ret;
  751.     }
  752.  
  753.     /* Update a page
  754.      * $pHashOld the where conmdition : page_id
  755.      * $pHashNew the new fields: title, data
  756.      */
  757.     function update( $pHashOld, $pHashNew) {
  758.         $set = array();
  759.         $where = array();
  760.         if (!empty($pHashNew['title'])) {
  761.             $set[] = "lc.`title`=?";
  762.             $bindVars[] = $pHashNew['title'];
  763.         }
  764.         if (!empty($pHashNew['data'])) {
  765.             $set[] = "lc.`data`=?";
  766.             $bindVars[] = $pHashNew['data'];
  767.         }
  768.         if (!empty($pHashOld['page_id'])) {
  769.             $where[] = "wp.`page_id`=?";
  770.             $bindVars[] = $pHashOld['page_id'] ;
  771.         }
  772.         if (empty($where)) {
  773.             $this->mErrors['page_id'] = "You must specify a where condition";
  774.             return false;
  775.         }
  776.  
  777.         $query = "update `".BIT_DB_PREFIX."liberty_content` lc
  778.             LEFT JOIN `".BIT_DB_PREFIX."wiki_pages` wp on (wp.`content_id`= lc.`content_id`)
  779.             SET ".implode(',', $set)."
  780.             WHERE ".implode (" AND ", $where);
  781.         $this->mDb->query( $query, $bindVars);
  782.         return true;
  783.     }
  784.  
  785.     // ...page... functions
  786.     function countSubPages( $pData ) {
  787.         return(( preg_match_all( '/'.( defined( 'PAGE_SEP' ) ? preg_quote( PAGE_SEP ) : '\.\.\.page\.\.\.').'/', $pData, $matches ) + 1 ));
  788.     }
  789.  
  790.     /**
  791.      * getSubPage
  792.      *
  793.      * @param array $pData 
  794.      * @param array $pPageNumber 
  795.      * @access public
  796.      * @return string SubPage
  797.      */
  798.     function getSubPage( $pData, $pPageNumber ) {
  799.         // Get slides
  800.         $parts = explode( defined( 'PAGE_SEP' ) ? PAGE_SEP : "...page...", $pData );
  801.         if( substr( $parts[$pPageNumber - 1], 1, 5 ) == "<br/>" ) {
  802.             $ret = substr( $parts[$pPageNumber - 1], 6 );
  803.         } else {
  804.             $ret = $parts[$pPageNumber - 1];
  805.         }
  806.         return $ret;
  807.     }
  808.  
  809.     /**
  810.      * getLikePages Like pages are pages that share a word in common with the current page
  811.      *
  812.      * @param array $pPageTitle 
  813.      * @access public
  814.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  815.      */
  816.     function getLikePages( $pPageTitle ) {
  817.         $ret = array();
  818.         if( !empty( $pPageName ) ) {
  819.             preg_match_all("/([A-Z])([a-z]+)/", $pPageTitle, $words);
  820.             // Add support to ((x)) in either strict or full modes
  821.             preg_match_all("/(([A-Za-z]|[\x80-\xFF])+)/", $pPageTitle, $words2);
  822.             $words = array_unique(array_merge($words[0], $words2[0]));
  823.             $exps = array();
  824.             $bindVars=array();
  825.             foreach ($words as $word) {
  826.                 $exps[] = "`title` like ?";
  827.                 $bindVars[] = "%$word%";
  828.             }
  829.             $selectSql = '';
  830.             $joinSql = '';
  831.             $whereSql = implode(" or ", $exps);
  832.             array_push( $bindVars, $this->mContentTypeGuid );
  833.             $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
  834.  
  835.             $query = "SELECT lc.`title` FROM `".BIT_DB_PREFIX."wiki_pages` wp INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id` = wp.`content_id`) $join WHERE $whereSql";
  836.             $result = $this->mDb->query($query,$bindVars);
  837.             while ($res = $result->fetchRow()) {
  838.                 $ret[] = $res["title"];
  839.             }
  840.         }
  841.         return $ret;
  842.     }
  843.  
  844.     /**
  845.      * getStats getStats is always used by the stats package to display various stats of your package.
  846.      *
  847.      * @access public
  848.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  849.      */
  850.     function getStats() {
  851.         global $gBitSystem;
  852.         $ret = array();
  853.  
  854.         $query = "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."wiki_pages`";
  855.         $ret['pages'] = array(
  856.             'label' => "Number of pages",
  857.             'value' => $this->mDb->getOne( $query ),
  858.         );
  859.  
  860.         $listHash = array( 'orphans_only' => TRUE );
  861.         $this->getList( $listHash );
  862.         $ret['orphans'] = array(
  863.             'label' => 'Orphan Pages',
  864.             'value' => $listHash['listInfo']['total_records'],
  865.         );
  866.  
  867.         $query = "SELECT SUM(`wiki_page_size`) FROM `".BIT_DB_PREFIX."wiki_pages`";
  868.         $ret['size'] = array(
  869.             'label' => "Combined size",
  870.             'value' => $this->mDb->getOne( $query ),
  871.             'modifier' => 'display_bytes',
  872.         );
  873.  
  874.         $ret['average_size'] = array(
  875.             'label' => 'Average page size',
  876.             'value' => $ret['size']['value'] / $ret['pages']['value'],
  877.             'modifier' => 'display_bytes',
  878.         );
  879.  
  880.         $query = "
  881.             SELECT COUNT(*)
  882.             FROM `".BIT_DB_PREFIX."liberty_content_history` lch
  883.             INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lch.`content_id` = lc.`content_id` )
  884.             WHERE lc.`content_type_guid` = ?";
  885.         $ret['versions'] = array(
  886.             'label' => "Versions",
  887.             'value' => $this->mDb->getOne( $query, array( BITPAGE_CONTENT_TYPE_GUID )),
  888.         );
  889.  
  890.         $ret['average_versions'] = array(
  891.             'label' => 'Average versions per page',
  892.             'value' => round( $ret['versions']['value'] / $ret['pages']['value'], 3 ),
  893.         );
  894.  
  895.         $query = "
  896.             SELECT COUNT(*) FROM `".BIT_DB_PREFIX."liberty_content_links` lcl
  897.             INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lcl.`from_content_id` = lc.`content_id` OR lcl.`from_content_id` = lc.`content_id` )
  898.             WHERE lc.`content_type_guid` = ?";
  899.         $ret['links'] = array(
  900.             'label' => "Total wiki links",
  901.             'value' => $this->mDb->getOne( $query, array( BITPAGE_CONTENT_TYPE_GUID )),
  902.         );
  903.  
  904.         $ret['average_links'] = array(
  905.             'label' => 'Average links per page',
  906.             'value' => round( $ret['links']['value'] / $ret['pages']['value'], 3 ),
  907.         );
  908.  
  909.         return $ret;
  910.     }
  911.  
  912.     // {{{ ==================================== GraphViz wiki graph methods ====================================
  913.     /**
  914.      * linkStructureGraph
  915.      *
  916.      * @param array $pLinkStructure 
  917.      * @param array $pParams 
  918.      * @param array $pGraphViz 
  919.      * @access public
  920.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  921.      */
  922.     function linkStructureGraph( $pLinkStructure = array(), $pParams = array(), &$pGraphViz ) {
  923.         if( !empty( $pLinkStructure ) && !empty( $pGraphViz )) {
  924.             $pParams['graph']['URL'] = WIKI_PKG_URL.'index.php';
  925.             $pGraphViz->addAttributes( $pParams['graph'] );
  926.             $pLinkStructure['title'] = $pLinkStructure['name'];
  927.             $pParams['node']['URL'] = static::getDisplayUrlFromHash( $pLinkStructure );
  928.             $pGraphViz->addNode( $pLinkStructure['name'], $pParams['node'] );
  929.  
  930.             foreach( $pLinkStructure['pages'] as $node ) {
  931.                 $this->linkStructureGraph( $node, $pParams, $pGraphViz );
  932.                 $pGraphViz->addEdge( array( $pLinkStructure['name'] => $node['name'] ), $pParams['node'] );
  933.             }
  934.         }
  935.     }
  936.  
  937.     /**
  938.      * linkStructureMap
  939.      *
  940.      * @param array $pPageName 
  941.      * @param int $pLevel 
  942.      * @param array $pParams 
  943.      * @access public
  944.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  945.      */
  946.     function linkStructureMap( $pPageName, $pLevel = 0, $pParams = array() ) {
  947.         if( !empty( $pPageName ) && @include_once( 'Image/GraphViz.php' )) {
  948.             $graph = new Image_GraphViz();
  949.             $this->linkStructureGraph( $this->getLinkStructure( $pPageName, $pLevel ), $pParams, $graph );
  950.             return $graph->fetch( 'cmap' );
  951.         }
  952.     }
  953.  
  954.     /**
  955.      * getLinkStructure
  956.      *
  957.      * @param array $pPageName 
  958.      * @param float $pLevel 
  959.      * @access public
  960.      * @return boolean TRUE on success, FALSE on failure - $this->mErrors will contain reason for failure
  961.      */
  962.     function getLinkStructure( $pPageName, $pLevel = 0 ) {
  963.         $query = "
  964.             SELECT lc2.`title`
  965.             FROM `".BIT_DB_PREFIX."liberty_content_links` lcl
  966.             INNER JOIN liberty_content lc1 ON( lc1.`content_id` = lcl.`from_content_id` AND lc1.`content_status_id` > 49 )
  967.             INNER JOIN liberty_content lc2 ON( lc2.`content_id` = lcl.`to_content_id` AND lc2.`content_status_id` > 49 )
  968.             WHERE lc1.`title` = ? AND lcl.`from_content_id` <> lcl.`to_content_id`";
  969.         $result = $this->mDb->query( $query, array( $pPageName ));
  970.  
  971.         $ret['pages'] = array();
  972.         $ret['name']  = $pPageName;
  973.  
  974.         while( $res = $result->fetchRow() ) {
  975.             if( !empty( $pLevel )) {
  976.                 $ret['pages'][] = $this->getLinkStructure( $res['title'], $pLevel - 1 );
  977.             } else {
  978.                 $ret['pages'][] = array(
  979.                     'name'  => $res['title'],
  980.                     'pages' => array(),
  981.                 );
  982.             }
  983.         }
  984.         return $ret;
  985.     }
  986.     // }}}
  987. }
  988.  
  989. /* vim: :set fdm=marker : */
  990. ?>

Documentation generated on Wed, 29 Jul 2015 13:55:57 +0000 by phpDocumentor 1.5.0-lsces