Bug #7990: Show README files in directory listings
authorChuck Hagenbuch <chuck@horde.org>
Sun, 12 Sep 2010 03:37:28 +0000 (23:37 -0400)
committerChuck Hagenbuch <chuck@horde.org>
Sun, 12 Sep 2010 03:37:28 +0000 (23:37 -0400)
chora/app/views/file/pretty.html.php [new file with mode: 0644]
chora/browsedir.php
chora/lib/Readme/Collection.php [new file with mode: 0644]
chora/lib/Renderer/File.php [new file with mode: 0644]
chora/lib/Renderer/File/Plain.php [new file with mode: 0644]
chora/lib/Renderer/File/Pretty.php [new file with mode: 0644]
chora/patchsets.php
chora/themes/screen.css

diff --git a/chora/app/views/file/pretty.html.php b/chora/app/views/file/pretty.html.php
new file mode 100644 (file)
index 0000000..cedb2ee
--- /dev/null
@@ -0,0 +1,19 @@
+<div class="file-view">
+<h3 class="file-view-header"><?php echo $this->h($this->title) ?></h3>
+<div class="file-view-contents">
+<?php
+if (strpos($this->mimeType, 'text/plain') !== false) {
+    $data = $this->pretty->render('inline');
+    $data = reset($data);
+    echo '<div class="fixed">' . $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($data['data'], 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO)) . '</div>';
+} 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) . '</a>';
+}
+?>
+</div>
+</div>
index f6579b1..7b5843f 100644 (file)
@@ -93,6 +93,7 @@ if ($dirList) {
 }
 
 /* Display all of the files in this directory */
+$readmes = array();
 if ($fileList) {
     echo '<tbody>';
     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 '</table>';
+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 (file)
index 0000000..df8bfcf
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright 2000-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @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 (file)
index 0000000..56ef71a
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright 2000-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @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 (file)
index 0000000..2cef583
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Copyright 2000-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @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 (file)
index 0000000..226ab04
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright 2000-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @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');
+    }
+}
index 6542b49..c5c4035 100644 (file)
@@ -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';
 }
 
index afa6689..5b287ec 100644 (file)
@@ -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;