includes/log.php
changeset 1227 bdac73ed481e
parent 1212 db2edac4e5a7
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    20  * @license GNU General Public License
    20  * @license GNU General Public License
    21  */
    21  */
    22 
    22 
    23 class LogDisplay
    23 class LogDisplay
    24 {
    24 {
    25   /**
    25 	/**
    26    * Criteria for the search.
    26  	* Criteria for the search.
    27    * Structure:
    27  	* Structure:
    28    <code>
    28  	<code>
    29    array(
    29  	array(
    30        array( 'user', 'Dan' ),
    30  			array( 'user', 'Dan' ),
    31        array( 'within', 86400 ),
    31  			array( 'within', 86400 ),
    32        array( 'page', 'Main_Page' )
    32  			array( 'page', 'Main_Page' )
    33      )
    33  		)
    34    </code>
    34  	</code>
    35    * @var array
    35  	* @var array
    36    */
    36  	*/
    37   
    37 	
    38   var $criteria = array();
    38 	var $criteria = array();
    39   
    39 	
    40   /**
    40 	/**
    41    * Adds a criterion for the log display.
    41  	* Adds a criterion for the log display.
    42    * @param string Criterion type - user, page, or within
    42  	* @param string Criterion type - user, page, or within
    43    * @param string Value - username, page ID, or (int) within # seconds or (string) number + suffix (suffix: d = day, w = week, m = month, y = year) ex: "1w"
    43  	* @param string Value - username, page ID, or (int) within # seconds or (string) number + suffix (suffix: d = day, w = week, m = month, y = year) ex: "1w"
    44    */
    44  	*/
    45   
    45 	
    46   public function add_criterion($criterion, $value)
    46 	public function add_criterion($criterion, $value)
    47   {
    47 	{
    48     switch ( $criterion )
    48 		switch ( $criterion )
    49     {
    49 		{
    50       case 'user':
    50 			case 'user':
    51       case 'page':
    51 			case 'page':
    52       case 'action':
    52 			case 'action':
    53         $this->criteria[] = array($criterion, $value);
    53 				$this->criteria[] = array($criterion, $value);
    54         break;
    54 				break;
    55       case 'minor':
    55 			case 'minor':
    56         $this->criteria[] = array($criterion, intval($value));
    56 				$this->criteria[] = array($criterion, intval($value));
    57         break;
    57 				break;
    58       case 'within':
    58 			case 'within':
    59         if ( is_int($value) )
    59 				if ( is_int($value) )
    60         {
    60 				{
    61           $this->criteria[] = array($criterion, $value);
    61 					$this->criteria[] = array($criterion, $value);
    62         }
    62 				}
    63         else if ( is_string($value) )
    63 				else if ( is_string($value) )
    64         {
    64 				{
    65           $lastchar = substr($value, -1);
    65 					$lastchar = substr($value, -1);
    66           $amt = intval($value);
    66 					$amt = intval($value);
    67           switch($lastchar)
    67 					switch($lastchar)
    68           {
    68 					{
    69             case 'd':
    69 						case 'd':
    70               $amt = $amt * 86400;
    70 							$amt = $amt * 86400;
    71               break;
    71 							break;
    72             case 'w':
    72 						case 'w':
    73               $amt = $amt * 604800;
    73 							$amt = $amt * 604800;
    74               break;
    74 							break;
    75             case 'm':
    75 						case 'm':
    76               $amt = $amt * 2592000;
    76 							$amt = $amt * 2592000;
    77               break;
    77 							break;
    78             case 'y':
    78 						case 'y':
    79               $amt = $amt * 31536000;
    79 							$amt = $amt * 31536000;
    80               break;
    80 							break;
    81           }
    81 					}
    82           $this->criteria[] = array($criterion, $amt);
    82 					$this->criteria[] = array($criterion, $amt);
    83         }
    83 				}
    84         else
    84 				else
    85         {
    85 				{
    86           throw new Exception('Invalid value type for within');
    86 					throw new Exception('Invalid value type for within');
    87         }
    87 				}
    88         break;
    88 				break;
    89       default:
    89 			default:
    90         throw new Exception('Unknown criterion type');
    90 				throw new Exception('Unknown criterion type');
    91         break;
    91 				break;
    92     }
    92 		}
    93   }
    93 	}
    94   
    94 	
    95   /**
    95 	/**
    96    * Build the necessary SQL query.
    96  	* Build the necessary SQL query.
    97    * @param int Optional: offset, defaults to 0
    97  	* @param int Optional: offset, defaults to 0
    98    * @param int Optional: page size, defaults to 0; 0 = don't limit
    98  	* @param int Optional: page size, defaults to 0; 0 = don't limit
    99    */
    99  	*/
   100   
   100 	
   101   public function build_sql($offset = 0, $page_size = 0, $just_page_count = false)
   101 	public function build_sql($offset = 0, $page_size = 0, $just_page_count = false)
   102   {
   102 	{
   103     global $db, $session, $paths, $template, $plugins; // Common objects
   103 		global $db, $session, $paths, $template, $plugins; // Common objects
   104     
   104 		
   105     $where_extra = '';
   105 		$where_extra = '';
   106     $where_bits = array(
   106 		$where_bits = array(
   107         'user' => array(),
   107 				'user' => array(),
   108         'page' => array(),
   108 				'page' => array(),
   109         'action' => array()
   109 				'action' => array()
   110       );
   110 			);
   111     foreach ( $this->criteria as $criterion )
   111 		foreach ( $this->criteria as $criterion )
   112     {
   112 		{
   113       list($type, $value) = $criterion;
   113 			list($type, $value) = $criterion;
   114       switch($type)
   114 			switch($type)
   115       {
   115 			{
   116         case 'user':
   116 				case 'user':
   117           $where_bits['user'][] = "author = '" . $db->escape(str_replace('_', ' ', $value)) . "'";
   117 					$where_bits['user'][] = "author = '" . $db->escape(str_replace('_', ' ', $value)) . "'";
   118           break;
   118 					break;
   119         case 'action':
   119 				case 'action':
   120           if ( $value === 'protect' )
   120 					if ( $value === 'protect' )
   121           {
   121 					{
   122             $where_bits['action'][] = "action = 'prot'";
   122 						$where_bits['action'][] = "action = 'prot'";
   123             $where_bits['action'][] = "action = 'unprot'";
   123 						$where_bits['action'][] = "action = 'unprot'";
   124             $where_bits['action'][] = "action = 'semiprot'";
   124 						$where_bits['action'][] = "action = 'semiprot'";
   125           }
   125 					}
   126           else
   126 					else
   127           {
   127 					{
   128             $where_bits['action'][] = "action = '" . $db->escape($value) . "'";
   128 						$where_bits['action'][] = "action = '" . $db->escape($value) . "'";
   129           }
   129 					}
   130           break;
   130 					break;
   131         case 'page':
   131 				case 'page':
   132           list($page_id, $namespace) = RenderMan::strToPageId($value);
   132 					list($page_id, $namespace) = RenderMan::strToPageId($value);
   133           $where_bits['page'][] = "page_id = '" . $db->escape($page_id) . "' AND namespace = '" . $db->escape($namespace) . "'";
   133 					$where_bits['page'][] = "page_id = '" . $db->escape($page_id) . "' AND namespace = '" . $db->escape($namespace) . "'";
   134           break;
   134 					break;
   135         case 'within':
   135 				case 'within':
   136           $threshold = time() - $value;
   136 					$threshold = time() - $value;
   137           $where_extra .= "\n    AND time_id > $threshold";
   137 					$where_extra .= "\n    AND time_id > $threshold";
   138           break;
   138 					break;
   139         case 'minor':
   139 				case 'minor':
   140           if ( $value == 1 )
   140 					if ( $value == 1 )
   141             $where_extra .= "\n    AND ( minor_edit = 1 OR action != 'edit' )";
   141 						$where_extra .= "\n    AND ( minor_edit = 1 OR action != 'edit' )";
   142           else
   142 					else
   143             $where_extra .= "\n    AND minor_edit != 1";
   143 						$where_extra .= "\n    AND minor_edit != 1";
   144           break;
   144 					break;
   145       }
   145 			}
   146     }
   146 		}
   147     if ( !empty($where_bits['user']) )
   147 		if ( !empty($where_bits['user']) )
   148     {
   148 		{
   149       $where_extra .= "\n    AND ( " . implode(" OR ", $where_bits['user']) . " )";
   149 			$where_extra .= "\n    AND ( " . implode(" OR ", $where_bits['user']) . " )";
   150     }
   150 		}
   151     if ( !empty($where_bits['page']) )
   151 		if ( !empty($where_bits['page']) )
   152     {
   152 		{
   153       $where_extra .= "\n    AND ( (" . implode(") OR (", $where_bits['page']) . ") )";
   153 			$where_extra .= "\n    AND ( (" . implode(") OR (", $where_bits['page']) . ") )";
   154     }
   154 		}
   155     if ( !empty($where_bits['action']) )
   155 		if ( !empty($where_bits['action']) )
   156     {
   156 		{
   157       $where_extra .= "\n    AND ( (" . implode(") OR (", $where_bits['action']) . ") )";
   157 			$where_extra .= "\n    AND ( (" . implode(") OR (", $where_bits['action']) . ") )";
   158     }
   158 		}
   159     if ( ENANO_DBLAYER == 'PGSQL' )
   159 		if ( ENANO_DBLAYER == 'PGSQL' )
   160       $limit = ( $page_size > 0 ) ? "\n  LIMIT $page_size OFFSET $offset" : '';
   160 			$limit = ( $page_size > 0 ) ? "\n  LIMIT $page_size OFFSET $offset" : '';
   161     else
   161 		else
   162       $limit = ( $page_size > 0 ) ? "\n  LIMIT $offset, $page_size" : '';
   162 			$limit = ( $page_size > 0 ) ? "\n  LIMIT $offset, $page_size" : '';
   163     $columns = ( $just_page_count ) ? 'COUNT(*)' : 'log_id, action, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, author, author_uid, u.username, time_id, edit_summary, minor_edit';
   163 		$columns = ( $just_page_count ) ? 'COUNT(*)' : 'log_id, action, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, author, author_uid, u.username, time_id, edit_summary, minor_edit';
   164     $sql = 'SELECT ' . $columns . ' FROM ' . table_prefix . "logs AS l\n"
   164 		$sql = 'SELECT ' . $columns . ' FROM ' . table_prefix . "logs AS l\n"
   165          . "  LEFT JOIN " . table_prefix . "users AS u\n"
   165  				. "  LEFT JOIN " . table_prefix . "users AS u\n"
   166          . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   166  				. "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   167          . "  WHERE log_type = 'page' AND is_draft != 1$where_extra\n"
   167  				. "  WHERE log_type = 'page' AND is_draft != 1$where_extra\n"
   168          . "  GROUP BY log_id, action, page_id, namespace, page_text, author, author_uid, username, time_id, edit_summary, minor_edit\n"
   168  				. "  GROUP BY log_id, action, page_id, namespace, page_text, author, author_uid, username, time_id, edit_summary, minor_edit\n"
   169          . "  ORDER BY time_id DESC $limit;";
   169  				. "  ORDER BY time_id DESC $limit;";
   170     
   170 		
   171     return $sql;
   171 		return $sql;
   172   }
   172 	}
   173   
   173 	
   174   /**
   174 	/**
   175    * Get data!
   175  	* Get data!
   176    * @param int Offset, defaults to 0
   176  	* @param int Offset, defaults to 0
   177    * @param int Page size, if 0 (default) returns entire table (danger Will Robinson!)
   177  	* @param int Page size, if 0 (default) returns entire table (danger Will Robinson!)
   178    * @return array
   178  	* @return array
   179    */
   179  	*/
   180   
   180 	
   181   public function get_data($offset = 0, $page_size = 0)
   181 	public function get_data($offset = 0, $page_size = 0)
   182   {
   182 	{
   183     global $db, $session, $paths, $session, $plugins; // Common objects
   183 		global $db, $session, $paths, $session, $plugins; // Common objects
   184     $sql = $this->build_sql($offset, $page_size);
   184 		$sql = $this->build_sql($offset, $page_size);
   185     if ( !$db->sql_query($sql) )
   185 		if ( !$db->sql_query($sql) )
   186       $db->_die();
   186 			$db->_die();
   187     
   187 		
   188     $return = array();
   188 		$return = array();
   189     $deplist = array();
   189 		$deplist = array();
   190     $idlist = array();
   190 		$idlist = array();
   191     while ( $row = $db->fetchrow() )
   191 		while ( $row = $db->fetchrow() )
   192     {
   192 		{
   193       $return[ $row['log_id'] ] = $row;
   193 			$return[ $row['log_id'] ] = $row;
   194       if ( $row['action'] === 'edit' )
   194 			if ( $row['action'] === 'edit' )
   195       {
   195 			{
   196         // This is a page revision; its parent needs to be found
   196 				// This is a page revision; its parent needs to be found
   197         $pagekey = serialize(array($row['page_id'], $row['namespace']));
   197 				$pagekey = serialize(array($row['page_id'], $row['namespace']));
   198         $deplist[$pagekey] = "( page_id = '" . $db->escape($row['page_id']) . "' AND namespace = '" . $db->escape($row['namespace']) . "' AND log_id < {$row['log_id']} )";
   198 				$deplist[$pagekey] = "( page_id = '" . $db->escape($row['page_id']) . "' AND namespace = '" . $db->escape($row['namespace']) . "' AND log_id < {$row['log_id']} )";
   199         // if we already have a revision from this page in the dataset, we've found its parent
   199 				// if we already have a revision from this page in the dataset, we've found its parent
   200         if ( isset($idlist[$pagekey]) )
   200 				if ( isset($idlist[$pagekey]) )
   201         {
   201 				{
   202           $child =& $return[ $idlist[$pagekey] ];
   202 					$child =& $return[ $idlist[$pagekey] ];
   203           $child['parent_size'] = $row['revision_size'];
   203 					$child['parent_size'] = $row['revision_size'];
   204           $child['parent_revid'] = $row['log_id'];
   204 					$child['parent_revid'] = $row['log_id'];
   205           $child['parent_time'] = $row['time_id'];
   205 					$child['parent_time'] = $row['time_id'];
   206           unset($child);
   206 					unset($child);
   207         }
   207 				}
   208         $idlist[$pagekey] = $row['log_id'];
   208 				$idlist[$pagekey] = $row['log_id'];
   209       }
   209 			}
   210     }
   210 		}
   211     
   211 		
   212     // Second query fetches all parent revision data
   212 		// Second query fetches all parent revision data
   213     // (maybe we have no edits?? check deplist)
   213 		// (maybe we have no edits?? check deplist)
   214     
   214 		
   215     if ( !empty($deplist) )
   215 		if ( !empty($deplist) )
   216     {
   216 		{
   217       // FIXME: inefficient. damn GROUP BY for not obeying ORDER BY, it means we can't group and instead have to select
   217 			// FIXME: inefficient. damn GROUP BY for not obeying ORDER BY, it means we can't group and instead have to select
   218       // all previous revisions of page X and discard all but the first one we find.
   218 			// all previous revisions of page X and discard all but the first one we find.
   219       $where_extra = implode("\n    OR ", $deplist);
   219 			$where_extra = implode("\n    OR ", $deplist);
   220       $sql = 'SELECT log_id, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, time_id FROM ' . table_prefix . "logs\n"
   220 			$sql = 'SELECT log_id, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, time_id FROM ' . table_prefix . "logs\n"
   221            . "  WHERE log_type = 'page' AND action = 'edit'\n  AND ( $where_extra )\n"
   221  					. "  WHERE log_type = 'page' AND action = 'edit'\n  AND ( $where_extra )\n"
   222            // . "  GROUP BY page_id, namespace\n"
   222  					// . "  GROUP BY page_id, namespace\n"
   223            . "  ORDER BY log_id DESC;";
   223  					. "  ORDER BY log_id DESC;";
   224       if ( !$db->sql_query($sql) )
   224 			if ( !$db->sql_query($sql) )
   225         $db->_die();
   225 				$db->_die();
   226       
   226 			
   227       while ( $row = $db->fetchrow() )
   227 			while ( $row = $db->fetchrow() )
   228       {
   228 			{
   229         $pagekey = serialize(array($row['page_id'], $row['namespace']));
   229 				$pagekey = serialize(array($row['page_id'], $row['namespace']));
   230         if ( isset($idlist[$pagekey]) )
   230 				if ( isset($idlist[$pagekey]) )
   231         {
   231 				{
   232           $child =& $return[ $idlist[$pagekey] ];
   232 					$child =& $return[ $idlist[$pagekey] ];
   233           $child['parent_size'] = $row['revision_size'];
   233 					$child['parent_size'] = $row['revision_size'];
   234           $child['parent_revid'] = $row['log_id'];
   234 					$child['parent_revid'] = $row['log_id'];
   235           $child['parent_time'] = $row['time_id'];
   235 					$child['parent_time'] = $row['time_id'];
   236           unset($child, $idlist[$pagekey]);
   236 					unset($child, $idlist[$pagekey]);
   237         }
   237 				}
   238       }
   238 			}
   239     }
   239 		}
   240     
   240 		
   241     // final iteration goes through all edits and if there's not info on the parent, sets to 0. It also calculates size change.
   241 		// final iteration goes through all edits and if there's not info on the parent, sets to 0. It also calculates size change.
   242     foreach ( $return as &$row )
   242 		foreach ( $return as &$row )
   243     {
   243 		{
   244       if ( $row['action'] === 'edit' && !isset($row['parent_revid']) )
   244 			if ( $row['action'] === 'edit' && !isset($row['parent_revid']) )
   245       {
   245 			{
   246         $row['parent_revid'] = 0;
   246 				$row['parent_revid'] = 0;
   247         $row['parent_size'] = 0;
   247 				$row['parent_size'] = 0;
   248       }
   248 			}
   249       if ( $row['action'] === 'edit' )
   249 			if ( $row['action'] === 'edit' )
   250       {
   250 			{
   251         $row['size_delta'] = $row['revision_size'] - $row['parent_size'];
   251 				$row['size_delta'] = $row['revision_size'] - $row['parent_size'];
   252       }
   252 			}
   253     }
   253 		}
   254     
   254 		
   255     return array_values($return);
   255 		return array_values($return);
   256   }
   256 	}
   257   
   257 	
   258   /**
   258 	/**
   259    * Get the number of rows that will be in the result set.
   259  	* Get the number of rows that will be in the result set.
   260    * @return int
   260  	* @return int
   261    */
   261  	*/
   262   
   262 	
   263   public function get_row_count()
   263 	public function get_row_count()
   264   {
   264 	{
   265     global $db, $session, $paths, $session, $plugins; // Common objects
   265 		global $db, $session, $paths, $session, $plugins; // Common objects
   266     
   266 		
   267     if ( !$db->sql_query( $this->build_sql(0, 0, true) ) )
   267 		if ( !$db->sql_query( $this->build_sql(0, 0, true) ) )
   268       $db->_die();
   268 			$db->_die();
   269     
   269 		
   270     list($count) = $db->fetchrow_num();
   270 		list($count) = $db->fetchrow_num();
   271     return $count;
   271 		return $count;
   272   }
   272 	}
   273   
   273 	
   274   /**
   274 	/**
   275    * Returns the list of criteria
   275  	* Returns the list of criteria
   276    * @return array
   276  	* @return array
   277    */
   277  	*/
   278   
   278 	
   279   public function get_criteria()
   279 	public function get_criteria()
   280   {
   280 	{
   281     return $this->criteria;
   281 		return $this->criteria;
   282   }
   282 	}
   283   
   283 	
   284   /**
   284 	/**
   285    * Formats a result row into pretty HTML.
   285  	* Formats a result row into pretty HTML.
   286    * @param array dataset from LogDisplay::get_data()
   286  	* @param array dataset from LogDisplay::get_data()
   287    * @param bool If true (default), shows action buttons.
   287  	* @param bool If true (default), shows action buttons.
   288    * @param bool If true (default), shows page title; good for integrated displays
   288  	* @param bool If true (default), shows page title; good for integrated displays
   289    * @static
   289  	* @static
   290    * @return string
   290  	* @return string
   291    */
   291  	*/
   292   
   292 	
   293   public static function render_row($row, $show_buttons = true, $show_pagetitle = true)
   293 	public static function render_row($row, $show_buttons = true, $show_pagetitle = true)
   294   {
   294 	{
   295     global $db, $session, $paths, $session, $plugins; // Common objects
   295 		global $db, $session, $paths, $session, $plugins; // Common objects
   296     global $lang;
   296 		global $lang;
   297     
   297 		
   298     $html = '';
   298 		$html = '';
   299     
   299 		
   300     $pagekey = ( isset($paths->nslist[$row['namespace']]) ) ? $paths->nslist[$row['namespace']] . $row['page_id'] : $row['namespace'] . ':' . $row['page_id'];
   300 		$pagekey = ( isset($paths->nslist[$row['namespace']]) ) ? $paths->nslist[$row['namespace']] . $row['page_id'] : $row['namespace'] . ':' . $row['page_id'];
   301     $pagekey = sanitize_page_id($pagekey);
   301 		$pagekey = sanitize_page_id($pagekey);
   302     
   302 		
   303     // diff button
   303 		// diff button
   304     if ( $show_buttons )
   304 		if ( $show_buttons )
   305     {
   305 		{
   306       if ( $row['action'] == 'edit' && !empty($row['parent_revid']) )
   306 			if ( $row['action'] == 'edit' && !empty($row['parent_revid']) )
   307       {
   307 			{
   308         $html .= '(';
   308 				$html .= '(';
   309         $ispage = isPage($pagekey);
   309 				$ispage = isPage($pagekey);
   310         
   310 				
   311         if ( $ispage )
   311 				if ( $ispage )
   312           $html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=diff&diff1={$row['parent_revid']}&diff2={$row['log_id']}", true) . '">';
   312 					$html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=diff&diff1={$row['parent_revid']}&diff2={$row['log_id']}", true) . '">';
   313         
   313 				
   314         $html .= $lang->get('pagetools_rc_btn_diff');
   314 				$html .= $lang->get('pagetools_rc_btn_diff');
   315         
   315 				
   316         if ( $ispage )
   316 				if ( $ispage )
   317           $html .= '</a>';
   317 					$html .= '</a>';
   318         
   318 				
   319         if ( $ispage )
   319 				if ( $ispage )
   320           $html .= ', <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "oldid={$row['log_id']}", true) . '">';
   320 					$html .= ', <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "oldid={$row['log_id']}", true) . '">';
   321         
   321 				
   322         $html .= $lang->get('pagetools_rc_btn_view');
   322 				$html .= $lang->get('pagetools_rc_btn_view');
   323         
   323 				
   324         if ( $ispage )
   324 				if ( $ispage )
   325           $html .= '</a>';
   325 					$html .= '</a>';
   326         
   326 				
   327         if ( $row['parent_revid'] > 0 && isPage($pagekey) )
   327 				if ( $row['parent_revid'] > 0 && isPage($pagekey) )
   328         {
   328 				{
   329           $html .= ', <a href="' . makeUrlNS($row['namespace'], $row['page_id'], false, true) . '#do:edit;rev:' . $row['parent_revid'] . '">' . $lang->get('pagetools_rc_btn_undo') . '</a>';
   329 					$html .= ', <a href="' . makeUrlNS($row['namespace'], $row['page_id'], false, true) . '#do:edit;rev:' . $row['parent_revid'] . '">' . $lang->get('pagetools_rc_btn_undo') . '</a>';
   330         }
   330 				}
   331         $html .= ') ';
   331 				$html .= ') ';
   332       }
   332 			}
   333       else if ( $row['action'] != 'edit' && ( isPage($pagekey) || $row['action'] == 'delete' ) )
   333 			else if ( $row['action'] != 'edit' && ( isPage($pagekey) || $row['action'] == 'delete' ) )
   334       {
   334 			{
   335         $html .= '(';
   335 				$html .= '(';
   336         $html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['log_id']}", true). '">' . $lang->get('pagetools_rc_btn_undo') . '</a>';
   336 				$html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['log_id']}", true). '">' . $lang->get('pagetools_rc_btn_undo') . '</a>';
   337         $html .= ') ';
   337 				$html .= ') ';
   338       }
   338 			}
   339       
   339 			
   340       // hist button
   340 			// hist button
   341       $html .= '(';
   341 			$html .= '(';
   342       if ( isPage($pagekey) )
   342 			if ( isPage($pagekey) )
   343       {
   343 			{
   344         $html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=history", true) . '">';
   344 				$html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=history", true) . '">';
   345       }
   345 			}
   346       $html .= $lang->get('pagetools_rc_btn_hist');
   346 			$html .= $lang->get('pagetools_rc_btn_hist');
   347       if ( isPage($pagekey) )
   347 			if ( isPage($pagekey) )
   348       {
   348 			{
   349         $html .= '</a>';
   349 				$html .= '</a>';
   350       }
   350 			}
   351       $html .= ') . . ';
   351 			$html .= ') . . ';
   352     }
   352 		}
   353     
   353 		
   354     if ( $show_pagetitle )
   354 		if ( $show_pagetitle )
   355     {
   355 		{
   356       // new page?
   356 			// new page?
   357       if ( $row['action'] == 'edit' && empty($row['parent_revid']) )
   357 			if ( $row['action'] == 'edit' && empty($row['parent_revid']) )
   358       {
   358 			{
   359         $html .= '<b>N</b> ';
   359 				$html .= '<b>N</b> ';
   360       }
   360 			}
   361       // minor edit?
   361 			// minor edit?
   362       if ( $row['action'] == 'edit' && $row['minor_edit'] )
   362 			if ( $row['action'] == 'edit' && $row['minor_edit'] )
   363       {
   363 			{
   364         $html .= '<b>m</b> ';
   364 				$html .= '<b>m</b> ';
   365       }
   365 			}
   366       
   366 			
   367       // link to the page
   367 			// link to the page
   368       $cls = ( isPage($pagekey) ) ? '' : ' class="wikilink-nonexistent"';
   368 			$cls = ( isPage($pagekey) ) ? '' : ' class="wikilink-nonexistent"';
   369       $html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '"' . $cls . '>' . htmlspecialchars(get_page_title_ns($row['page_id'], $row['namespace'])) . '</a>; ';
   369 			$html .= '<a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '"' . $cls . '>' . htmlspecialchars(get_page_title_ns($row['page_id'], $row['namespace'])) . '</a>; ';
   370     }
   370 		}
   371     
   371 		
   372     // date
   372 		// date
   373     $today = time() - ( time() % 86400 );
   373 		$today = time() - ( time() % 86400 );
   374     $date = MemberlistFormatter::format_date($row['time_id']) . ' ';
   374 		$date = MemberlistFormatter::format_date($row['time_id']) . ' ';
   375     $date .= date('h:i:s', $row['time_id']);
   375 		$date .= date('h:i:s', $row['time_id']);
   376     $html .= "$date . . ";
   376 		$html .= "$date . . ";
   377     
   377 		
   378     // size counter
   378 		// size counter
   379     if ( $row['action'] == 'edit' )
   379 		if ( $row['action'] == 'edit' )
   380     {
   380 		{
   381       $css = self::get_css($row['size_delta']);
   381 			$css = self::get_css($row['size_delta']);
   382       $size_change = number_format($row['size_delta']);
   382 			$size_change = number_format($row['size_delta']);
   383       if ( substr($size_change, 0, 1) != '-' )
   383 			if ( substr($size_change, 0, 1) != '-' )
   384         $size_change = "+$size_change";
   384 				$size_change = "+$size_change";
   385       
   385 			
   386       $html .= "<span style=\"$css\">({$size_change})</span>";
   386 			$html .= "<span style=\"$css\">({$size_change})</span>";
   387       $html .= ' . . ';
   387 			$html .= ' . . ';
   388     }
   388 		}
   389     
   389 		
   390     // link to userpage
   390 		// link to userpage
   391     $real_username = $row['author_uid'] > 1 && !empty($row['username']) ? $row['username'] : $row['author'];
   391 		$real_username = $row['author_uid'] > 1 && !empty($row['username']) ? $row['username'] : $row['author'];
   392     $cls = ( isPage($paths->nslist['User'] . $real_username) ) ? '' : ' class="wikilink-nonexistent"';
   392 		$cls = ( isPage($paths->nslist['User'] . $real_username) ) ? '' : ' class="wikilink-nonexistent"';
   393     $rank_info = $session->get_user_rank($row['author_uid']);
   393 		$rank_info = $session->get_user_rank($row['author_uid']);
   394     $html .= '<a style="' . $rank_info['rank_style'] . '" href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '"' . $cls . '>' . htmlspecialchars($real_username) . '</a> ';
   394 		$html .= '<a style="' . $rank_info['rank_style'] . '" href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '"' . $cls . '>' . htmlspecialchars($real_username) . '</a> ';
   395     $html .= '(';
   395 		$html .= '(';
   396     $html .= '<a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/To/' . sanitize_page_id($real_username), false, true) . '">';
   396 		$html .= '<a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/To/' . sanitize_page_id($real_username), false, true) . '">';
   397     $html .= $lang->get('pagetools_rc_btn_pm');
   397 		$html .= $lang->get('pagetools_rc_btn_pm');
   398     $html .= '</a>, ';
   398 		$html .= '</a>, ';
   399     $html .= '<a href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '#do:comments">';
   399 		$html .= '<a href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '#do:comments">';
   400     $html .= $lang->get('pagetools_rc_btn_usertalk');
   400 		$html .= $lang->get('pagetools_rc_btn_usertalk');
   401     $html .= '</a>';
   401 		$html .= '</a>';
   402     $html .= ') . . ';
   402 		$html .= ') . . ';
   403     
   403 		
   404     // Edit summary
   404 		// Edit summary
   405     
   405 		
   406     if ( $row['action'] == 'edit' )
   406 		if ( $row['action'] == 'edit' )
   407     {
   407 		{
   408       $html .= '<i>(';
   408 			$html .= '<i>(';
   409       if ( empty($row['edit_summary']) )
   409 			if ( empty($row['edit_summary']) )
   410       {
   410 			{
   411         $html .= '<span style="color: #808080;">' . $lang->get('history_summary_none_given') . '</span>';
   411 				$html .= '<span style="color: #808080;">' . $lang->get('history_summary_none_given') . '</span>';
   412       }
   412 			}
   413       else
   413 			else
   414       {
   414 			{
   415         $html .= RenderMan::parse_internal_links(htmlspecialchars($row['edit_summary']));
   415 				$html .= RenderMan::parse_internal_links(htmlspecialchars($row['edit_summary']));
   416       }
   416 			}
   417       $html .= ')</i>';
   417 			$html .= ')</i>';
   418     }
   418 		}
   419     else
   419 		else
   420     {
   420 		{
   421       switch($row['action'])
   421 			switch($row['action'])
   422       {
   422 			{
   423         default:
   423 				default:
   424           $html .= $row['action'];
   424 					$html .= $row['action'];
   425           break;
   425 					break;
   426         case 'rename':
   426 				case 'rename':
   427           $html .= $lang->get('log_action_rename', array('old_name' => htmlspecialchars($row['edit_summary'])));
   427 					$html .= $lang->get('log_action_rename', array('old_name' => htmlspecialchars($row['edit_summary'])));
   428           break;
   428 					break;
   429         case 'create':
   429 				case 'create':
   430           $html .= $lang->get('log_action_create');
   430 					$html .= $lang->get('log_action_create');
   431           break;
   431 					break;
   432         case 'votereset':
   432 				case 'votereset':
   433           $html .= $lang->get('log_action_votereset', array('num_votes' => $row['edit_summary'], 'plural' => ( intval($row['edit_summary']) == 1 ? '' : $lang->get('meta_plural'))));
   433 					$html .= $lang->get('log_action_votereset', array('num_votes' => $row['edit_summary'], 'plural' => ( intval($row['edit_summary']) == 1 ? '' : $lang->get('meta_plural'))));
   434           break;
   434 					break;
   435         case 'prot':
   435 				case 'prot':
   436         case 'unprot':
   436 				case 'unprot':
   437         case 'semiprot':
   437 				case 'semiprot':
   438         case 'delete':
   438 				case 'delete':
   439         case 'reupload':
   439 				case 'reupload':
   440           $stringmap = array(
   440 					$stringmap = array(
   441             'prot' => 'log_action_protect_full',
   441 						'prot' => 'log_action_protect_full',
   442             'unprot' => 'log_action_protect_none',
   442 						'unprot' => 'log_action_protect_none',
   443             'semiprot' => 'log_action_protect_semi',
   443 						'semiprot' => 'log_action_protect_semi',
   444             'delete' => 'log_action_delete',
   444 						'delete' => 'log_action_delete',
   445             'reupload' => 'log_action_reupload'
   445 						'reupload' => 'log_action_reupload'
   446           );
   446 					);
   447         
   447 				
   448         if ( $row['edit_summary'] === '__REVERSION__' )
   448 				if ( $row['edit_summary'] === '__REVERSION__' )
   449           $reason = '<span style="color: #808080;">' . $lang->get('log_msg_reversion') . '</span>';
   449 					$reason = '<span style="color: #808080;">' . $lang->get('log_msg_reversion') . '</span>';
   450         else if ( $row['action'] == 'reupload' && $row['edit_summary'] === '__ROLLBACK__' )
   450 				else if ( $row['action'] == 'reupload' && $row['edit_summary'] === '__ROLLBACK__' )
   451           $reason = '<span style="color: #808080;">' . $lang->get('log_msg_file_restored') . '</span>';
   451 					$reason = '<span style="color: #808080;">' . $lang->get('log_msg_file_restored') . '</span>';
   452         else
   452 				else
   453           $reason = ( !empty($row['edit_summary']) ) ? htmlspecialchars($row['edit_summary']) : '<span style="color: #808080;">' . $lang->get('log_msg_no_reason_provided') . '</span>';
   453 					$reason = ( !empty($row['edit_summary']) ) ? htmlspecialchars($row['edit_summary']) : '<span style="color: #808080;">' . $lang->get('log_msg_no_reason_provided') . '</span>';
   454         
   454 				
   455         $html .= $lang->get($stringmap[$row['action']], array('reason' => $reason));
   455 				$html .= $lang->get($stringmap[$row['action']], array('reason' => $reason));
   456       }
   456 			}
   457     }
   457 		}
   458     
   458 		
   459     return $html;
   459 		return $html;
   460   }
   460 	}
   461   
   461 	
   462   /**
   462 	/**
   463    * Return CSS blurb for size delta
   463  	* Return CSS blurb for size delta
   464    * @return string
   464  	* @return string
   465    * @static
   465  	* @static
   466    * @access private
   466  	* @access private
   467    */
   467  	*/
   468   
   468 	
   469   private static function get_css($change_size)
   469 	private static function get_css($change_size)
   470   {
   470 	{
   471     // Hardly changed at all? Return a gray
   471 		// Hardly changed at all? Return a gray
   472     if ( $change_size <= 5 && $change_size >= -5 )
   472 		if ( $change_size <= 5 && $change_size >= -5 )
   473       return 'color: #808080;';
   473 			return 'color: #808080;';
   474     // determine saturation based on size of change (1-500 bytes)
   474 		// determine saturation based on size of change (1-500 bytes)
   475     $change_abs = abs($change_size);
   475 		$change_abs = abs($change_size);
   476     $index = 0x70 * ( $change_abs / 500 );
   476 		$index = 0x70 * ( $change_abs / 500 );
   477     if ( $index > 0x70 )
   477 		if ( $index > 0x70 )
   478       $index = 0x70;
   478 			$index = 0x70;
   479     $index = $index + 0x40;
   479 		$index = $index + 0x40;
   480     $index = dechex($index);
   480 		$index = dechex($index);
   481     if ( strlen($index) < 2 )
   481 		if ( strlen($index) < 2 )
   482       $index = "0$index";
   482 			$index = "0$index";
   483     $css = ( $change_size > 0 ) ? "color: #00{$index}00;" : "color: #{$index}0000;";
   483 		$css = ( $change_size > 0 ) ? "color: #00{$index}00;" : "color: #{$index}0000;";
   484     if ( $change_abs > 500 )
   484 		if ( $change_abs > 500 )
   485       $css .= ' font-weight: bold;';
   485 			$css .= ' font-weight: bold;';
   486     return $css;
   486 		return $css;
   487   }
   487 	}
   488 }
   488 }
   489  
   489  
   490 ?>
   490 ?>