- <?php
- /**
- * PHLY - PHp LibrarY
- *
- * PHLY is a library of PHP classes designed with the following intentions:
- * - Loosely coupled; dependencies should be few, and no base class should be
- * necessary.
- * - Extendible; all classes should be easily extendible. This may be via
- * observers, interfaces, adapters, etc.. The base class should solve 80% of
- * usage, and allow extensions to the class to fill in the remainder.
- * - Designed for PHP5 and up; all classes should make use of PHP5's features.
- * - Documented; all classes should minimally have excellent API-level
- * documentation, with use cases in the class docblock.
- * - Tested; all classes should have (passing) unit tests accompanying them.
- * - Open source and commercial friendly; all classes should use a
- * commercial-friendly open source license. The BSD license is one such
- * example.
- *
- * @license New BSD, http://www.opensource.org/licenses/bsd-license.php
- * @package Phly
- * @copyright 2006 - Present, Matthew Weier O'Phinney
- */
-
- /**
- * Cgiapp2 controller
- */
- require_once 'Cgiapp2.class.php';
-
- /**
- * Use XSLT for templating
- */
- require_once 'Cgiapp2/Plugin/Xslt.php';
-
- /**
- * Use darcs model
- */
- require_once 'Phly/Darcs/Model.php';
-
- /**
- * Darcs repository browsing class
- *
- * @todo Ability to PUT to repository
- * @package Phly
- * @subpackage Phly_Darcs
- * @copyright 2006 - Present, Matthew Weier O'Phinney
- * @author Matthew Weier O'Phinney <mweierophinney@gmail.com>
- * @license BSD
- * @version $Id: fsource_Phly_Phly_Darcs_Phly_DarcsPhlyDarcsController.php.html 71 2007-05-12 20:54:24Z matthew $
- */
- class Phly_Darcs_Controller extends Cgiapp2
- {
- /**
- * Phly_Config object
- * @var Phly_Config
- * @access public
- */
- public $config;
-
- /**
- * Pre-run initialization
- *
- * Loads configuration from file specified in 'darcs_config' Cgiapp param.
- *
- * @access public
- * @param Cgiapp2 $cgiapp
- * @return void
- */
- public function cgiapp_init($args, Cgiapp2 $cgiapp)
- {
- if (!$this->param('darcs_config')) {
- $cgiapp->croak('Missing darcs config file declaration');
- }
-
- // Load config
- require_once 'Phly/Config.php';
- Phly_Config::load($this->param('darcs_config'), 'darcs');
- $this->config = Phly_Config::getInstance();
- Phly_Darcs_Model::setExecutable($this->config->darcs->exe);
- Phly_Darcs_Model::setRepoPath($this->config->darcs->repoPath);
- }
-
- public function setup()
- {
- // Setup run modes
- $this->run_modes(array(
- 'repos' => 'listRepos',
- 'browse' => 'browseRepo',
- 'annotate' => 'annotate',
- 'patch' => 'showPatches',
- 'diff' => 'showDiff',
- 'rss' => 'showRss'
- ));
-
- // start mode
- $this->start_mode('repos');
-
- // error mode
- $this->error_mode('showError');
-
- // mode param...
- if (null === ($idx = $this->config->darcs->index->action)) {
- $idx = 1;
- }
- $this->mode_param(array(
- 'path_info' => $idx,
- 'param' => 'q'
- ));
- }
-
- /**
- * Handle and display errors
- *
- * @access public
- * @param mixed $e
- * @return string
- */
- public function showError($e)
- {
- $message = 'An error occurred in this application.';
- if (is_object($e) && method_exists($e, 'getMessage')) {
- $message = $e->getMessage();
- } elseif (is_string($e)) {
- $message = $e;
- }
- $output =<<<EOX
- <error type="general" title="error">
- $message
- </error>
- EOX;
- $xml = Phly_Darcs_Model::xmlWrap($output);
-
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->error));
- }
-
- /**
- * Prerun
- *
- * Check for presence of certain items, and forward as necessary on absence.
- *
- * @access public
- * @param mixed $rm
- * @param Cgiapp2 $cgiapp
- * @return void
- */
- public function cgiapp_prerun($rm, Cgiapp2 $cgiapp)
- {
- // Pass some info on to the template
- $path = strpos($_SERVER['REQUEST_URI'], $rm)
- ? substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $rm) + strlen($rm) + 1)
- : $_SERVER['REQUEST_URI'];
- if (strpos($path, '?')) {
- $path = substr($path, 0, strpos($path, '?'));
- }
-
- // Get protocol:
- $proto = 'http://';
- if (isset($_SERVER['HTTPS']) && 'on' == strtolower($_SERVER['HTTPS'])) {
- $proto = 'https://';
- }
- $uri = $proto . $_SERVER['HTTP_HOST'] . $cgiapp->config->darcs->baseUrl;
- $cgiapp->tmpl_assign(array(
- 'cgi-program' => $uri,
- 'cgi-url' => $uri . '/' . $path
- ));
-
- // Most run modes require a valid repository
- if (in_array($rm, array('browse', 'annotate', 'patch', 'diff', 'rss')))
- {
- if (!$repo = Cgiapp2::path_info($cgiapp->config->darcs->index->repo))
- {
- // repo not found in path
- $cgiapp->prerun_mode('repos');
- return;
- } else {
- // repo does not exist
- if (!in_array($repo, array_keys(Phly_Darcs_Model::getRepos())))
- {
- $cgiapp->prerun_mode('repos');
- return;
- }
- }
-
- // Capture the current repository for later...
- $cgiapp->param('cur_repo', $repo);
- $cgiapp->tmpl_assign('darcs-repo', $repo);
- }
-
- $this->tmpl_assign('repo-path', $this->_getRqPath());
-
- // Capture query string arguments for later
- $darcs_args = array();
- $q =& self::query();
- if (isset($q['p']) && preg_match('/^([\w\-.]+)$/', $q['p'])) {
- // patch provided
- $darcs_args[] = '--match \'hash ' . $q['p'] . '\'';
- }
-
- if (isset($q['t']) && preg_match('/^(.+)$/', $q['t'])) {
- // tag provided
- $darcs_args[] = '--tag ' . $q['t'];
- }
-
- if (isset($q['ch']) && preg_match('/^([\w\-.]+)$/', $q['ch'])) {
- // creator hash provided
- $darcs_args[] = '--creator-hash ' . $q['ch'];
- }
-
- if (isset($q['o']) && preg_match('@^([^\\!\$\^&*()\[\]{}<>~`|\';"?\r\n]+)$@', $q['o'])) {
- $cgiapp->param('darcs_orig_path', $q['o']);
- }
-
- if (0 < count($darcs_args)) {
- $cgiapp->param('darcs_args', $darcs_args);
- }
-
- // Capture sorting information
- $sort = '';
- if (isset($q['s']) && preg_match('/^(\w+)$/', $q['s'])) {
- $sort = $q['s'];
- }
-
- // Pass sort info on to the template
- $cgiapp->tmpl_assign('sort-by', $sort);
- }
-
- /**
- * List available repositories
- *
- * Creates an XML list of repository directories and passes it on to the
- * xslt processor to process.
- *
- * @access public
- * @return string
- */
- public function listRepos()
- {
- $xml = Phly_Darcs_Model::listRepos();
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->listRepos));
- }
-
- /**
- * Determine the request path
- *
- * @access protected
- * @return string
- */
- protected function _getRqPath()
- {
- if (!$this->param('rq_path')) {
- $repo = $this->param('cur_repo');
- $rm = $this->get_current_runmode();
- $baseDir = $this->config->darcs->repoPath;
- $rq = $_SERVER['REQUEST_URI'];
- $seed = $rm . '/' . $repo;
-
- $path = substr($rq, strpos($rq, $seed) + strlen($seed) + 1);
- if (strpos($path, '?')) {
- $path = substr($path, 0, strpos($path, '?'));
- }
-
- $this->param('rq_path', trim($path, '/'));
- }
-
- return $this->param('rq_path');
- }
-
- /**
- * Browse a repository
- *
- * @access public
- * @return string
- */
- public function browseRepo()
- {
- $repo = $this->param('cur_repo');
- $rqPath = $this->_getRqPath();
- $xml = Phly_Darcs_Model::browseRepo($repo, $rqPath);
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->browse));
- }
-
- /**
- * Show annotations for a file
- *
- * @access public
- * @return string
- */
- public function annotate()
- {
- $repo = $this->param('cur_repo');
- if (!$rqPath = $this->param('darcs_orig_path')) {
- $rqPath = $this->_getRqPath();
- }
- if (!$darcs_args = $this->param('darcs_args')) {
- $darcs_args = '--summary';
- } else {
- $darcs_args[] = '--summary';
- }
-
- $xml = Phly_Darcs_Model::execute($repo, 'annotate', $darcs_args, $rqPath);
-
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->annotate));
- }
-
- /**
- * Show patches for a file
- *
- * @access public
- * @return string
- */
- public function showPatches()
- {
- $repo = $this->param('cur_repo');
- if (!$rqPath = $this->param('darcs_orig_path')) {
- $rqPath = $this->_getRqPath();
- }
- $xml = Phly_Darcs_Model::execute($repo, 'changes', null, $rqPath);
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->patches));
- }
-
- /**
- * Show a diff for a file
- *
- * @access public
- * @return string
- */
- public function showDiff()
- {
- $repo = $this->param('cur_repo');
- if (!$rqPath = $this->param('darcs_orig_path')) {
- $rqPath = $this->_getRqPath();
- }
-
- if (!$darcs_args = $this->param('darcs_args')) {
- throw new Cgiapp2_Exception('Missing patch hash for diff');
- } else {
- $found = false;
- foreach ($darcs_args as $arg) {
- if (strstr($arg, '--match \'hash')) {
- $found = true;
- break;
- }
- }
- if (!$found) {
- throw new Cgiapp2_Exception('Missing patch hash for diff');
- }
- }
-
- $xml = Phly_Darcs_Model::execute($repo, 'diff', $darcs_args, $rqPath);
-
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->diff));
- }
-
- /**
- * Show an RSS feed of changes
- *
- * @access public
- * @return string
- */
- public function showRss()
- {
- $repo = $this->param('cur_repo');
- $rqPath = $this->_getRqPath();
- if (null === ($count = $this->config->darcs->rssCount)) {
- $count = 10;
- }
- if (!$darcs_args = $this->param('darcs_args')) {
- $darcs_args = '--last ' . $count;
- } else {
- $darcs_args[] = '--last ' . $count;
- }
-
- $xml = Phly_Darcs_Model::execute($repo, 'changes', $darcs_args, $rqPath);
- $this->header_type('header');
- $this->header_props(array('Content-type' => 'text/xml'));
- return $this->load_tmpl(array($xml, $this->config->darcs->tmpl->rss));
- }
- }