From f4c308509eccafff991b0093d793a02dc0502c14 Mon Sep 17 00:00:00 2001 From: Chuck Hagenbuch Date: Sat, 11 Sep 2010 23:37:28 -0400 Subject: [PATCH] Bug #7990: Show README files in directory listings --- chora/app/views/file/pretty.html.php | 19 ++++++++++++ chora/browsedir.php | 13 +++++++- chora/lib/Readme/Collection.php | 59 ++++++++++++++++++++++++++++++++++++ chora/lib/Renderer/File.php | 34 +++++++++++++++++++++ chora/lib/Renderer/File/Plain.php | 16 ++++++++++ chora/lib/Renderer/File/Pretty.php | 33 ++++++++++++++++++++ chora/patchsets.php | 10 ++---- chora/themes/screen.css | 9 ++++-- 8 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 chora/app/views/file/pretty.html.php create mode 100644 chora/lib/Readme/Collection.php create mode 100644 chora/lib/Renderer/File.php create mode 100644 chora/lib/Renderer/File/Plain.php create mode 100644 chora/lib/Renderer/File/Pretty.php diff --git a/chora/app/views/file/pretty.html.php b/chora/app/views/file/pretty.html.php new file mode 100644 index 000000000..cedb2eef4 --- /dev/null +++ b/chora/app/views/file/pretty.html.php @@ -0,0 +1,19 @@ +
+

h($this->title) ?>

+
+mimeType, 'text/plain') !== false) { + $data = $this->pretty->render('inline'); + $data = reset($data); + echo '
' . $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($data['data'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)) . '
'; +} elseif (strpos($this->mimeType, 'image/') !== false) { + echo Horde::img(Horde_Util::addParameter(Horde::selfUrl(true), 'p', 1), '', '', ''); +} elseif ($this->pretty->canRender('inline')) { + $data = $this->pretty->render('inline'); + echo $data['data']; +} else { + echo Horde::link(Horde_Util::addParameter(Horde::selfUrl(true), 'p', 1)) . Horde::img('download.png') . ' ' . sprintf(_("Download revision %s"), $r) . ''; +} +?> +
+
diff --git a/chora/browsedir.php b/chora/browsedir.php index f6579b140..7b5843fdf 100644 --- a/chora/browsedir.php +++ b/chora/browsedir.php @@ -93,6 +93,7 @@ if ($dirList) { } /* Display all of the files in this directory */ +$readmes = array(); if ($fileList) { echo ''; foreach ($fileList as $currFile) { @@ -104,9 +105,13 @@ if ($fileList) { $lg = $currFile->queryLastLog(); $realname = $currFile->queryName(); $mimeType = Horde_Mime_Magic::filenameToMIME($realname); + $currFile->mimeType = $mimeType; - $icon = $injector->getInstance('Horde_Mime_Viewer')->getIcon($mimeType); + if (Horde_String::lower(Horde_String::substr($realname, 0, 6)) == 'readme') { + $readmes[] = $currFile; + } + $icon = $injector->getInstance('Horde_Mime_Viewer')->getIcon($mimeType); $author = Chora::showAuthorName($lg->queryAuthor()); $filerev = $lg->queryRevision(); $date = $lg->queryDate(); @@ -125,4 +130,10 @@ if ($fileList) { } echo ''; +if ($readmes) { + $readmeCollection = new Chora_Readme_Collection($readmes); + $readmeFile = $readmeCollection->chooseReadme(); + $readmeRenderer = new Chora_Renderer_File_Pretty($injector->createInstance('Horde_View_Base'), $readmeFile, $readmeFile->queryRevision()); + echo $readmeRenderer->render(); +} require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/chora/lib/Readme/Collection.php b/chora/lib/Readme/Collection.php new file mode 100644 index 000000000..df8bfcfce --- /dev/null +++ b/chora/lib/Readme/Collection.php @@ -0,0 +1,59 @@ + + * @package Chora + */ +class Chora_Readme_Collection +{ + protected $_readmes; + + const CHOOSE_A = -1; + const CHOOSE_B = 1; + const EQUAL = 0; + + public function __construct(array $readmes) + { + $this->_readmes = $readmes; + } + + public function chooseReadme() + { + $count = count($this->_readmes); + if ($count == 0) { + throw new Chora_Exception('No README files to choose from'); + } + + if ($count > 1) { + usort($this->_readmes, array($this, 'compareReadmes')); + } + + return $this->_readmes[0]; + } + + public function compareReadmes($a, $b) + { + if ($this->_isHtmlReadme($a)) { return self::CHOOSE_A; } + if ($this->_isHtmlReadme($b)) { return self::CHOOSE_B; } + + $a_len = Horde_String::length($a->queryName()); + $b_len = Horde_String::length($b->queryName()); + if ($a_len < $b_len) { + return self::CHOOSE_A; + } elseif ($b_len < $a_len) { + return self::CHOOSE_B; + } else { + return strcasecmp($a->queryName(), $b->queryName()); + } + } + + protected function _isHtmlReadme(Horde_Vcs_File $readme) + { + $file = Horde_String::lower($readme->queryName()); + return ($file == 'readme.html' || $file == 'readme.htm' || ($file == 'readme' && $readme->mimeType == 'text/html')); + } +} diff --git a/chora/lib/Renderer/File.php b/chora/lib/Renderer/File.php new file mode 100644 index 000000000..56ef71a7f --- /dev/null +++ b/chora/lib/Renderer/File.php @@ -0,0 +1,34 @@ + + * @package Chora + */ +class Chora_Renderer_File +{ + /** + * @var Horde_View + */ + protected $_view; + + /** + * @var Horde_Vcs_File + */ + protected $_file; + + /** + * @var string + */ + protected $_revision; + + public function __construct(Horde_View $view, Horde_Vcs_File $file, $revision) + { + $this->_view = $view; + $this->_file = $file; + $this->_revision = $revision; + } +} diff --git a/chora/lib/Renderer/File/Plain.php b/chora/lib/Renderer/File/Plain.php new file mode 100644 index 000000000..2cef5839a --- /dev/null +++ b/chora/lib/Renderer/File/Plain.php @@ -0,0 +1,16 @@ + + * @package Chora + */ +class Chora_Renderer_File_Plain extends Chora_Renderer_File +{ + public function render() + { + } +} diff --git a/chora/lib/Renderer/File/Pretty.php b/chora/lib/Renderer/File/Pretty.php new file mode 100644 index 000000000..226ab0483 --- /dev/null +++ b/chora/lib/Renderer/File/Pretty.php @@ -0,0 +1,33 @@ + + * @package Chora + */ +class Chora_Renderer_File_Pretty extends Chora_Renderer_File +{ + public function render() + { + // need the checkout + $checkOut = $GLOBALS['VC']->checkout($this->_file->queryPath(), $this->_revision); + + // Pretty-print the checked out copy */ + if ($this->_file->mimeType == 'application/octet-stream') { + $this->_view->mimeType = 'text/plain'; + } else { + $this->_view->mimeType = $this->_file->mimeType; + } + + $this->_view->title = $this->_file->queryName(); + $this->_view->pretty = Chora::pretty($this->_view->mimeType, $checkOut); + if ($this->_view->mimeType == 'text/html') { + $this->_view->pretty->setConfigParam('inline', true); + } + + return $this->_view->render('app/views/file/pretty.html.php'); + } +} diff --git a/chora/patchsets.php b/chora/patchsets.php index 6542b49fc..c5c403586 100644 --- a/chora/patchsets.php +++ b/chora/patchsets.php @@ -56,13 +56,9 @@ if ($ps_id) { require CHORA_TEMPLATES . '/common-header.inc'; require CHORA_TEMPLATES . '/menu.inc'; - - -if ($ps_id) { - require CHORA_TEMPLATES . '/patchsets/header.inc'; -} else { - require CHORA_TEMPLATES . '/headerbar.inc'; - require CHORA_TEMPLATES . '/patchsets/header.inc'; +require CHORA_TEMPLATES . '/headerbar.inc'; +require CHORA_TEMPLATES . '/patchsets/header.inc'; +if (!$ps_id) { require CHORA_TEMPLATES . '/patchsets/header_table.inc'; } diff --git a/chora/themes/screen.css b/chora/themes/screen.css index afa6689b5..5b287ec96 100644 --- a/chora/themes/screen.css +++ b/chora/themes/screen.css @@ -91,7 +91,7 @@ ul.revision li.tags { } /* Labels. */ -h3.revision_log, h3.checkout { +h3.revision_log, h3.checkout, h3.file-view-header { background: #e9e9e9; display: inline; font-weight: bold; @@ -182,12 +182,15 @@ ul.singlepsfiles li { color: red; } -/* Checkout. */ -div.checkout { +/* Checkout, File view */ +div.checkout, div.file-view-contents { padding: 3px; margin: 2px 5px 8px 5px; border: 1px solid #ddd; } +div.file-view { + margin-top: 2em; +} .attic { background: #edd; -- 2.11.0