From: Michael M Slusarz Date: Thu, 29 Jan 2009 04:18:01 +0000 (-0700) Subject: Cleanups to Chora::. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=297da5fbffc44c0041f2a3b9c35039f847774a82;p=horde.git Cleanups to Chora::. --- diff --git a/chora/browse.php b/chora/browse.php index 6d0e56934..3ba7155e0 100644 --- a/chora/browse.php +++ b/chora/browse.php @@ -33,7 +33,7 @@ if ($atdir) { : sprintf(_("Source Directory of /%s"), $where); $extraLink = $VC->hasFeature('deleted') - ? Horde::widget(Chora::url('', $where . '/', array('sa' => ($acts['sa'] ? 0 : 1))), $acts['sa'] ? _("Hide Deleted Files") : _("Show Deleted Files"), 'widget', '', '', $acts['sa'] ? _("Hide _Deleted Files") : _("Show _Deleted Files")) + ? Horde::widget(Chora::url('browse', $where . '/', array('sa' => ($acts['sa'] ? 0 : 1))), $acts['sa'] ? _("Hide Deleted Files") : _("Show Deleted Files"), 'widget', '', '', $acts['sa'] ? _("Hide _Deleted Files") : _("Show _Deleted Files")) : ''; $umap = array( @@ -48,7 +48,7 @@ if ($atdir) { if ($acts['sbt'] == $val) { $arg['ord'] = !$acts['ord']; } - $url[$key] = Chora::url('', $where . '/', $arg); + $url[$key] = Chora::url('browse', $where . '/', $arg); } /* Print out the directory header. */ @@ -63,7 +63,7 @@ if ($atdir) { /* Unless we're at the top, display the 'back' bar. */ if ($where != '') { - $url = Chora::url('', preg_replace('|[^/]+$|', '', $where)); + $url = Chora::url('browse', preg_replace('|[^/]+$|', '', $where)); require CHORA_TEMPLATES . '/directory/back.inc'; } @@ -74,7 +74,7 @@ if ($atdir) { if ($conf['hide_restricted'] && Chora::isRestricted($currentDir)) { continue; } - $url = Chora::url('', "$where/$currentDir/"); + $url = Chora::url('browse', "$where/$currentDir/"); $currDir = Text::htmlAllSpaces($currentDir); require CHORA_TEMPLATES . '/directory/dir.inc'; } @@ -102,7 +102,7 @@ if ($atdir) { $attic = $currFile->isDeleted(); $fileName = $where . ($attic ? '/' . 'Attic' : '') . '/' . $realname; $name = Text::htmlAllSpaces($realname); - $url = Chora::url('', $fileName); + $url = Chora::url('browse', $fileName); $readableDate = Chora::readableTime($date); if ($log) { $shortLog = str_replace("\n", ' ', @@ -131,7 +131,7 @@ try { $title = sprintf(_("Revisions for %s"), $where); -$extraLink = Chora::getFileViews(); +$extraLink = Chora::getFileViews($where, 'browse'); $logs = $fl->queryLogs(); $first = end($logs); $diffValueLeft = $first->queryRevision(); diff --git a/chora/cvsgraph.php b/chora/cvsgraph.php index 85fe68df7..c8eb41fca 100644 --- a/chora/cvsgraph.php +++ b/chora/cvsgraph.php @@ -16,7 +16,7 @@ require_once dirname(__FILE__) . '/lib/base.php'; // Exit if cvsgraph isn't active or it's not supported. if (empty($conf['paths']['cvsgraph']) || !$VC->hasFeature('branches')) { - header('Location: ' . Chora::url('', $where)); + header('Location: ' . Chora::url('browse', $where)); exit; } @@ -49,7 +49,7 @@ if (Util::getFormData('show_image')) { } else { // Display the wrapper page for the image. $title = sprintf(_("Graph for %s"), Text::htmlAllSpaces($where)); - $extraLink = Chora::getFileViews(); + $extraLink = Chora::getFileViews($where, 'cvsgraph'); require CHORA_TEMPLATES . '/common-header.inc'; require CHORA_TEMPLATES . '/menu.inc'; @@ -61,7 +61,7 @@ if (Util::getFormData('show_image')) { 'M' => 'graphMap', 'r' => $root, '0' => '&', - '1' => Chora::url('', $where, array('dummy' => 'true')), + '1' => Chora::url('browse', $where, array('dummy' => 'true')), '2' => Chora::url('diff', $where, array('dummy' =>'true')), '3' => Chora::url('co', $where, array('dummy' => 'true')), ); diff --git a/chora/history.php b/chora/history.php index adf38eb20..1962f07a2 100644 --- a/chora/history.php +++ b/chora/history.php @@ -125,7 +125,7 @@ foreach ($grid as $cols) { } $title = sprintf(_("Source Branching View for %s"), Text::htmlallspaces($where)); -$extraLink = Chora::getFileViews(); +$extraLink = Chora::getFileViews($where, 'history'); require CHORA_TEMPLATES . '/common-header.inc'; require CHORA_TEMPLATES . '/menu.inc'; diff --git a/chora/lib/Block/tree_menu.php b/chora/lib/Block/tree_menu.php index 2aa717ea8..f2cc9e7b7 100644 --- a/chora/lib/Block/tree_menu.php +++ b/chora/lib/Block/tree_menu.php @@ -3,35 +3,33 @@ $block_name = _("Menu List"); $block_type = 'tree'; -class Horde_Block_chora_tree_menu extends Horde_Block { - +class Horde_Block_chora_tree_menu extends Horde_Block +{ var $_app = 'chora'; function _buildTree(&$tree, $indent = 0, $parent = null) { - global $perms, $sourceroots; - define('CHORA_ERROR_HANDLER', true); require_once dirname(__FILE__) . '/../base.php'; $arr = array(); - asort($sourceroots); + asort($GLOBALS['sourceroots']); + foreach ($sourceroots as $key => $val) { - if ((!$perms->exists('chora:sourceroots:' . $key) || - $perms->hasPermission('chora:sourceroots:' . $key, - Auth::getAuth(), - PERMS_READ | PERMS_SHOW))) { + if (Chora::checkPerms($key)) { $tree->addNode($parent . $key, - $parent, - $val['name'], - $indent + 1, - false, - array('icon' => 'folder.png', - 'icondir' => $registry->getImageDir('horde') . '/tree', - 'url' => Chora::url('', '', array('rt' => $key)))); + $parent, + $val['name'], + $indent + 1, + false, + array( + 'icon' => 'folder.png', + 'icondir' => $GLOBALS['registry']->getImageDir('horde') . '/tree', + 'url' => Chora::url('browse', '', array('rt' => $key)) + ) + ); } } - } } diff --git a/chora/lib/Chora.php b/chora/lib/Chora.php index 591ff0acf..85ee6a011 100644 --- a/chora/lib/Chora.php +++ b/chora/lib/Chora.php @@ -8,73 +8,41 @@ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. * * @author Anil Madhavapeddy + * @author Michael Slusarz * @package Chora */ class Chora { /** - * Return a text description of how long its been since the file - * has been last modified. + * Cached data for isRestricted(). * - * @param integer $date Number of seconds since epoch we wish to display. - * @param boolean $long If true, display a more verbose date. - * - * @return string The human-readable date. + * @var array */ - static public function readableTime($date, $long = false) - { - static $time, $desc, $breaks; - - /* Initialize popular variables. */ - if (!isset($time)) { - $time = time(); - $desc = array( - 1 => array(_("second"), _("seconds")), - 60 => array(_("minute"), _("minutes")), - 3600 => array(_("hour"), _("hours")), - 86400 => array(_("day"), _("days")), - 604800 => array(_("week"), _("weeks")), - 2628000 => array(_("month"), _("months")), - 31536000 => array(_("year"), _("years")) - ); - $breaks = array_keys($desc); - } - - $i = count($breaks); - $secs = $time - $date; - - if ($secs < 2) { - return _("very little time"); - } - - while (--$i && $i && $breaks[$i] * 2 > $secs); + static public $restricted; - $break = $breaks[$i]; - - $val = intval($secs / $break); - $retval = $val . ' ' . ($val > 1 ? $desc[$break][1] : $desc[$break][0]); - if ($long && $i > 0) { - $rest = $secs % $break; - $break = $breaks[--$i]; - $rest = (int)($rest / $break); - if ($rest > 0) { - $resttime = $rest . ' ' . ($rest > 1 ? $desc[$break][1] : $desc[$break][0]); - $retval .= ', ' . $resttime; - } - } + /** + * Cached data for readableTime(). + * + * @var array + */ + static public $rtcache; - return $retval; - } + /** + * Cached data for formatDate(). + * + * @var string + */ + static public $fdcache; /** * Initialize global variables and objects. */ static public function initialize() { - global $acts, $defaultActs, $conf, $where, $atdir, $fullname, $prefs, - $sourceroot, $scriptName; + global $acts, $defaultActs, $where, $atdir, $fullname, $sourceroot; - $sourceroots = Chora::sourceroots(); + $GLOBALS['sourceroots'] = Horde::loadConfiguration('sourceroots.php', 'sourceroots'); + $sourceroots = self::sourceroots(); /** * Variables we wish to propagate across web pages @@ -87,22 +55,27 @@ class Chora * XXX: Rewrite this propagation code, since it sucks - avsm */ $defaultActs = array( - 'sbt' => constant($conf['options']['defaultsort']), + 'sbt' => constant($GLOBALS['conf']['options']['defaultsort']), 'sa' => 0, 'ord' => Horde_Vcs::SORT_ASCENDING, 'ws' => 1 ); - /* Use the last sourceroot used as the default value if the user - * has that preference. */ - $remember_last_file = $prefs->getValue('remember_last_file'); - if ($remember_last_file) { - $last_file = $prefs->getValue('last_file') ? $prefs->getValue('last_file') : null; - $last_sourceroot = $prefs->getValue('last_sourceroot') ? $prefs->getValue('last_sourceroot') : null; - } - - if ($remember_last_file && !empty($last_sourceroot) && - is_array(@$sourceroots[$last_sourceroot])) { + /* Use the last sourceroot used as the default value if the user has + * that preference. */ + if ($remember = $GLOBALS['prefs']->getValue('remember_last_file')) { + $last_file = $GLOBALS['prefs']->getValue('last_file') + ? $GLOBALS['prefs']->getValue('last_file') + : null; + $last_sourceroot = $GLOBALS['prefs']->getValue('last_sourceroot') + ? $GLOBALS['prefs']->getValue('last_sourceroot') + : null; + } + + if ($remember && + !empty($last_sourceroot) && + !empty($sourceroots[$last_sourceroot]) && + is_array($sourceroots[$last_sourceroot])) { $defaultActs['rt'] = $last_sourceroot; } else { foreach ($sourceroots as $key => $val) { @@ -112,59 +85,54 @@ class Chora } } - /* See if any have been passed as GET variables, and if so, - * assign them into the acts array. */ + /* See if any have been passed as GET variables, and if so, assign + * them into the acts array. */ $acts = array(); foreach ($defaultActs as $key => $default) { $acts[$key] = Util::getFormData($key, $default); } if (!isset($sourceroots[$acts['rt']])) { - Chora::fatal(_("Malformed URL"), '400 Bad Request'); + self::fatal(_("Malformed URL"), '400 Bad Request'); } $sourcerootopts = $sourceroots[$acts['rt']]; $sourceroot = $acts['rt']; // Cache. - if (empty($conf['caching'])) { + if (empty($GLOBALS['conf']['caching'])) { $cache = null; } else { - $cache = &Horde_Cache::singleton($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver'])); + $cache = &Horde_Cache::singleton($GLOBALS['conf']['cache']['driver'], Horde::getDriverConfig('cache', $GLOBALS['conf']['cache']['driver'])); } - $conf['paths']['temp'] = Horde::getTempDir(); + $GLOBALS['conf']['paths']['temp'] = Horde::getTempDir(); + try { $GLOBALS['VC'] = Horde_Vcs::factory(String::ucfirst($sourcerootopts['type']), array('cache' => $cache, 'sourceroot' => $sourcerootopts['location'], - 'paths' => $conf['paths'], + 'paths' => $GLOBALS['conf']['paths'], 'username' => isset($sourcerootopts['username']) ? $sourcerootopts['username'] : '', 'password' => isset($sourcerootopts['password']) ? $sourcerootopts['password'] : '')); } catch (Horde_Vcs_Exception $e) { - Chora::fatal($e); + self::fatal($e); } - $conf['paths']['sourceroot'] = $sourcerootopts['location']; - $conf['paths']['cvsusers'] = $sourcerootopts['location'] . '/' . (isset($sourcerootopts['cvsusers']) ? $sourcerootopts['cvsusers'] : ''); - $conf['paths']['introText'] = CHORA_BASE . '/config/' . (isset($sourcerootopts['intro']) ? $sourcerootopts['intro'] : ''); - $conf['options']['introTitle'] = isset($sourcerootopts['title']) ? $sourcerootopts['title'] : ''; - $conf['options']['sourceRootName'] = $sourcerootopts['name']; + $GLOBALS['conf']['paths']['sourceroot'] = $sourcerootopts['location']; + $GLOBALS['conf']['paths']['cvsusers'] = $sourcerootopts['location'] . '/' . (isset($sourcerootopts['cvsusers']) ? $sourcerootopts['cvsusers'] : ''); + $GLOBALS['conf']['paths']['introText'] = CHORA_BASE . '/config/' . (isset($sourcerootopts['intro']) ? $sourcerootopts['intro'] : ''); + $GLOBALS['conf']['options']['introTitle'] = isset($sourcerootopts['title']) ? $sourcerootopts['title'] : ''; + $GLOBALS['conf']['options']['sourceRootName'] = $sourcerootopts['name']; - $where = Util::getFormData('f', ''); - if ($where == '') { - $where = '/'; - } + $where = Util::getFormData('f', '/'); /* Location relative to the sourceroot. */ $where = preg_replace(array('|^/|', '|\.\.|'), '', $where); - /* Location of this script (e.g. /chora/browse.php). */ - $scriptName = preg_replace(array('|^/?|', '|/$|'), array('/', ''), $_SERVER['PHP_SELF']); - /* Store last file/repository viewed, and set 'where' to * last_file if necessary. */ - if ($remember_last_file) { + if ($remember) { if (!isset($_SESSION['chora']['login'])) { $_SESSION['chora']['login'] = 0; } @@ -172,8 +140,8 @@ class Chora /* We store last_sourceroot and last_file only when we have * already displayed at least one page. */ if (!empty($_SESSION['chora']['login'])) { - $prefs->setValue('last_sourceroot', $acts['rt']); - $prefs->setValue('last_file', $where); + $GLOBALS['prefs']->setValue('last_sourceroot', $acts['rt']); + $GLOBALS['prefs']->setValue('last_file', $where); } else { /* We are displaying the first page. */ if ($last_file && !$where) { @@ -195,26 +163,30 @@ class Chora if (($sourcerootopts['type'] == 'cvs') && !@is_dir($sourcerootopts['location'])) { - Chora::fatal(_("Sourceroot not found. This could be a misconfiguration by the server administrator, or the server could be having temporary problems. Please try again later."), '500 Internal Server Error'); + self::fatal(_("Sourceroot not found. This could be a misconfiguration by the server administrator, or the server could be having temporary problems. Please try again later."), '500 Internal Server Error'); } - if (Chora::isRestricted($where)) { - Chora::fatal(sprintf(_("%s: Forbidden by server configuration"), $where), '403 Forbidden'); + if (self::isRestricted($where)) { + self::fatal(sprintf(_("%s: Forbidden by server configuration"), $where), '403 Forbidden'); } } - static public function whereMenu() + /** + * Create the breadcrumb directory listing. + * + * @param string $where The current filepath. + * + * @return string The directory string. + */ + static public function whereMenu($where) { - global $where, $atdir; - - $bar = $wherePath = ''; + $bar = ''; $dirs = explode('/', $where); $dir_count = count($dirs) - 1; foreach ($dirs as $i => $dir) { - if (!empty($dir) && ($dir != 'Attic')) { - $wherePath = str_replace('//', '/', $wherePath . '/' . $dir); - $bar .= '/ '. Text::htmlallspaces($dir) . ' '; + if (!empty($dir)) { + $bar .= '/ '. Text::htmlallspaces($dir) . ' '; } } @@ -224,87 +196,51 @@ class Chora /** * Output an error page. * - * @param string $message The verbose error message to be displayed. - * @param string $responseCode The HTTP error number (and optional text), - * for sending 404s or other codes if - * appropriate. + * @param string $message The verbose error message to be displayed. + * @param string $code The HTTP error number (and optional text), for + * sending 404s or other codes if appropriate. */ - static public function fatal($message, $responseCode = null) + static public function fatal($message, $code = null) { if (defined('CHORA_ERROR_HANDLER') && constant('CHORA_ERROR_HANDLER')) { return; } - global $registry, $conf, $notification, $browser, $prefs; - if (is_a($message, 'Horde_Vcs_Exception')) { $message = $message->getMessage(); } /* Don't store the bad file in the user's preferences. */ - $prefs->setValue('last_file', ''); + $GLOBALS['prefs']->setValue('last_file', ''); - if ($responseCode) { - header('HTTP/1.0 ' . $responseCode); + if ($code) { + header('HTTP/1.0 ' . $code); } - $notification->push($message, 'horde.error'); + $GLOBALS['notification']->push($message, 'horde.error'); require CHORA_TEMPLATES . '/common-header.inc'; require CHORA_TEMPLATES . '/menu.inc'; - require $registry->get('templates', 'horde') . '/common-footer.inc'; + require $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'; exit; } /** - * Convert a commit-name into whatever the user wants. - * - * @param string $name Account name. - * - * @return string The transformed name. - */ - static public function showAuthorName($name, $fullname = false) - { - static $users = null; - - if (is_null($users)) { - $users = $GLOBALS['VC']->getUsers($GLOBALS['conf']['paths']['cvsusers']); - } - - if (is_array($users) && isset($users[$name])) { - return '' . - htmlspecialchars($fullname ? $users[$name]['name'] : $name) . - '' . ($fullname ? ' ' . htmlspecialchars($name) . '' : ''); - } - - return htmlspecialchars($name); - } - - /** * Generate a URL that links into Chora. * - * @param string $script Name of the Chora script to link into + * @param string $script Name of the Chora script to link into. * @param string $uri The path being browsed. - * @param array $args Key/value pair of any GET parameters to append - * @param string $anchor Anchor entity name + * @param array $args Key/value pair of any GET parameters to append. + * @param string $anchor Anchor entity name. * * @return string The URL, with session information if necessary. */ - static public function url($script = '', $uri = '', $args = array(), + static public function url($script, $uri = '', $args = array(), $anchor = '') { - global $conf, $acts, $defaultActs; - - $differing = array(); - foreach ($acts as $key => $val) { - if ($val != $defaultActs[$key]) { - $differing[$key] = $val; - } - } + $arglist = self::_getArgList($GLOBALS['acts'], $GLOBALS['defaultActs'], $args); + $script .= '.php'; - $arglist = array_merge($differing, $args); - $script = $script ? $script . '.php' : 'browse.php'; - - if ($conf['options']['urls'] == 'rewrite') { + if ($GLOBALS['conf']['options']['urls'] == 'rewrite') { if ($script == 'browse.php') { $script = $uri; if (substr($script, 0, 1) == '/') { @@ -313,62 +249,69 @@ class Chora } else { $script .= '/' . $uri; } - } else { + } elseif (!empty($uri)) { $arglist['f'] = $uri; } $url = Util::addParameter(Horde::applicationUrl($script), $arglist); - if (!empty($anchor)) { - $url .= '#' . $anchor; - } - return $url; + return empty($anchor) ? $url : ($url . '#' . $anchor); } /** * Generates hidden form fields with all required parameters. * - * @param array $args Key/value pair of any POST parameters to append - * * @return string The form fields, with session information if necessary. */ - static public function formInputs($args = array()) + static public function formInputs() { - global $conf, $acts, $defaultActs; + $arglist = self::_getArgList($GLOBALS['acts'], $GLOBALS['defaultActs'], array()); + $fields = Util::formInput(); + foreach ($arglist as $key => $val) { + $fields .= ''; + } + + return $fields; + } + + /** + * TODO + */ + static protected function _getArgList($acts, $defaultActs, $args) + { $differing = array(); + foreach ($acts as $key => $val) { if ($val != $defaultActs[$key]) { $differing[$key] = $val; } } - $arglist = array_merge($differing, $args); - - $fields = Util::formInput(); - foreach ($arglist as $key => $val) { - $fields .= ''; - } + return array_merge($differing, $args); + } - return $fields; + /** + * TODO + */ + static public function checkPerms($key) + { + return (!$GLOBALS['perms']->exists('chora:sourceroots:' . $key) || + $GLOBALS['perms']->hasPermission('chora:sourceroots:' . $key, Auth::getAuth(), PERMS_READ | PERMS_SHOW)); } /** - * Returns the entries of $sourceroots that the current user has access to. + * Returns the entries of $sourceroots that the current user has access + * to. * * @return array The sourceroots that the current user has access to. */ static public function sourceroots() { - global $perms, $sourceroot, $sourceroots; - $arr = array(); - foreach ($sourceroots as $key => $val) { - if (!$perms->exists('chora:sourceroots:' . $key) || - $perms->hasPermission('chora:sourceroots:' . $key, - Auth::getAuth(), - PERMS_READ | PERMS_SHOW)) { + + foreach ($GLOBALS['sourceroots'] as $key => $val) { + if (self::checkPerms($key)) { $arr[$key] = $val; } } @@ -377,15 +320,16 @@ class Chora } /** - * Generate a list of repositories available from this - * installation of Chora. + * Generate a list of repositories available from this installation of + * Chora. * * @return string XHTML code representing links to the repositories. */ static public function repositories() { - $sourceroots = Chora::sourceroots(); + $sourceroots = self::sourceroots(); $num_repositories = count($sourceroots); + if ($num_repositories == 1) { return ''; } @@ -393,17 +337,14 @@ class Chora $arr = array(); foreach ($sourceroots as $key => $val) { if ($GLOBALS['sourceroot'] != $key) { - $arr[] = ''; + $arr[] = ''; } } - return - '
' - . '
'; + return '
' . + '
'; } /** @@ -432,40 +373,41 @@ class Chora /** * Check if the given item is restricted from being shown. - * @return boolean whether or not the item is allowed to be displayed - **/ - static public function isRestricted($item) + * + * @param string $where The current file path. + * + * @return boolean Is item allowed to be displayed? + */ + static public function isRestricted($where) { - global $conf, $perms, $sourceroots, $sourceroot; - static $restricted; - // First check if the current user has access to this repository. - if ($perms->exists('chora:sourceroots:' . $sourceroot) && - !$perms->hasPermission('chora:sourceroots:' . $sourceroot, - Auth::getAuth(), - PERMS_READ | PERMS_SHOW)) { + if (!self::checkPerms($GLOBALS['sourceroot'])) { return true; } - if (!isset($restricted)) { + if (!isset(self::$restricted)) { $restricted = array(); - if (isset($conf['restrictions']) && is_array($conf['restrictions'])) { - $restricted = $conf['restrictions']; + + if (isset($GLOBALS['conf']['restrictions']) && + is_array($GLOBALS['conf']['restrictions'])) { + $restricted = $GLOBALS['conf']['restrictions']; } - foreach ($sourceroots as $key => $val) { - if ($sourceroot == $key) { - if (isset($val['restrictions']) && is_array($val['restrictions'])) { - $restricted = array_merge($restricted, $val['restrictions']); - break; - } + foreach ($GLOBALS['sourceroots'] as $key => $val) { + if (($GLOBALS['sourceroot'] == $key) && + isset($val['restrictions']) && + is_array($val['restrictions'])) { + $restricted = array_merge($restricted, $val['restrictions']); + break; } } + + self::$restricted = $restricted; } - if (!empty($restricted) && is_array($restricted) && count($restricted)) { - for ($i = 0; $i < count($restricted); $i++) { - if (preg_match('|' . str_replace('|', '\|', $restricted[$i]) . '|', $item)) { + if (!empty($restricted)) { + for ($i = 0; $i < count($restricted); ++$i) { + if (preg_match('|' . str_replace('|', '\|', $restricted[$i]) . '|', $where)) { return true; } } @@ -476,89 +418,62 @@ class Chora /** * Build Chora's list of menu items. + * + * @return string The menu HTML code. */ - static public function getMenu($returnType = 'object') + static public function getMenu() { require_once 'Horde/Menu.php'; - $menu = new Menu(); - $menu->add(Chora::url(), _("_Browse"), 'chora.png'); - - if ($returnType == 'object') { - return $menu; - } else { - return $menu->render(); - } + $menu->add(self::url('browse'), _("_Browse"), 'chora.png'); + return $menu->render(); } /** + * Generate the link used for various file-based views. + * + * @param string $where The current file path. + * @param string $current The current view ('browse', 'patchsets', + * 'history', 'cvsgraph', or 'stats'). + * + * @return array An array of file view links. */ - static public function getFileViews() + static public function getFileViews($where, $current) { - global $where; - - $views = array(); - $current = str_replace('.php', '', basename($_SERVER['PHP_SELF'])); + $views = ($current == 'browse') + ? array('' . _("Logs") . '') + : array(Horde::widget(self::url('browse', $where), _("Logs"), 'widget', '', '', _("_Logs"))); - $views[] = $current == 'browse' - ? '' . _("Logs") . '' - : Horde::widget(Chora::url('', $where), _("Logs"), 'widget', '', - '', _("_Logs")); - - if (!empty($GLOBALS['conf']['paths']['cvsps']) || - $GLOBALS['VC']->hasFeature('patchsets')) { - $views[] = $current == 'patchsets' + if ($GLOBALS['VC']->hasFeature('patchsets')) { + $views[] = ($current == 'patchsets') ? '' . _("Patchsets") . '' - : Horde::widget(Chora::url('patchsets', $where), _("Patchsets"), - 'widget', '', '', _("_Patchsets")); + : Horde::widget(self::url('patchsets', $where), _("Patchsets"), 'widget', '', '', _("_Patchsets")); } if ($GLOBALS['VC']->hasFeature('branches')) { if (empty($GLOBALS['conf']['paths']['cvsgraph'])) { - $views[] = $current == 'history' + $views[] = ($current == 'history') ? '' . _("Branches") . '' - : Horde::widget(Chora::url('history', $where), _("Branches"), - 'widget', '', '', _("_Branches")); + : Horde::widget(self::url('history', $where), _("Branches"), 'widget', '', '', _("_Branches")); } else { - $views[] = $current == 'cvsgraph' + $views[] = ($current == 'cvsgraph') ? '' . _("Branches") . '' - : Horde::widget(Chora::url('cvsgraph', $where), _("Branches"), - 'widget', '', '', _("_Branches")); + : Horde::widget(self::url('cvsgraph', $where), _("Branches"), 'widget', '', '', _("_Branches")); } } - /* Can't use $current - gives us PATH_INFO information. */ - $views[] = (strpos($_SERVER['PHP_SELF'], '/stats.php') !== false) + $views[] = ($current == 'stats') ? '' . _("Statistics") . '' - : Horde::widget(Chora::url('stats', $where), _("Statistics"), - 'widget', '', '', _("_Statistics")); + : Horde::widget(self::url('stats', $where), _("Statistics"), 'widget', '', '', _("_Statistics")); return _("View:") . ' ' . implode(' | ', $views); } /** - */ - static public function formatLogMessage($log) - { - global $conf; - - require_once 'Horde/Text/Filter.php'; - - $log = Text_Filter::filter($log, 'text2html', array('parselevel' => TEXT_HTML_MICRO, 'charset' => NLS::getCharset(), 'class' => '')); - - if (!empty($conf['tickets']['regexp']) && - !empty($conf['tickets']['replacement'])) { - $log = preg_replace($conf['tickets']['regexp'], $conf['tickets']['replacement'], $log); - } - - return $log; - } - - /** * Return a list of tags for a given log entry. * * @param Horde_Vcs_Log $lg The Horde_Vcs_Log object. - * @param string $where The filename. + * @param string $where The current filepath. * * @return array An array of linked tags. */ @@ -567,7 +482,7 @@ class Chora $tags = array(); foreach ($lg->querySymbolicBranches() as $symb => $bra) { - $tags[] = ''. htmlspecialchars($symb) . ''; + $tags[] = ''. htmlspecialchars($symb) . ''; } foreach ($lg->queryTags() as $tag) { @@ -578,6 +493,83 @@ class Chora } /** + * Return a text description of how long its been since the file + * has been last modified. + * + * @param integer $date Number of seconds since epoch we wish to display. + * @param boolean $long If true, display a more verbose date. + * + * @return string The human-readable date. + */ + static public function readableTime($date, $long = false) + { + /* Initialize popular variables. */ + if (!isset(self::$rtcache)) { + $desc = array( + 1 => array(_("second"), _("seconds")), + 60 => array(_("minute"), _("minutes")), + 3600 => array(_("hour"), _("hours")), + 86400 => array(_("day"), _("days")), + 604800 => array(_("week"), _("weeks")), + 2628000 => array(_("month"), _("months")), + 31536000 => array(_("year"), _("years")) + ); + + self::$rtcache = array( + 'breaks' => array_keys($desc), + 'desc' => $desc, + 'time' => time(), + ); + } + + $cache = self::$rtcache; + $i = count($cache['breaks']); + $secs = $cache['time'] - $date; + + if ($secs < 2) { + return _("very little time"); + } + + while (--$i && $i && $cache['breaks'][$i] * 2 > $secs); + + $break = $cache['breaks'][$i]; + + $val = intval($secs / $break); + $retval = $val . ' ' . ($val > 1 ? $cache['desc'][$break][1] : $cache['desc'][$break][0]); + if ($long && $i > 0) { + $rest = $secs % $break; + $break = $cache['breaks'][--$i]; + $rest = (int)($rest / $break); + if ($rest > 0) { + $retval .= ', ' . $rest . ' ' . ($rest > 1 ? $cache['desc'][$break][1] : $cache['desc'][$break][0]); + } + } + + return $retval; + } + + /** + * Convert a commit-name into whatever the user wants. + * + * @param string $name Account name. + * + * @return string The transformed name. + */ + static public function showAuthorName($name, $fullname = false) + { + try { + $users = $GLOBALS['VC']->getUsers($GLOBALS['conf']['paths']['cvsusers']); + if (isset($users[$name])) { + return '' . + htmlspecialchars($fullname ? $users[$name]['name'] : $name) . + '' . ($fullname ? ' ' . htmlspecialchars($name) . '' : ''); + } + } catch (Horde_Vcs_Exception $e) {} + + return htmlspecialchars($name); + } + + /** * Return formatted date information. * * @param integer $date Number of seconds since epoch we wish to display. @@ -586,16 +578,32 @@ class Chora */ static public function formatDate($date) { - static $format; - - if (!isset($format)) { - $format = $GLOBALS['prefs']->getValue('date_format') . + if (!isset(self::$fdcache)) { + self::$fdcache = $GLOBALS['prefs']->getValue('date_format') . ($GLOBALS['prefs']->getValue('twenty_four') ? ' %H:%M' : ' %I:%M %p'); } - return strftime($format, $date); + return strftime(self::$fdcache, $date); + } + + /** + * Formats a log message. + * + * @param string $log The log message text. + * + * @return string The formatted message. + */ + static public function formatLogMessage($log) + { + require_once 'Horde/Text/Filter.php'; + + $log = Text_Filter::filter($log, 'text2html', array('parselevel' => TEXT_HTML_MICRO, 'charset' => NLS::getCharset(), 'class' => '')); + + return (empty($GLOBALS['conf']['tickets']['regexp']) || empty($GLOBALS['conf']['tickets']['replacement'])) + ? $log + : preg_replace($GLOBALS['conf']['tickets']['regexp'], $GLOBALS['conf']['tickets']['replacement'], $log); } } diff --git a/chora/lib/base.php b/chora/lib/base.php index 4056d6104..206cbc4e2 100644 --- a/chora/lib/base.php +++ b/chora/lib/base.php @@ -48,12 +48,7 @@ $notification->attach('status'); require_once 'Horde/Text.php'; require_once 'Horde/Help.php'; -// Chora libraries and config. -if (is_callable(array('Horde', 'loadConfiguration'))) { - $sourceroots = Horde::loadConfiguration('sourceroots.php', 'sourceroots'); -} else { - require_once CHORA_BASE . '/config/sourceroots.php'; -} +// Chora base library. require_once CHORA_BASE . '/lib/Chora.php'; // Initialize objects, path, etc. diff --git a/chora/patchsets.php b/chora/patchsets.php index caccddf90..0bc40c77d 100644 --- a/chora/patchsets.php +++ b/chora/patchsets.php @@ -17,7 +17,7 @@ require_once dirname(__FILE__) . '/lib/base.php'; // Exit if patchset feature is not available. if (!$GLOBALS['VC']->hasFeature('patchsets')) { - header('Location: ' . Chora::url('', $where)); + header('Location: ' . Chora::url('browse', $where)); exit; } @@ -33,7 +33,7 @@ try { } $title = sprintf(_("Patchsets for %s"), $where); -$extraLink = Chora::getFileViews(); +$extraLink = Chora::getFileViews($where, 'patchsets'); Horde::addScriptFile('prototype.js', 'horde', true); Horde::addScriptFile('tables.js', 'horde', true); diff --git a/chora/stats.php b/chora/stats.php index 6e32b28fd..965a738fe 100644 --- a/chora/stats.php +++ b/chora/stats.php @@ -17,7 +17,7 @@ try { Chora::fatal($e); } -$extraLink = Chora::getFileViews(); +$extraLink = Chora::getFileViews($where, 'stats'); $stats = array(); foreach ($fl->logs as $lg) { diff --git a/chora/templates/checkout/checkout.inc b/chora/templates/checkout/checkout.inc index 96091bae0..fd6765d54 100644 --- a/chora/templates/checkout/checkout.inc +++ b/chora/templates/checkout/checkout.inc @@ -5,7 +5,7 @@
  • - +
  • diff --git a/chora/templates/common-header.inc b/chora/templates/common-header.inc index 0a3ef3e98..3be56f2ff 100644 --- a/chora/templates/common-header.inc +++ b/chora/templates/common-header.inc @@ -5,7 +5,7 @@ if (isset($language)) { } echo !empty($language) ? '' : ''; -$page_title = $registry->get('name'); +$page_title = $GLOBALS['registry']->get('name'); if (!empty($title)) $page_title .= ' :: ' . $title; if (!empty($refresh_time) && ($refresh_time > 0) && !empty($refresh_url)) { echo "\n"; diff --git a/chora/templates/diff/hr/header.inc b/chora/templates/diff/hr/header.inc index 70240b70d..e3d087eb9 100644 --- a/chora/templates/diff/hr/header.inc +++ b/chora/templates/diff/hr/header.inc @@ -45,7 +45,7 @@
  • - +
  • diff --git a/chora/templates/headerbar.inc b/chora/templates/headerbar.inc index 2110d88f8..4e49ff99f 100644 --- a/chora/templates/headerbar.inc +++ b/chora/templates/headerbar.inc @@ -3,8 +3,8 @@ - [ ] - + [ ] + ( ) diff --git a/chora/templates/history/branch_cell.inc b/chora/templates/history/branch_cell.inc index 0f955f250..56c54bf21 100644 --- a/chora/templates/history/branch_cell.inc +++ b/chora/templates/history/branch_cell.inc @@ -1,6 +1,6 @@ :
    - +
    () diff --git a/chora/templates/history/rev.inc b/chora/templates/history/rev.inc index 22118d87e..6e42976b6 100644 --- a/chora/templates/history/rev.inc +++ b/chora/templates/history/rev.inc @@ -1,5 +1,5 @@ - "> + ">
    diff --git a/chora/templates/log/rev.inc b/chora/templates/log/rev.inc index 24a6efb81..d4012ba45 100644 --- a/chora/templates/log/rev.inc +++ b/chora/templates/log/rev.inc @@ -7,7 +7,7 @@ abbrev($rev)) ?> - $val))) . htmlspecialchars($val) ?> + $val))) . htmlspecialchars($val) ?> lines)): ?> (lines) ?>) diff --git a/chora/templates/menu.inc b/chora/templates/menu.inc index ebda88b49..11c17bc02 100644 --- a/chora/templates/menu.inc +++ b/chora/templates/menu.inc @@ -2,6 +2,6 @@
    - + notify(array('listeners' => 'status')) ?> diff --git a/framework/Vcs/lib/Horde/Vcs.php b/framework/Vcs/lib/Horde/Vcs.php index 2caaabe01..f8a4c228b 100644 --- a/framework/Vcs/lib/Horde/Vcs.php +++ b/framework/Vcs/lib/Horde/Vcs.php @@ -44,7 +44,7 @@ class Horde_Vcs * * @var array */ - protected $_users = null; + protected $_users = array(); /** * The current driver. @@ -409,42 +409,40 @@ class Horde_Vcs * a hash containing the requisite information, keyed on the * username, and with the 'desc', 'name', and 'mail' values inside. * - * @return boolean|array False if the file is not present, otherwise - * $this->_users populated with the data + * @return array User data. + * @throws Horde_Vcs_Exception */ public function getUsers($usersfile) { /* Check that we haven't already parsed users. */ - if (!is_null($this->_users)) { - return $this->_users; + if (isset($this->_users[$usersfile])) { + return $this->_users[$usersfile]; } if (!@is_file($usersfile) || !($fl = @fopen($usersfile, VC_WINDOWS ? 'rb' : 'r'))) { - return false; + throw new Horde_Vcs_Exception('Invalid users file: ' . $usersfile); } - $this->_users = array(); - /* Discard the first line, since it'll be the header info. */ fgets($fl, 4096); - /* Parse the rest of the lines into a hash, keyed on - * username. */ + /* Parse the rest of the lines into a hash, keyed on username. */ + $users = array(); while ($line = fgets($fl, 4096)) { - if (preg_match('/^\s*$/', $line) || - !preg_match('/^(\w+)\s+(.+)\s+([\w\.\-\_]+@[\w\.\-\_]+)\s+(.*)$/', $line, $regs)) { - continue; + if (!preg_match('/^\s*$/', $line) && + preg_match('/^(\w+)\s+(.+)\s+([\w\.\-\_]+@[\w\.\-\_]+)\s+(.*)$/', $line, $regs)) { + $users[$regs[1]] = array( + 'name' => trim($regs[2]), + 'mail' => trim($regs[3]), + 'desc' => trim($regs[4]) + ); } - - $this->_users[$regs[1]] = array( - 'name' => trim($regs[2]), - 'mail' => trim($regs[3]), - 'desc' => trim($regs[4]) - ); } - return $this->_users; + $this->_users[$usersfile] = $users; + + return $users; } /**