1<?php
2
3# Copyright (c) 2017 Damien Regad
4# Licensed under the MIT license
5
6require_once( 'MantisSourcePlugin.class.php' );
7
8/**
9 * Class MantisSourceGitBasePlugin
10 *
11 * Base class providing common methods for all git-based Source Integration
12 * Plugin classes.
13 *
14 */
15abstract class MantisSourceGitBasePlugin extends MantisSourcePlugin
16{
17	/**
18	 * Git branch name validation regex.
19	 * Based on rules defined in man page
20	 * http://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
21	 * - Must not start with '/'; cannot contain '/.', '//', '@{' or '\';
22	 *   cannot be a single '@': `^(?!/|.*([/.]\.|//|@\{|\\\\)|@$)`
23	 * - One or more chars, except the following: ASCII control, space,
24	 *   tilde, caret, colon, question mark, asterisk, open bracket:
25	 *   `[^\000-\037\177 ~^:?*[]+`
26	 * - Must not end with '.lock', '/' or '.': `(?<!\.lock|[/.])$`
27	 */
28	private $valid_branch_regex = '%^(?!/|.*([/.]\.|//|@\{|\\\\)|@$)[^\000-\037\177 ~^:?*[]+(?<!\.lock|[/.])$%';
29
30	/**
31	 * @var bool Parent class includes global configuratino
32	 */
33	public $configuration = true;
34
35	/**
36	 * @var bool Prevent more than one Git-based plugin from processing form
37	 */
38	private static $config_form_handled = false;
39
40	/**
41	 *
42	 */
43	const CFG_DEFAULT_PRIMARY_BRANCH = 'git_default_primary_branch';
44
45	/**
46	 * Error constants
47	 */
48	const ERROR_INVALID_BRANCH = 'invalid_branch';
49
50	/**
51	 * Define plugin's Error strings
52	 * @return array
53	 */
54	public function errors() {
55		$t_errors_list = array(
56			self::ERROR_INVALID_BRANCH,
57		);
58
59		foreach( $t_errors_list as $t_error ) {
60			$t_errors[$t_error] = plugin_lang_get( 'error_' . $t_error, 'Source' );
61		}
62
63		return array_merge( parent::errors(), $t_errors );
64	}
65
66	/**
67	 * Determines if given string name is a valid git branch name.
68	 * @param string $p_branch Branch name to validate
69	 * @return bool True if valid
70	 */
71	protected function is_branch_valid( $p_branch )
72	{
73		return (bool)preg_match( $this->valid_branch_regex, $p_branch );
74	}
75
76	/**
77	 * Triggers an error if the branch is invalid
78	 * @param string $p_branch Branch name to validate
79	 * @return void
80	 */
81	protected function ensure_branch_valid( $p_branch )
82	{
83		if( !$this->is_branch_valid( $p_branch ) ) {
84			error_parameters( $p_branch );
85			plugin_error( self::ERROR_INVALID_BRANCH );
86		}
87	}
88
89	/**
90	 * Validates a comma-delimited list of git branches.
91	 * Triggers an ERROR_INVALID_BRANCH if one of the branches is invalid
92	 * @param string $p_list Comma-delimited list of branch names (or '*')
93	 * @return void
94	 */
95	protected function validate_branch_list( $p_list )
96	{
97		if( $p_list == '*' ) {
98			return;
99		}
100
101		foreach( explode( ',', $p_list ) as $t_branch ) {
102			$this->ensure_branch_valid( trim( $t_branch ) );
103		}
104	}
105
106	/**
107	 * Retrieves the default primary branches from Source plugin's config
108	 * @return string
109	 */
110	protected function get_default_primary_branches() {
111		plugin_push_current( 'Source' );
112		$t_value = plugin_config_get( self::CFG_DEFAULT_PRIMARY_BRANCH, 'master' );
113		plugin_pop_current();
114		return $t_value;
115	}
116
117	/**
118	 * Output form elements for configuration options.
119	 */
120	public function update_config_form() {
121		# Prevent more than one Git-based class from outputting form elements.
122		if( !MantisSourceGitBasePlugin::$config_form_handled ) {
123			plugin_push_current( 'Source' );
124			MantisSourceGitBasePlugin::$config_form_handled = true;
125?>
126	<tr class="spacer"></tr>
127	<tr>
128		<td colspan="2"><h4><?php echo plugin_lang_get( 'git_title' ) ?></h4></td>
129	</tr>
130	<tr>
131		<td class="category"><?php echo plugin_lang_get( self::CFG_DEFAULT_PRIMARY_BRANCH ) ?></td>
132		<td>
133			<input name="<?php echo self::CFG_DEFAULT_PRIMARY_BRANCH ?>"
134				   type="text" class="input-sm" size="50"
135				   value="<?php echo string_attribute( plugin_config_get( self::CFG_DEFAULT_PRIMARY_BRANCH, 'master' ) ) ?>"
136			/>
137			<br>
138			<span class="small"><?php echo plugin_lang_get( 'git_default_primary_branch_info' ) ?></span>
139		</td>
140	</tr>
141	<tr></tr>
142<?php
143			plugin_pop_current();
144		}
145	}
146
147	/**
148	 * Process form elements for configuration options.
149	 */
150	public function update_config() {
151		# Prevent more than one SVN class from handling form elements.
152		if( !MantisSourceGitBasePlugin::$config_form_handled ) {
153			MantisSourceGitBasePlugin::$config_form_handled = true;
154
155			plugin_push_current( 'Source' );
156			$f_default_branch = trim( gpc_get_string( self::CFG_DEFAULT_PRIMARY_BRANCH ) ) ?: 'master';
157			$t_default_branch = plugin_config_get( self::CFG_DEFAULT_PRIMARY_BRANCH, 'master' );
158			if ( $f_default_branch != $t_default_branch ) {
159				plugin_config_set( self::CFG_DEFAULT_PRIMARY_BRANCH, $f_default_branch );
160			}
161			plugin_pop_current();
162		}
163	}
164}
165