diff --git a/SourceWebSVN/SourceWebSVN.php b/SourceWebSVN/SourceWebSVN.php index a2dabec..2d9e668 100644 --- a/SourceWebSVN/SourceWebSVN.php +++ b/SourceWebSVN/SourceWebSVN.php @@ -30,49 +30,142 @@ return lang_get( 'plugin_SourceWebSVN_svn' ); } - protected function websvn_url($p_repo) { - $t_path = ''; - if ( !is_blank( $p_repo->info['websvn_path'] ) ) { - $t_path = '/' . urlencode( $p_repo->info['websvn_path'] ); + /** + * Retrieves the repository's multiviews setting (set to true if WebSVN is + * configured to use Apache Multiviews link format) + * @param object $p_repo repository + * @return bool + */ + public function is_multiviews( $p_repo ) { + return isset( $p_repo->info['websvn_multiviews'] ) + ? $p_repo->info['websvn_multiviews'] + : false; + } + + public function get_websvn_url( $p_repo ) { + return isset( $p_repo->info['websvn_url'] ) + ? $p_repo->info['websvn_url'] + : ''; + } + + public function get_websvn_name( $p_repo ) { + return isset( $p_repo->info['websvn_name'] ) + ? $p_repo->info['websvn_name'] + : ''; + } + + public function get_websvn_path( $p_repo ) { + return isset( $p_repo->info['websvn_path'] ) + ? $p_repo->info['websvn_path'] + : ''; + } + + /** + * Builds the WebSVN URL base string + * @param object $p_repo repository + * @param string $p_op optional WebSVN operation + * @param string $p_file optional filename (as absolute path from root) + * @param array $p_opts optional additional WebSVN URL parameters + * @return string WebSVN URL + */ + protected function url_base( $p_repo, $p_op = '', $p_file = '', $p_opts=array() ) { + $t_name = urlencode( $this->get_websvn_name( $p_repo ) ); + + # The 'sc' (show change) option is obsolete since WebSVN 2.1.0 (r621) + # we keep it for Compatibility with oder releases + if( !isset( $p_opts['sc'] ) ) { + $p_opts['sc'] = 1; } - return $p_repo->info['websvn_url'] . $p_repo->info['websvn_name'] . $t_path; + + if( $this->is_multiviews( $p_repo ) ) { + $t_url = $this->get_websvn_url( $p_repo ) . $t_name; + + if( is_blank( $p_file ) ) { + $t_url .= $this->get_websvn_path( $p_repo ); + } else { + $t_url .= $p_file; + } + + $t_url = rtrim( $t_url, '/' ); + + if( !is_blank( $p_op ) ) { + $p_opts['op'] = $p_op; + } + } else { + $t_url = $this->get_websvn_url( $p_repo ); + + if( !is_blank( $p_op ) ) { + $t_url .= '$p_op.php'; + } + + if( is_blank( $p_file ) ) { + $t_path = $this->get_websvn_path( $p_repo ); + } else { + $t_path = $p_file; + } + if( !is_blank( $t_path ) ) { + $p_opts['path'] = $t_path; + } + + $p_opts['repname'] = $t_name; + } + + return $t_url . '?' . http_build_query( $p_opts ); } public function url_repo( $p_repo, $p_changeset=null ) { - $t_rev = ''; + $t_opts = array(); if ( !is_null( $p_changeset ) ) { - $t_rev = '?rev=' . urlencode( $p_changeset->revision ); + $t_opts['rev'] = $p_changeset->revision; } - return $this->websvn_url($p_repo) . $t_rev; + + $t_op = $this->is_multiviews( $p_repo ) ? '' : 'listing'; + + return $this->url_base( $p_repo, $t_op, '', $t_opts); } public function url_changeset( $p_repo, $p_changeset ) { - return $this->websvn_url($p_repo) . '?op=comp' . - '&compare[]=/@' . urlencode( $p_changeset->revision-1 ) . - '&compare[]=/@' . urlencode( $p_changeset->revision); + $t_rev = $p_changeset->revision; + $t_path = $this->get_websvn_path( $p_repo ); + $t_opts = array(); + $t_opts['compare[0]'] = $t_path . '@' . ($t_rev - 1); + $t_opts['compare[1]'] = $t_path . '@' . $t_rev; + + return $this->url_base( $p_repo, 'comp', '', $t_opts ); } public function url_file( $p_repo, $p_changeset, $p_file ) { - if ( $p_file->action == 'D' ) { - return ''; - } - return $this->websvn_url($p_repo) . $p_file->filename . '?op=filedetails' . - '&rev=' . urlencode( $p_changeset->revision ) . '&peg=' . urlencode( $p_changeset->revision ) ; + + # if the file has been removed, it doesn't exist in current revision + # so we generate a link to (current revision - 1) + $t_revision = ($p_file->action == 'rm') + ? $p_changeset->revision - 1 + : $p_changeset->revision; + + $t_opts = array(); + $t_opts['rev'] = $t_revision; + $t_opts['peg'] = $t_revision; + + return $this->url_base( $p_repo, 'filedetails', $p_file->filename, $t_opts ); } public function url_diff( $p_repo, $p_changeset, $p_file ) { - if ( $p_file->action == 'D' || $p_file->action == 'A' ) { + if ( $p_file->action == 'rm' || $p_file->action == 'add' ) { return ''; } - return $this->websvn_url( $p_repo ) . $p_file->filename . '?op=diff' . - '&rev=' . urlencode( $p_changeset->revision ) . '&peg=' . urlencode( $p_changeset->revision ) ; + + $t_opts = array(); + $t_opts['rev'] = $p_changeset->revision; + $t_opts['peg'] = $p_changeset->revision; + + return $this->url_base( $p_repo, 'diff', $p_file->filename, $t_opts ); } public function update_repo_form( $p_repo ) { - $t_url = isset( $p_repo->info['websvn_url'] ) ? $p_repo->info['websvn_url'] : ''; - $t_name = isset( $p_repo->info['websvn_name'] ) ? $p_repo->info['websvn_name'] : ''; - $t_path = isset( $p_repo->info['websvn_path'] ) ? $p_repo->info['websvn_path'] : ''; + $t_url = $this->get_websvn_url( $p_repo ); + $t_name = $this->get_websvn_name( $p_repo ); + $t_path = $this->get_websvn_path( $p_repo ); ?>