Issues (80)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

inc/extras.php (17 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Custom functions that act independently of the theme templates.
4
 *
5
 * Eventually, some of the functionality here could be replaced by core features.
6
 *
7
 * @package spurs
8
 */
9
10
// Exit if accessed directly.
11
defined( 'ABSPATH' ) || exit;
12
13
add_filter( 'body_class', 'spurs_body_classes' );
14
15
if ( ! function_exists( 'spurs_body_classes' ) ) {
16
	/**
17
	 * Adds custom classes to the array of body classes.
18
	 *
19
	 * @param array $classes Classes for the body element.
20
	 *
21
	 * @return array
22
	 */
23
	function spurs_body_classes( $classes ) {
24
		// Adds a class of group-blog to blogs with more than 1 published author.
25
		if ( is_multi_author() ) {
26
			$classes[] = 'group-blog';
27
		}
28
		// Adds a class of hfeed to non-singular pages.
29
		if ( ! is_singular() ) {
30
			$classes[] = 'hfeed';
31
		}
32
33
		return $classes;
34
	}
35
}
36
37
// Removes tag class from the body_class array to avoid Bootstrap markup styling issues.
38
add_filter( 'body_class', 'spurs_adjust_body_class' );
39
40
if ( ! function_exists( 'spurs_adjust_body_class' ) ) {
41
	/**
42
	 * Setup body classes.
43
	 *
44
	 * @param string $classes CSS classes.
45
	 *
46
	 * @return mixed
0 ignored issues
show
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
47
	 */
48
	function spurs_adjust_body_class( $classes ) {
49
50
		foreach ( $classes as $key => $value ) {
0 ignored issues
show
The expression $classes of type string is not traversable.
Loading history...
51
			if ( 'tag' == $value ) {
52
				unset( $classes[ $key ] );
53
			}
54
		}
55
56
		return $classes;
57
	}
58
}
59
60
// Filter custom logo with correct classes.
61
add_filter( 'get_custom_logo', 'spurs_change_logo_class' );
62
63
if ( ! function_exists( 'spurs_change_logo_class' ) ) {
64
	/**
65
	 * Replaces logo CSS class.
66
	 *
67
	 * @param string $html Markup.
68
	 *
69
	 * @return mixed
0 ignored issues
show
Consider making the return type a bit more specific; maybe use string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
70
	 */
71
	function spurs_change_logo_class( $html ) {
72
73
		$html = str_replace( 'class="custom-logo"', 'class="img-fluid"', $html );
0 ignored issues
show
Consider using a different name than the parameter $html. This often makes code more readable.
Loading history...
74
		$html = str_replace( 'class="custom-logo-link"', 'class="navbar-brand custom-logo-link"', $html );
0 ignored issues
show
Consider using a different name than the parameter $html. This often makes code more readable.
Loading history...
75
		$html = str_replace( 'alt=""', 'title="Home" alt="logo"', $html );
0 ignored issues
show
Consider using a different name than the parameter $html. This often makes code more readable.
Loading history...
76
77
		return $html;
78
	}
79
}
80
81
if ( ! function_exists( 'spurs_post_nav' ) ) {
82
	/**
83
	 * Display navigation to next/previous post when applicable.
84
	 *
85
	 * @return void
86
	 * @since 1.0.0
87
	 *
88
	 */
89
	function spurs_post_nav() {
90
		// Don't print empty markup if there's nowhere to navigate.
91
		$previous = ( is_attachment() ) ? get_post( get_post()->post_parent ) : get_adjacent_post( false, '', true );
92
		$next     = get_adjacent_post( false, '', false );
93
94
		if ( ! $next && ! $previous ) {
95
			return;
96
		}
97
		?>
98
		<nav class="container navigation post-navigation">
99
			<h2 class="sr-only"><?php _e( 'Post navigation', 'spurs' ); ?></h2>
100
			<div class="row nav-links justify-content-between">
101
				<?php
102
103
				if ( get_previous_post_link() ) {
104
					previous_post_link( '<span class="nav-previous">%link</span>', _x( '<i class="fa fa-angle-left"></i>&nbsp;%title', 'Previous post link', 'spurs' ) );
105
				}
106
				if ( get_next_post_link() ) {
107
					next_post_link( '<span class="nav-next">%link</span>', _x( '%title&nbsp;<i class="fa fa-angle-right"></i>', 'Next post link', 'spurs' ) );
108
				}
109
				?>
110
			</div><!-- .nav-links -->
111
		</nav><!-- .navigation -->
112
113
		<?php
114
	}
115
}
116
if ( ! function_exists( 'spurs_pingback' ) ) {
117
	/**
118
	 * Add a pingback url auto-discovery header for single posts of any post type.
119
	 */
120
	function spurs_pingback() {
121
		if ( is_singular() && pings_open() ) {
122
			echo '<link rel="pingback" href="' . esc_url( get_bloginfo( 'pingback_url' ) ) . '">' . "\n";
123
		}
124
	}
125
}
126
add_action( 'wp_head', 'spurs_pingback' );
127
128
if ( ! function_exists( 'spurs_mobile_web_app_meta' ) ) {
129
	/**
130
	 * Add mobile-web-app meta.
131
	 */
132
	function spurs_mobile_web_app_meta() {
133
		echo '<meta name="mobile-web-app-capable" content="yes">' . "\n";
134
		echo '<meta name="apple-mobile-web-app-capable" content="yes">' . "\n";
135
		echo '<meta name="apple-mobile-web-app-title" content="' . esc_attr( get_bloginfo( 'name' ) ) . ' - ' . esc_attr( get_bloginfo( 'description' ) ) . '">' . "\n";
136
	}
137
}
138
add_action( 'wp_head', 'spurs_mobile_web_app_meta' );
139
140
141
/**
142
 * Search/replace string to make everything lower case and convert spaces and underscores to dashes.
143
 *
144
 * @param $string
145
 *
146
 * @return null|string|string[]
147
 */
148
function spurs_tidy_url( $string ) {
149
	// Convert everything to lower case
150
	$string = strtolower( $string );
0 ignored issues
show
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
151
152
	// Make everything alphanumeric (removes all other characters)
153
	$string = preg_replace( "/[^a-z0-9_\s-]/", "", $string );
0 ignored issues
show
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
154
155
	// Clean up multiple dashes or whitespace
156
	$string = preg_replace( "/[\s-]+/", " ", $string );
0 ignored issues
show
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
157
158
	// Convert whitespace and underscore to dash
159
	$string = preg_replace( "/[\s_]/", "-", $string );
0 ignored issues
show
Consider using a different name than the parameter $string. This often makes code more readable.
Loading history...
160
161
	return $string;
162
}
163
164
/**
165
 * Set Google Maps API Key for Advanced Custom Fields
166
 */
167
add_action( 'acf/init', 'rcn_acf_init' );
168
function rcn_acf_init() {
169
	acf_update_setting( 'google_api_key', '' );
170
}
171
172
/**
173
 * Output background image style
174
 *
175
 * @param array|string $img Image array or url
176
 * @param string $size Image size to retrieve
177
 * @param bool $echo Whether to output the the style tag or return it.
178
 *
179
 * @return string|void String when retrieving.
180
 */
181
if ( ! function_exists( 'bg' ) ) {
182
183
	function bg($img, $size = '', $echo = true, $additional_style = '') {
184
		if ( ! $img ) {
185
		    $uploads = wp_get_upload_dir();
186
		    $url = $uploads['baseurl'] . '/path_to_fallback_image.png'; // default placeholder image
187
		} else {
188
            if ( is_array( $img ) ) {
189
                $url = $size ? $img['sizes'][ $size ] : $img['url'];
190
            } else {
191
                $url = $img;
192
            }
193
        }
194
195
		/*if (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) {
196
197
			$webp_suffix_url = $url . '.webp';
198
			$headers = @get_headers($webp_suffix_url);
199
200
			if (strpos($headers[0], '200') > -1) {
201
				$url = $webp_suffix_url;
202
			} else {
203
				$webp_url = preg_replace('/(?:jpg|png|gif)$/i', 'webp', $url);
204
				$headers = @get_headers($webp_url);
205
206
				if (strpos($headers[0], '200') > -1) {
207
					$url = $webp_url;
208
				}
209
			}
210
		}*/
211
212
		$string = 'style="background-image: url(' . $url . '); ' . $additional_style . '"';
213
214
		if ( $echo ) {
215
			echo $string;
216
		} else {
217
			return $string;
218
		}
219
	}
220
}
221
222
/**
223
 * Output HTML markup of template with passed args
224
 *
225
 * @param string $file File name without extension (.php)
226
 * @param array $args Array with args ($key=>$value)
227
 * @param string $default_folder Requested file folder
228
 *
229
 * */
230
if ( ! function_exists( 'show_template' ) ) {
231
	function show_template( $file, $args = null, $default_folder = 'parts' ) {
232
		echo return_template( $file, $args, $default_folder );
233
	}
234
}
235
236
/**
237
 * Return HTML markup of template with passed args
238
 *
239
 * @param string $file File name without extension (.php)
240
 * @param array $args Array with args ($key=>$value)
241
 * @param string $default_folder Requested file folder
242
 *
243
 * @return string template HTML
244
 * */
245
if ( ! function_exists( 'return_template' ) ) {
246
	function return_template( $file, $args = null, $default_folder = 'parts' ) {
247
		$file = $default_folder . '/' . $file . '.php';
0 ignored issues
show
Consider using a different name than the parameter $file. This often makes code more readable.
Loading history...
248
		if ( $args ) {
249
			extract( $args );
250
		}
251
		if ( locate_template( $file ) ) {
252
			ob_start();
253
			include( locate_template( $file ) ); //Theme Check free. Child themes support.
254
			$template_content = ob_get_clean();
255
256
			return $template_content;
257
		}
258
259
		return '';
260
	}
261
}
262
263
/**
264
 * Get the primary term of a post, by taxonomy.
265
 * If Yoast Primary Term is used, return it,
266
 * otherwise fallback to the first term.
267
 *
268
 * @param string $taxonomy The taxonomy to get the primary term from.
269
 * @param int $post_id The post ID to check.
0 ignored issues
show
Should the type for parameter $post_id not be false|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
270
 *
271
 * @return   WP_Term|bool  The term object or false if no terms.
272
 * @author   Mike Hemberger @JiveDig.
273
 *
274
 * @version  1.1.0
275
 *
276
 * @link     https://gist.github.com/JiveDig/5d1518f370b1605ae9c753f564b20b7f
277
 * @link     https://gist.github.com/jawinn/1b44bf4e62e114dc341cd7d7cd8dce4c
278
 */
279
function spurs_get_primary_term( $taxonomy = 'category', $post_id = false ) {
280
281
	// Bail if no taxonomy.
282
	if ( ! $taxonomy ) {
283
		return false;
284
	}
285
286
	// If no post ID, set it.
287
	if ( ! $post_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $post_id of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
288
		$post_id = get_the_ID();
0 ignored issues
show
Consider using a different name than the parameter $post_id. This often makes code more readable.
Loading history...
289
	}
290
291
	// If checking for WPSEO.
292
	if ( class_exists( 'WPSEO_Primary_Term' ) ) {
293
294
		// Get the primary term.
295
		$wpseo_primary_term = new WPSEO_Primary_Term( $taxonomy, $post_id );
296
		$wpseo_primary_term = $wpseo_primary_term->get_primary_term();
297
298
		// If we have one, return it.
299
		if ( $wpseo_primary_term ) {
300
			return get_term( $wpseo_primary_term );
301
		}
302
	}
303
304
	// We don't have a primary, so let's get all the terms.
305
	$terms = get_the_terms( $post_id, $taxonomy );
306
307
	// Bail if no terms.
308
	if ( ! $terms || is_wp_error( $terms ) ) {
309
		return false;
310
	}
311
312
	// Return the first term.
313
	return $terms[0];
314
}
315
316
function spurs_get_excerpt_by_post($id, $length = 70) {
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
317
318
	$content = get_the_content($id);
319
320
	if (null !== get_the_excerpt($id) && '' !== get_the_excerpt($id)) {
321
		$content = get_the_excerpt($id);
322
	}
323
324
	$content = strip_tags($content, '<ul><li>');
325
	$content = strip_shortcodes($content);
326
	if ( strlen($content) > $length ) {
327
		return substr($content, 0, $length) . '[..]';
328
	} else {
329
		return $content;
330
	}
331
}
332
333
// Enables the confirmation anchor on all Gravity Forms.
334
add_filter( 'gform_confirmation_anchor', '__return_true' );
335
336
/**
337
 * Remove comment below in order to create CPTs and Taxonomies dynamically.
338
 */
339
340
//add_action( 'init', 'spurs_register_cpt_taxonomies');
341
function spurs_register_cpt_taxonomies()
342
{
343
	spurs_register_cpts();
344
	spurs_register_taxonomies();
345
}
346
347 View Code Duplication
function spurs_register_cpts(){
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
348
349
    $cpts[] = array(
350
		'name'  => 'report',
351
		'names' => array(
352
			'singular'      => 'report',
353
			'plural'        => 'reports',
354
			'uc_singular'   => 'Report',
355
			'uc_plural'     => 'Reports',
356
		),
357
		'icon'  => 'analytics'
358
	);
359
360
	if ( count( $cpts ) > 0 ) {
361
		foreach ( $cpts as $cpt ) {
362
			$cpt_obj = new Spurs_CPT_Creator();
363
			$cpt_obj->register_cpt( $cpt['name'], $cpt['names'], $cpt['icon'] );
364
		}
365
	}
366
}
367
368 View Code Duplication
function spurs_register_taxonomies() {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
369
370
	$taxonomies[] = array(
371
		'name'      => 'report-type',
372
		'post_type' => 'report',
373
		'names'     => array(
374
			'singular'      => 'report-type',
375
			'plural'        => 'report-types',
376
			'uc_singular'   => 'Report Type',
377
			'uc_plural'     => 'Report Types',
378
		),
379
		'hierarchical'  => true
380
	);
381
382
	if ( count( $taxonomies ) > 0 ) {
383
		foreach ( $taxonomies as $tax ) {
384
			$tax_obj = new Spurs_CPT_Creator();
385
			$tax_obj->register_taxonomy( $tax['name'], $tax['post_type'], $tax['names'], $tax['hierarchical'] );
386
		}
387
	}
388
}