Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/hr-management/addons/Recaptcha/classes/Controllers/Credential.php
+++ b/hr-management/addons/Recaptcha/classes/Controllers/Credential.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptchaControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMAddonRecaptchaModelsGoogle;
use CrewHRMHelpersCredential as HelpersCredential;
use CrewHRMModelsUser;
--- a/hr-management/addons/Recaptcha/classes/Main.php
+++ b/hr-management/addons/Recaptcha/classes/Main.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptcha;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMAddonRecaptchaSetupDispatcher;
use CrewHRMAddonRecaptchaSetupScripts;
use CrewHRMAddonRecaptchaSetupVerify;
--- a/hr-management/addons/Recaptcha/classes/Models/Google.php
+++ b/hr-management/addons/Recaptcha/classes/Models/Google.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptchaModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpersCredential;
/**
--- a/hr-management/addons/Recaptcha/classes/Setup/Dispatcher.php
+++ b/hr-management/addons/Recaptcha/classes/Setup/Dispatcher.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptchaSetup;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMAddonRecaptchaControllersCredential;
/**
--- a/hr-management/addons/Recaptcha/classes/Setup/Scripts.php
+++ b/hr-management/addons/Recaptcha/classes/Setup/Scripts.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptchaSetup;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpersUtilities;
use CrewHRMAddonRecaptchaMain;
use CrewHRMAddonRecaptchaModelsGoogle;
--- a/hr-management/addons/Recaptcha/classes/Setup/Verify.php
+++ b/hr-management/addons/Recaptcha/classes/Setup/Verify.php
@@ -7,6 +7,11 @@
namespace CrewHRMAddonRecaptchaSetup;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMAddonRecaptchaModelsGoogle;
/**
--- a/hr-management/classes/Controllers/AddonController.php
+++ b/hr-management/classes/Controllers/AddonController.php
@@ -7,6 +7,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_String;
use CrewHRMModelsAddonManager;
--- a/hr-management/classes/Controllers/ApplicationHandler.php
+++ b/hr-management/classes/Controllers/ApplicationHandler.php
@@ -7,6 +7,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMModelsApplication;
use CrewHRMModelsField;
use CrewHRMModelsFileManager;
@@ -92,7 +97,7 @@
wp_send_json_success(
array(
'application_id' => $application_id,
- 'message' => esc_html__( 'Application has been created.' ),
+ 'message' => esc_html__( 'Application has been created.', 'hr-management' ),
)
);
}
@@ -199,7 +204,7 @@
Application::changeApplicationStage( $job_id, $application_id, $stage_id );
wp_send_json_success(
array(
- 'message' => esc_html__( 'Application stage changed successfully!' ),
+ 'message' => esc_html__( 'Application stage changed successfully!', 'hr-management' ),
)
);
}
@@ -280,6 +285,6 @@
);
}
- wp_send_json_error( array( 'message' => __( 'Invalid access', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => __( 'Invalid access', 'hr-management' ) ) );
}
}
--- a/hr-management/classes/Controllers/EmployeeController.php
+++ b/hr-management/classes/Controllers/EmployeeController.php
@@ -5,6 +5,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpersFile;
use CrewHRMModelsEmployment;
use CrewHRMModelsUser;
@@ -45,12 +50,12 @@
// If acting as admin but not admin then show error
if ( $is_admin && ! User::hasAdministrativeRole( $current_user_id ) ) {
- wp_send_json_error( array( 'message' => __( 'Access denied!', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => __( 'Access denied!', 'hr-management' ) ) );
}
// Check if required fields provided
if ( empty( $employee['first_name'] ) || empty( $employee['last_name'] ) || ( $is_admin && empty( $employee['user_email'] ) ) ) {
- wp_send_json_error( array( 'message' => esc_html__( 'Required fields missing', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'Required fields missing', 'hr-management' ) ) );
}
// If it is onboarding by end user, use current user ID as the employee
@@ -64,7 +69,7 @@
// Show warning for existing email
$mail_user_id = $is_admin ? User::getUserIdByEmail( $employee['user_email'] ) : null;
if ( ! empty( $mail_user_id ) && $mail_user_id !== ( $employee['user_id'] ?? null ) ) {
- wp_send_json_error( array( 'message' => esc_html__( 'The email is associated with another account already', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'The email is associated with another account already', 'hr-management' ) ) );
}
// Show warning for duplicate employee ID
@@ -77,7 +82,7 @@
$employee_user_id = User::getUserIdByEmployeeId( $employee['employee_id'] );
if ( ! empty( $employee_user_id ) && $employee_user_id != ( $employee['user_id'] ?? null ) ) {
- wp_send_json_error( array( 'message' => __( 'The employee ID exists', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => __( 'The employee ID exists', 'hr-management' ) ) );
}
}
@@ -88,7 +93,7 @@
// If fails
if ( empty( $user_id ) || ! is_numeric( $user_id ) ) {
- wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong!', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong!', 'hr-management' ) ) );
}
// Update completed step array
@@ -116,7 +121,7 @@
// Validate access
if ( get_current_user_id() != $user_id && ! User::hasAdministrativeRole( get_current_user_id() ) ) {
- wp_send_json_error( array( 'message' => __( 'Access denied!', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => __( 'Access denied!', 'hr-management' ) ) );
}
$employee = User::getUserInfo( $user_id );
@@ -129,7 +134,7 @@
)
);
} else {
- wp_send_json_error( array( 'message' => esc_html__( 'Employee not found', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'Employee not found', 'hr-management' ) ) );
}
}
@@ -145,7 +150,7 @@
$administrative = User::hasAdministrativeRole( $user_id );
if ( ( $is_admin && ! $administrative ) || ( ! $administrative && ! User::validateRole( $user_id, User::ROLE_EMPLOYEE ) ) ) {
- wp_send_json_error( array( 'message' => __( 'Access denied!', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => __( 'Access denied!', 'hr-management' ) ) );
}
$users = User::getEmployeeUsers( $filters );
@@ -192,11 +197,11 @@
$success = Employment::changeStatus( $user_id, $status );
if ( $success ) {
- wp_send_json_success( array( 'message' => __( 'Employment status has been changed successfully!' ) ) );
+ wp_send_json_success( array( 'message' => __( 'Employment status has been changed successfully!', 'hr-management' ) ) );
return;
}
- wp_send_json_error( array( 'message' => __( 'Employment not found to change status' ) ) );
+ wp_send_json_error( array( 'message' => __( 'Employment not found to change status', 'hr-management' ) ) );
}
/**
--- a/hr-management/classes/Controllers/JobManagement.php
+++ b/hr-management/classes/Controllers/JobManagement.php
@@ -7,6 +7,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMModelsApplication;
use CrewHRMModelsJob;
@@ -26,7 +31,9 @@
'getJobsDashboard' => array(),
'getJobsDashboardMinimal' => array(),
'getApplicationsByJob' => array(),
- 'singleJobAction' => array(),
+ 'singleJobAction' => array(
+ 'role' => array( 'administrator' ),
+ ),
'getSingleJobView' => array(
'nopriv' => true,
),
@@ -157,7 +164,7 @@
Job::toggleArchiveState( $job_id, $do_archive );
wp_send_json_success(
array(
- 'message' => $do_archive ? esc_html__( 'Job archived', 'hr-management' ) : esc_html__( 'Job removed from archived' ),
+ 'message' => $do_archive ? esc_html__( 'Job archived', 'hr-management' ) : esc_html__( 'Job removed from archived', 'hr-management' ),
)
);
break;
@@ -194,7 +201,7 @@
// If job not found, show error message.
if ( empty( $job ) ) {
- wp_send_json_error( array( 'message' => esc_html__( 'Job Not Found', 'crewhrm' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'Job Not Found', 'hr-management' ) ) );
}
// Determine if the current user can visit the job
@@ -227,7 +234,7 @@
$job = apply_filters( 'crewhrm_single_job_view', $job );
if ( ! $can_visit ) {
- wp_send_json_error( array( 'message' => esc_html__( 'Job not found' ) ) );
+ wp_send_json_error( array( 'message' => esc_html__( 'Job not found', 'hr-management' ) ) );
} else {
wp_send_json_success(
array(
--- a/hr-management/classes/Controllers/MailPreview.php
+++ b/hr-management/classes/Controllers/MailPreview.php
@@ -7,6 +7,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMMain;
use CrewHRMModelsMailer;
@@ -53,14 +58,14 @@
}
if ( empty( $templates[ $template ] ) ) {
- exit( esc_html__( 'The email template was not found to preview', 'crewhrm' ) );
+ exit( esc_html__( 'The email template was not found to preview', 'hr-management' ) );
}
$path = $templates[ $template ]['path'];
if ( ! file_exists( $path ) ) {
http_response_code( 404 );
- exit( esc_html__( 'Template file not found', 'crewhrm' ) );
+ exit( esc_html__( 'Template file not found', 'hr-management' ) );
}
// Render event template
@@ -72,8 +77,32 @@
ob_start();
include Main::$configs->dir . 'templates/email/layout.php';
$final_body = str_replace( '{contents}', $contents, ob_get_clean() );
+ $allowed = wp_kses_allowed_html( 'post' );
+
+ // Keep document-level tags so email preview can render as full HTML in browser.
+ $allowed['html'] = array(
+ 'lang' => true,
+ 'dir' => true,
+ );
+ $allowed['head'] = array();
+ $allowed['body'] = array(
+ 'class' => true,
+ 'id' => true,
+ 'style' => true,
+ );
+ $allowed['meta'] = array(
+ 'charset' => true,
+ 'name' => true,
+ 'content' => true,
+ 'http-equiv' => true,
+ );
+ $allowed['title'] = array();
+ $allowed['style'] = array(
+ 'type' => true,
+ 'media' => true,
+ );
- echo $final_body;
+ echo wp_kses( $final_body, $allowed );
exit;
}
--- a/hr-management/classes/Controllers/MediaHandler.php
+++ b/hr-management/classes/Controllers/MediaHandler.php
@@ -27,13 +27,50 @@
$path = get_attached_file( $file_id );
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ global $wp_filesystem;
+ WP_Filesystem();
+
if ( empty( $path ) || ! is_readable( $path ) ) {
http_response_code( 404 );
exit;
}
+ if ( ! $wp_filesystem ) {
+ http_response_code( 500 );
+ exit;
+ }
+
+ $file_contents = $wp_filesystem->get_contents( $path );
+ if ( false === $file_contents ) {
+ http_response_code( 404 );
+ exit;
+ }
+
$mime_type = mime_content_type( $path );
- $file_size = filesize( $path );
+ $file_size = strlen( $file_contents );
+
+ $allowed_html = wp_kses_allowed_html( 'post' );
+ $allowed_html['html'] = array(
+ 'lang' => true,
+ 'dir' => true,
+ );
+ $allowed_html['head'] = array();
+ $allowed_html['meta'] = array(
+ 'charset' => true,
+ 'name' => true,
+ 'content' => true,
+ 'http-equiv' => true,
+ );
+ $allowed_html['title'] = array();
+ $allowed_html['body'] = array(
+ 'class' => true,
+ 'id' => true,
+ 'style' => true,
+ );
+ $allowed_html['style'] = array(
+ 'type' => true,
+ );
nocache_headers();
header( 'Content-Type: ' . $mime_type . '; charset=utf-8' );
@@ -41,7 +78,8 @@
header( 'Content-Length: ' . $file_size );
header( 'Pragma: no-cache' );
header( 'Expires: 0' );
- readfile( $path );
+
+ echo wp_kses( $file_contents, $allowed_html );
exit;
}
}
--- a/hr-management/classes/Controllers/PluginSettings.php
+++ b/hr-management/classes/Controllers/PluginSettings.php
@@ -7,6 +7,11 @@
namespace CrewHRMControllers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMModelsDepartment;
use CrewHRMModelsSettings;
--- a/hr-management/classes/Helpers/Colors.php
+++ b/hr-management/classes/Helpers/Colors.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
/**
* Color helper class
*/
--- a/hr-management/classes/Helpers/Credential.php
+++ b/hr-management/classes/Helpers/Credential.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
/**
* Credential manager class
*/
--- a/hr-management/classes/Helpers/File.php
+++ b/hr-management/classes/Helpers/File.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMMain;
/**
--- a/hr-management/classes/Helpers/Utilities.php
+++ b/hr-management/classes/Helpers/Utilities.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMMain;
use CrewHRMModelsSettings;
--- a/hr-management/classes/Helpers/_Array.php
+++ b/hr-management/classes/Helpers/_Array.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
/**
* The enriched array class
*/
--- a/hr-management/classes/Helpers/_Number.php
+++ b/hr-management/classes/Helpers/_Number.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
/**
* Number handler class
*/
--- a/hr-management/classes/Helpers/_String.php
+++ b/hr-management/classes/Helpers/_String.php
@@ -7,6 +7,11 @@
namespace CrewHRMHelpers;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
/**
* String handler class
*/
--- a/hr-management/classes/Main.php
+++ b/hr-management/classes/Main.php
@@ -7,6 +7,11 @@
namespace CrewHRM;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMSetupAddon;
use CrewHRMSetupAdmin;
--- a/hr-management/classes/Models/AddonManager.php
+++ b/hr-management/classes/Models/AddonManager.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMModelsSettings;
--- a/hr-management/classes/Models/Address.php
+++ b/hr-management/classes/Models/Address.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
use CrewHRMHelpersUtilities;
@@ -75,8 +80,9 @@
global $wpdb;
$wpdb->query(
- $wpdb->prepare(
- "DELETE FROM {$wpdb->crewhrm_addresses} WHERE address_id IN ({$ids_places})",
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'DELETE FROM %i WHERE address_id IN (' . $ids_places . ')', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $wpdb->crewhrm_addresses,
...$ids
)
);
@@ -93,7 +99,8 @@
global $wpdb;
$address = $wpdb->get_row(
$wpdb->prepare(
- "SELECT * FROM {$wpdb->crewhrm_addresses} WHERE address_id=%d",
+ 'SELECT * FROM %i WHERE address_id=%d',
+ $wpdb->crewhrm_addresses,
$address_id
),
ARRAY_A
--- a/hr-management/classes/Models/Application.php
+++ b/hr-management/classes/Models/Application.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
use CrewHRMHelpersFile;
@@ -167,15 +172,16 @@
global $wpdb;
$applications = $wpdb->get_results(
- $wpdb->prepare(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
application_id,
resume_file_id,
address_id
FROM
- {$wpdb->crewhrm_applications}
+ %i
WHERE
- application_id IN ({$ids_places})",
+ application_id IN ({$ids_places})", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $wpdb->crewhrm_applications,
...$ids
),
ARRAY_A
@@ -219,16 +225,18 @@
// Delete pipelines
$wpdb->query(
- $wpdb->prepare(
- "DELETE FROM {$wpdb->crewhrm_pipeline} WHERE application_id IN ({$ids_places})",
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'DELETE FROM %i WHERE application_id IN (' . $ids_places . ')', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $wpdb->crewhrm_pipeline,
...$ids
)
);
// Delete application finally
$wpdb->query(
- $wpdb->prepare(
- "DELETE FROM {$wpdb->crewhrm_applications} WHERE application_id IN ({$ids_places})",
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'DELETE FROM %i WHERE application_id IN (' . $ids_places . ')', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $wpdb->crewhrm_applications,
...$ids
)
);
@@ -246,12 +254,13 @@
public static function getApplicationsIdsByJobId( $job_id ) {
global $wpdb;
- return $wpdb->get_col(
- $wpdb->prepare(
- "SELECT application_id FROM {$wpdb->crewhrm_applications} WHERE job_id=%d",
- $job_id
- )
- );
+ return $wpdb->get_col(
+ $wpdb->prepare(
+ 'SELECT application_id FROM %i WHERE job_id=%d',
+ $wpdb->crewhrm_applications,
+ $job_id
+ )
+ );
}
/**
@@ -320,7 +329,8 @@
$get_qualified = 'disqualified' !== ( $args['qualification'] ?? 'qualified' ); // Whether to get disqualified or qualified applications
// Where conditions. Get only completed applications to show the list. Incomplete means file upload is in progress.
- $where_clause = $wpdb->prepare( 'app.job_id=%d AND app.is_complete=1', $job_id );
+ $where_clause = 'app.job_id=%d AND app.is_complete=1';
+ $where_args = array( $job_id );
// Assign applicant name search query
if ( ! empty( $args['search'] ) ) {
@@ -333,7 +343,8 @@
// Apply specific stage filter if need
if ( ! empty( $stage_id ) ) {
- $where_clause .= $wpdb->prepare( ' AND app.stage_id=%d', $stage_id );
+ $where_clause .= ' AND app.stage_id=%d';
+ $where_args[] = $stage_id;
}
// Whether to get non user only
@@ -346,22 +357,28 @@
$disq_ids = self::getDisqualifiedAppIDs( $job_id, $disq_stage_id );
$disq_ids = array_values( _Array::getArray( $disq_ids, false, 0 ) );
$disq_ids_places = _String::getPlaceHolders( $disq_ids );
+ $query_args = array_merge( $where_args, $disq_ids );
// Run query and get the application IDs
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$application_ids = $wpdb->get_col(
- $wpdb->prepare(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
app.application_id
- FROM {$wpdb->crewhrm_applications} app
- LEFT JOIN {$wpdb->crewhrm_stages} stage ON app.stage_id=stage.stage_id
- LEFT JOIN {$wpdb->users} _user ON app.email COLLATE $wp_collate=_user.user_email
+ FROM %i app
+ LEFT JOIN %i stage ON app.stage_id=stage.stage_id
+ LEFT JOIN %i _user ON app.email COLLATE $wp_collate=_user.user_email
WHERE
{$where_clause}
AND app.application_id {$negate_in} IN ({$disq_ids_places})
ORDER BY application_date DESC",
- ...$disq_ids
+ $wpdb->crewhrm_applications,
+ $wpdb->crewhrm_stages,
+ $wpdb->users,
+ ...$query_args
)
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
// If it needs only count, no need to include other data, return count onyl
if ( $count_only ) {
@@ -377,31 +394,34 @@
$ids_places = _String::getPlaceHolders( $application_ids );
// Get the resutls
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$results = $wpdb->get_results(
- $wpdb->prepare(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
- application_id,
- job_id,
- stage_id,
- address_id,
- first_name,
- last_name,
- email,
- phone,
- date_of_birth,
- gender,
- cover_letter,
- resume_file_id,
- is_complete,
- UNIX_TIMESTAMP(application_date) AS application_date
+ application_id,
+ job_id,
+ stage_id,
+ address_id,
+ first_name,
+ last_name,
+ email,
+ phone,
+ date_of_birth,
+ gender,
+ cover_letter,
+ resume_file_id,
+ is_complete,
+ UNIX_TIMESTAMP(application_date) AS application_date
FROM
- {$wpdb->crewhrm_applications}
+ %i
WHERE application_id IN ({$ids_places})
ORDER BY application_date DESC",
+ $wpdb->crewhrm_applications,
...$application_ids
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
return _Array::castRecursive( $results );
}
@@ -423,10 +443,12 @@
pipe.application_id,
pipe.stage_id
FROM
- {$wpdb->crewhrm_pipeline} pipe INNER JOIN {$wpdb->crewhrm_applications} app ON pipe.application_id=app.application_id
+ %i pipe INNER JOIN %i app ON pipe.application_id=app.application_id
WHERE
app.job_id=%d
ORDER BY action_date DESC",
+ $wpdb->crewhrm_pipeline,
+ $wpdb->crewhrm_applications,
$job_id
),
ARRAY_A
--- a/hr-management/classes/Models/DB.php
+++ b/hr-management/classes/Models/DB.php
@@ -182,11 +182,28 @@
foreach ( $query['columns'] as $column_name => $column_info ) {
// Determine if column needs to be added or modified
if ( $column_info['operation'] === 'ADD' && ! in_array( $column_name, $current_columns ) ) {
- $wpdb->query( "ALTER TABLE {$query['table']} ADD {$column_info['definition']}" );
+ $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $wpdb->prepare(
+ 'ALTER TABLE %i ADD ' . $column_info['definition'], // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $query['table']
+ )
+ );
} elseif ( $column_info['operation'] === 'MODIFY' && in_array( $column_name, $current_columns ) ) {
- $wpdb->query( "ALTER TABLE {$query['table']} MODIFY `{$column_name}` {$column_info['definition']}" );
+ $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $wpdb->prepare(
+ 'ALTER TABLE %i MODIFY %i ' . $column_info['definition'], // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $query['table'],
+ $column_name
+ )
+ );
} elseif ( $column_info['operation'] === 'DROP' && in_array( $column_name, $current_columns ) ) {
- $wpdb->query( "ALTER TABLE {$query['table']} DROP COLUMN `{$column_name}`" );
+ $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $wpdb->prepare(
+ 'ALTER TABLE %i DROP COLUMN %i', // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
+ $query['table'],
+ $column_name
+ )
+ );
}
}
}
--- a/hr-management/classes/Models/Department.php
+++ b/hr-management/classes/Models/Department.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
@@ -81,11 +86,12 @@
global $wpdb;
$wpdb->query(
- $wpdb->prepare(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"DELETE FROM
- {$wpdb->crewhrm_departments}
+ %i
WHERE
- department_id NOT IN ({$ids_places})",
+ department_id NOT IN ({$ids_places})", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $wpdb->crewhrm_departments,
...$current_ids
)
);
--- a/hr-management/classes/Models/Employment.php
+++ b/hr-management/classes/Models/Employment.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
class Employment {
@@ -88,7 +93,8 @@
global $wpdb;
- $limit = ! empty( $limit ) ? $wpdb->prepare( ' LIMIT %d', $limit ) : '';
+ $limit_clause = ! empty( $limit ) ? ' LIMIT %d' : '';
+ $query_args = ! empty( $limit ) ? array( $user_id, $limit ) : array( $user_id );
$rows = $wpdb->get_results(
$wpdb->prepare(
@@ -98,11 +104,11 @@
{$wpdb->crewhrm_employments}
WHERE
employee_user_id=%d
- ORDER BY employment_id DESC {$limit}",
- $user_id
- ),
- ARRAY_A
- );
+ ORDER BY employment_id DESC {$limit_clause}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ ...$query_args
+ ),
+ ARRAY_A
+ );
// Get employment specific related data
foreach ( $rows as $index => $row ) {
@@ -186,23 +192,25 @@
// WordPress Table Collate
$wp_collate = $wpdb->collate;
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$users = $wpdb->get_results(
- $wpdb->prepare(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT
_employee.employee_user_id,
_user.display_name
FROM
{$wpdb->crewhrm_employments} _employee
INNER JOIN {$wpdb->users} _user ON _employee.employee_user_id COLLATE $wp_collate=_user.ID
- WHERE
- _employee.reporting_person_user_id=%d
- ORDER BY
- _employee.employment_id DESC
- ",
- $user_id
+ WHERE
+ _employee.reporting_person_user_id=%d
+ ORDER BY
+ _employee.employment_id DESC
+ ",
+ $user_id
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$users = _Array::castRecursive( $users );
@@ -223,17 +231,23 @@
global $wpdb;
$where = '';
+ $args = array();
if ( ! empty( $status ) ) {
- $where .= $wpdb->prepare( ' AND employment_status=%s', $status );
+ $where .= ' AND employment_status=%s';
+ $args[] = $status;
}
if ( ! empty( $department_id ) ) {
- $where .= $wpdb->prepare( ' AND department_id=%d', $department_id );
+ $where .= ' AND department_id=%d';
+ $args[] = $department_id;
}
$count = $wpdb->get_var(
- "SELECT COUNT(DISTINCT employee_user_id) FROM {$wpdb->crewhrm_employments} WHERE 1=1 {$where}"
+ $wpdb->prepare(
+ "SELECT COUNT(DISTINCT employee_user_id) FROM {$wpdb->crewhrm_employments} WHERE 1=1 {$where}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
+ ...$args
+ )
);
return ( int ) $count;
--- a/hr-management/classes/Models/Field.php
+++ b/hr-management/classes/Models/Field.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
/**
@@ -62,16 +67,21 @@
global $wpdb;
// Prepare select columns and where clause
- $columns = is_array( $field ) ? implode( ', ', $field ) : $field;
+ $columns = is_array( $field ) ? array_values( $field ) : array( $field );
+ $column_place = implode( ', ', array_fill( 0, count( $columns ), '%i' ) );
$where_clause = '1=1';
+ $args = $columns;
+ $args[] = $this->table;
// Loop through conditions
foreach ( $where as $col => $val ) {
- $where_clause .= $wpdb->prepare( " AND {$col}=%s", $val );
+ $where_clause .= ' AND %i=%s';
+ $args[] = (string) $col;
+ $args[] = $val;
}
$row = $wpdb->get_row(
- "SELECT {$columns} FROM {$this->table} WHERE {$where_clause} LIMIT 1",
+ $wpdb->prepare( 'SELECT ' . $column_place . ' FROM %i WHERE ' . $where_clause . ' LIMIT 1', ...$args ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
ARRAY_A
);
@@ -90,15 +100,18 @@
public function getCol( array $where, string $col_name ) {
$where_clause = '1=1';
+ $args = array( $col_name, $this->table );
// Loop through conditions
foreach ( $where as $col => $val ) {
- $where_clause .= " AND {$col}='{$val}'";
+ $where_clause .= ' AND %i=%s';
+ $args[] = (string) $col;
+ $args[] = $val;
}
global $wpdb;
$col = $wpdb->get_col(
- "SELECT {$col_name} FROM {$this->table} WHERE {$where_clause}"
+ $wpdb->prepare( 'SELECT %i FROM %i WHERE ' . $where_clause, ...$args ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
);
return _Array::getArray( $col );
--- a/hr-management/classes/Models/FileManager.php
+++ b/hr-management/classes/Models/FileManager.php
@@ -7,6 +7,10 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
use CrewHRMHelpers_String;
/**
@@ -201,32 +205,42 @@
global $wpdb;
$where_clause = '';
+ $query_args = array();
// Keyword filter
- $where_clause .= $wpdb->prepare( ' AND post_title LIKE %s', "%{$wpdb->esc_like( $keyword )}%" );
+ $where_clause .= ' AND post_title LIKE %s';
+ $query_args[] = '%' . $wpdb->esc_like( $keyword ) . '%';
// Mime type filter
if ( ! empty( $mime ) ) {
- $where_clause .= $wpdb->prepare( ' AND post_mime_type=%d', $mime );
+ $where_clause .= ' AND post_mime_type=%s';
+ $query_args[] = $mime;
}
// Exclude certain IDs from result
if ( ! empty( $exclude ) ) {
$ids_places = _String::getPlaceHolders( $exclude );
$where_clause .= " AND ID NOT IN ({$ids_places})";
+ $query_args = array_merge( $query_args, $exclude );
}
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$results = $wpdb->get_results(
- "SELECT
+ $wpdb->prepare(
+ "SELECT
*
FROM
- {$wpdb->posts}
+ %i
WHERE
post_type = 'attachment'
{$where_clause}
- LIMIT 50",
+ LIMIT 50", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ $wpdb->posts,
+ ...$query_args
+ ),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$media_array = array();
--- a/hr-management/classes/Models/Job.php
+++ b/hr-management/classes/Models/Job.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
use CrewHRMHelpersUtilities;
@@ -54,7 +59,6 @@
'experience_level' => $job['experience_level'] ?? null,
'application_deadline' => $deadline,
'application_form' => maybe_serialize( $job['application_form'] ?? array() ),
- 'job_status' => $job['job_status'] ?? 'draft',
'currency' => $job['currency'] ?? null,
);
@@ -239,7 +243,9 @@
$field_value = $wpdb->get_var(
$wpdb->prepare(
- "SELECT {$field} FROM {$wpdb->crewhrm_jobs} WHERE job_id=%d",
+ 'SELECT %i FROM %i WHERE job_id=%d',
+ $field,
+ $wpdb->crewhrm_jobs,
$job_id
)
);
@@ -259,47 +265,56 @@
global $wpdb;
// Prepare limit, offset, where conditions
- $page = (int) ( $args['page'] ?? 1 );
- $limit = $args['limit'] ?? Settings::getSetting( 'job_post_per_page', 20 );
+ $page = Utilities::getInt( $args['page'] ?? 1, 1 );
+ $limit = Utilities::getInt( $args['limit'] ?? Settings::getSetting( 'job_post_per_page', 20 ), 1 );
$offset = ( $page - 1 ) * $limit;
// SQL parts
$where_clause = '';
+ $where_args = array();
$order_by = 'ORDER BY job.created_at DESC ';
$limit_clause = 'LIMIT ' . $limit . ' OFFSET ' . $offset;
// Apply query filters
if ( isset( $args['job_id'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND job.job_id=%d', $args['job_id'] );
+ $where_clause .= ' AND job.job_id=%d';
+ $where_args[] = $args['job_id'];
}
// Apply department filter
if ( ! empty( $args['department_id'] ) ) {
- $dep = esc_sql( $args['department_id'] );
- $where_clause .= $wpdb->prepare( ' AND job.department_id=%d', $dep );
+ $where_clause .= ' AND job.department_id=%d';
+ $where_args[] = $args['department_id'];
}
// Apply job status
if ( ! empty( $args['job_status'] ) ) {
- $status = esc_sql( $args['job_status'] );
- $where_clause .= $wpdb->prepare( ' AND job.job_status=%s', $status );
+ $where_clause .= ' AND job.job_status=%s';
+ $where_args[] = $args['job_status'];
}
// Apply search
if ( ! empty( $args['search'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND job.job_title LIKE %s', "%{$wpdb->esc_like( $args['search'] )}%" );
+ $where_clause .= ' AND job.job_title LIKE %s';
+ $where_args[] = '%' . $wpdb->esc_like( $args['search'] ) . '%';
}
// If it is for pagination, return only the counts
if ( $segmentation ) {
$total_count = (int) $wpdb->get_var(
- "SELECT
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ "SELECT
COUNT(job.job_id)
- FROM {$wpdb->crewhrm_jobs} job
- LEFT JOIN {$wpdb->crewhrm_departments} department ON job.department_id=department.department_id
- LEFT JOIN {$wpdb->crewhrm_addresses} address ON job.address_id=address.address_id
- WHERE 1=1 {$where_clause}"
+ FROM %i job
+ LEFT JOIN %i department ON job.department_id=department.department_id
+ LEFT JOIN %i address ON job.address_id=address.address_id
+ WHERE 1=1 {$where_clause}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $wpdb->crewhrm_jobs,
+ $wpdb->crewhrm_departments,
+ $wpdb->crewhrm_addresses,
+ ...$where_args
+ )
);
$page_count = ceil( $total_count / $limit );
@@ -314,36 +329,44 @@
}
// So it is not pagination, rather prepare whole job data
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$jobs = $wpdb->get_results(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
- job.job_id,
- job.job_code,
- job.job_title,
- job.job_description,
- job.job_status,
- job.department_id,
- job.vacancy,
- job.address_id,
- job.currency,
- job.salary_a,
- job.salary_b,
- job.salary_basis,
- job.employment_type,
- job.attendance_type,
- job.experience_level,
- job.experience_years,
- job.application_form,
- UNIX_TIMESTAMP(job.application_deadline) AS application_deadline,
- UNIX_TIMESTAMP(job.created_at) AS created_at,
- UNIX_TIMESTAMP(job.updated_at) AS updated_at,
- department.department_name,
- address.*
- FROM {$wpdb->crewhrm_jobs} job
- LEFT JOIN {$wpdb->crewhrm_departments} department ON job.department_id=department.department_id
- LEFT JOIN {$wpdb->crewhrm_addresses} address ON job.address_id=address.address_id
+ job.job_id,
+ job.job_code,
+ job.job_title,
+ job.job_description,
+ job.job_status,
+ job.department_id,
+ job.vacancy,
+ job.address_id,
+ job.currency,
+ job.salary_a,
+ job.salary_b,
+ job.salary_basis,
+ job.employment_type,
+ job.attendance_type,
+ job.experience_level,
+ job.experience_years,
+ job.application_form,
+ UNIX_TIMESTAMP(job.application_deadline) AS application_deadline,
+ UNIX_TIMESTAMP(job.created_at) AS created_at,
+ UNIX_TIMESTAMP(job.updated_at) AS updated_at,
+ department.department_name,
+ address.*
+ FROM %i job
+ LEFT JOIN %i department ON job.department_id=department.department_id
+ LEFT JOIN %i address ON job.address_id=address.address_id
WHERE 1=1 {$where_clause} {$order_by} {$limit_clause}",
+ $wpdb->crewhrm_jobs,
+ $wpdb->crewhrm_departments,
+ $wpdb->crewhrm_addresses,
+ ...$where_args
+ ),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
// No need further data if it's empty
if ( empty( $jobs ) ) {
@@ -398,8 +421,9 @@
$selects = 'job.job_id, job.job_title, job.employment_type, address.*';
$limit = Utilities::getInt( $args['limit'] ?? Settings::getSetting( 'job_post_per_page', 20 ), 1, 20 );
$offset = ( Utilities::getInt( $args['page'] ?? 1, 1 ) - 1 ) * $limit;
- $limit_clause = " LIMIT {$limit} OFFSET {$offset}";
- $where_clause = "job.job_status='publish'";
+ $limit_clause = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+ $where_clause = 'job.job_status=%s';
+ $where_args = array( 'publish' );
$department_clause = '';
global $wpdb;
@@ -407,35 +431,46 @@
// Add department filter
if ( ! empty( $args['department_id'] ) ) {
// Keep it in different clause in favour of group by query later.
- $department_clause .= $wpdb->prepare( ' AND job.department_id=%d', $args['department_id'] );
+ $department_clause .= ' AND job.department_id=%d';
+ $where_args[] = $args['department_id'];
}
// Add search filter
if ( ! empty( $args['search'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND job.job_title LIKE %s', "%{$wpdb->esc_like( $args['search'] )}%" );
+ $where_clause .= ' AND job.job_title LIKE %s';
+ $where_args[] = '%' . $wpdb->esc_like( $args['search'] ) . '%';
}
// Add country filter
if ( ! empty( $args['country_code'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND address.country_code=%s', $args['country_code'] );
+ $where_clause .= ' AND address.country_code=%s';
+ $where_args[] = $args['country_code'];
}
// Add employment_type filter
if ( ! empty( $args['employment_type'] ) ) {
// Like operator because multiple types get stored as serialized array.
- $where_clause .= $wpdb->prepare( ' AND job.employment_type LIKE %s', "%{$wpdb->esc_like( $args['employment_type'] )}%" );
+ $where_clause .= ' AND job.employment_type LIKE %s';
+ $where_args[] = '%' . $wpdb->esc_like( $args['employment_type'] ) . '%';
}
// Otherwise prepare other meta data
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$jobs = $wpdb->get_results(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
DISTINCT {$selects}
- FROM {$wpdb->crewhrm_jobs} job
- LEFT JOIN {$wpdb->crewhrm_addresses} address ON job.address_id=address.address_id
+ FROM %i job
+ LEFT JOIN %i address ON job.address_id=address.address_id
WHERE
{$where_clause} {$department_clause} {$limit_clause}",
+ $wpdb->crewhrm_jobs,
+ $wpdb->crewhrm_addresses,
+ ...$where_args
+ ),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$jobs = _Array::getArray( $jobs );
$jobs = _Array::indexify( $jobs, 'job_id' );
$jobs = Meta::job( null )->assignBulkMeta( $jobs );
@@ -446,19 +481,27 @@
}
// Get departments
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$departments = $wpdb->get_results(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
"SELECT
job.department_id,
d.department_name,
COUNT(job.job_id) AS job_count
- FROM {$wpdb->crewhrm_jobs} job
- LEFT JOIN $wpdb->crewhrm_addresses address ON job.address_id=address.address_id
- INNER JOIN {$wpdb->crewhrm_departments} d ON d.department_id=job.department_id
+ FROM %i job
+ LEFT JOIN %i address ON job.address_id=address.address_id
+ INNER JOIN %i d ON d.department_id=job.department_id
WHERE {$where_clause}
GROUP BY d.department_id
ORDER BY d.sequence",
+ $wpdb->crewhrm_jobs,
+ $wpdb->crewhrm_addresses,
+ $wpdb->crewhrm_departments,
+ ...$where_args
+ ),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$departments = _Array::getArray( $departments );
return array(
--- a/hr-management/classes/Models/Mailer.php
+++ b/hr-management/classes/Models/Mailer.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
use CrewHRMHelpersFile;
--- a/hr-management/classes/Models/Meta.php
+++ b/hr-management/classes/Models/Meta.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
@@ -90,21 +95,33 @@
* Get single meta value by object id and meta key
*
* @param string $meta_key Optional meta key to get specific. Otherwise all.
+ * @param mixed $fallback Fallback value when meta key does not exist.
* @return mixed
*/
public function getMeta( $meta_key = null, $fallback = null ) {
global $wpdb;
$is_singular = ! empty( $meta_key );
- $where_clause = $is_singular ? $wpdb->prepare( ' AND meta_key=%s', $meta_key ) : '';
-
- $results = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT meta_key, meta_value FROM {$this->table} WHERE object_id=%d {$where_clause}",
- $this->object_id
- ),
- ARRAY_A
- );
+ if ( $is_singular ) {
+ $results = $wpdb->get_results(
+ $wpdb->prepare(
+ 'SELECT meta_key, meta_value FROM %i WHERE object_id=%d AND meta_key=%s',
+ $this->table,
+ $this->object_id,
+ $meta_key
+ ),
+ ARRAY_A
+ );
+ } else {
+ $results = $wpdb->get_results(
+ $wpdb->prepare(
+ 'SELECT meta_key, meta_value FROM %i WHERE object_id=%d',
+ $this->table,
+ $this->object_id
+ ),
+ ARRAY_A
+ );
+ }
// New array
$_meta = array();
@@ -134,7 +151,8 @@
// Check if the meta exists already
$exists = $wpdb->get_var(
$wpdb->prepare(
- "SELECT meta_key FROM {$this->table} WHERE object_id=%d AND meta_key=%s LIMIT 1",
+ 'SELECT meta_key FROM %i WHERE object_id=%d AND meta_key=%s LIMIT 1',
+ $this->table,
$this->object_id,
$meta_key
)
@@ -170,7 +188,7 @@
/**
* Update bulk meta
*
- * @param array $meta_array
+ * @param array $meta_array Meta key-value pair array to update.
*
* @return void
*/
@@ -219,18 +237,22 @@
$object_ids = array_values( $object_ids );
$ids_places = _String::getPlaceHolders( $object_ids );
- $meta_key = $meta_key ? esc_sql( $meta_key ) : null;
- $key_clause = $meta_key ? $wpdb->prepare( ' AND meta_key=%s', $meta_key ) : '';
-
- $wpdb->query(
- $wpdb->prepare(
- "DELETE FROM
- {$this->table}
- WHERE
- object_id IN ({$ids_places}) {$key_clause}",
- ...$object_ids
- )
- );
+ if ( null !== $meta_key ) {
+ $wpdb->query(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'DELETE FROM %i WHERE object_id IN (' . $ids_places . ') AND meta_key=%s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ ...array_merge( array( $this->table ), $object_ids, array( $meta_key ) )
+ )
+ );
+ } else {
+ $wpdb->query(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'DELETE FROM %i WHERE object_id IN (' . $ids_places . ')', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $this->table,
+ ...$object_ids
+ )
+ );
+ }
}
/**
@@ -245,22 +267,30 @@
$objects = _Array::appendColumn( $objects, 'meta', (object) array() );
$obj_ids = array_values( _Array::getArray( array_keys( $objects ), false, 0 ) );
+ if ( empty( $obj_ids ) ) {
+ return $objects;
+ }
$ids_places = _String::getPlaceHolders( $obj_ids );
- $where_clause = '';
if ( $meta_key ) {
- $key = esc_sql( $meta_key );
- $where_clause .= $wpdb->prepare( ' AND meta_key=%s', $key );
+ $meta = $wpdb->get_results(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'SELECT * FROM %i WHERE object_id IN (' . $ids_places . ') AND meta_key=%s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ ...array_merge( array( $this->table ), $obj_ids, array( $meta_key ) )
+ ),
+ ARRAY_A
+ );
+ } else {
+ $meta = $wpdb->get_results(
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'SELECT * FROM %i WHERE object_id IN (' . $ids_places . ')', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $this->table,
+ ...$obj_ids
+ ),
+ ARRAY_A
+ );
}
- $meta = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT * FROM {$this->table} WHERE object_id IN ({$ids_places}) {$where_clause}",
- ...$obj_ids
- ),
- ARRAY_A
- );
-
foreach ( $meta as $m ) {
$_key = $m['meta_key'];
$_value = _String::maybe_unserialize( $m['meta_value'] );
@@ -283,7 +313,8 @@
$meta_data = $wpdb->get_results(
$wpdb->prepare(
- "SELECT meta_key, meta_value FROM {$this->table} WHERE object_id=%d",
+ 'SELECT meta_key, meta_value FROM %i WHERE object_id=%d',
+ $this->table,
$this->object_id
),
ARRAY_A
--- a/hr-management/classes/Models/Pipeline.php
+++ b/hr-management/classes/Models/Pipeline.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
/**
@@ -70,25 +75,27 @@
);
// --------------- Add application stage changes ---------------
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$logs = $wpdb->get_results(
- $wpdb->prepare(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT
pipe.application_id,
pipe.stage_id,
- pipe.action_taker_id,
- UNIX_TIMESTAMP(pipe.action_date) AS timestamp,
- stage.stage_name,
- _user.display_name AS action_taker_name
- FROM
- {$wpdb->crewhrm_pipeline} pipe
- LEFT JOIN {$wpdb->crewhrm_stages} stage ON pipe.stage_id=stage.stage_id
- LEFT JOIN {$wpdb->users} _user ON pipe.action_taker_id COLLATE $wp_collate=_user.ID
- WHERE
- pipe.application_id=%d",
- $application_id
+ pipe.action_taker_id,
+ UNIX_TIMESTAMP(pipe.action_date) AS timestamp,
+ stage.stage_name,
+ _user.display_name AS action_taker_name
+ FROM
+ {$wpdb->crewhrm_pipeline} pipe
+ LEFT JOIN {$wpdb->crewhrm_stages} stage ON pipe.stage_id=stage.stage_id
+ LEFT JOIN {$wpdb->users} _user ON pipe.action_taker_id COLLATE $wp_collate=_user.ID
+ WHERE
+ pipe.application_id=%d",
+ $application_id
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
// Loop through stage changes log and put to the combined pipeline array
foreach ( $logs as $log ) {
--- a/hr-management/classes/Models/Settings.php
+++ b/hr-management/classes/Models/Settings.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
use CrewHRMHelpersFile;
--- a/hr-management/classes/Models/Stage.php
+++ b/hr-management/classes/Models/Stage.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_Array;
use CrewHRMHelpers_String;
@@ -149,8 +154,9 @@
global $wpdb;
$stages = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT * FROM {$wpdb->crewhrm_stages} WHERE job_id IN ({$ids_places}) ORDER BY sequence",
+ $wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ 'SELECT * FROM %i WHERE job_id IN (' . $ids_places . ') ORDER BY sequence', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
+ $wpdb->crewhrm_stages,
...$ids_in
),
ARRAY_A
@@ -297,47 +303,55 @@
global $wpdb;
$order_by = $args['order_by'] ?? 'application_date';
- $order = $args['order'] ?? 'DESC';
+ $order = strtoupper( $args['order'] ?? 'DESC' );
+ $allowed_order_by = array( 'application_date', 'application_id', 'first_name', 'last_name' );
+ $order_by = in_array( $order_by, $allowed_order_by, true ) ? $order_by : 'application_date';
+ $order = in_array( $order, array( 'ASC', 'DESC' ), true ) ? $order : 'DESC';
$limit = $args['limit'] ?? 2;
$offset = ( ( $args['page'] ?? 1 ) - 1 ) * $limit;
$where_clause = '';
+ $where_args = array();
if ( ! empty( $args['job_id'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND job_id=%d', $args['job_id'] );
+ $where_clause .= ' AND job_id=%d';
+ $where_args[] = $args['job_id'];
}
if ( ! empty( $args['stage_id'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND stage_id=%d', $args['stage_id'] );
+ $where_clause .= ' AND stage_id=%d';
+ $where_args[] = $args['stage_id'];
}
+ $query_args = array_merge( array( $wpdb->crewhrm_applications ), $where_args, array( $limit, $offset ) );
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$applications = $wpdb->get_results(
- $wpdb->prepare(
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT
application_id,
- job_id,
- stage_id,
- address_id,
- first_name,
- last_name,
- email,
- phone,
- date_of_birth,
- gender,
- cover_letter,
- resume_file_id,
- is_complete,
- UNIX_TIMESTAMP(application_date) AS application_date
+ job_id,
+ stage_id,
+ address_id,
+ first_name,
+ last_name,
+ email,
+ phone,
+ date_of_birth,
+ gender,
+ cover_letter,
+ resume_file_id,
+ is_complete,
+ UNIX_TIMESTAMP(application_date) AS application_date
FROM
- {$wpdb->crewhrm_applications}
+ %i
WHERE
1=1 {$where_clause}
ORDER BY {$order_by} {$order} LIMIT %d OFFSET %d",
- $limit,
- $offset
+ ...$query_args
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
return _Array::castRecursive( $applications );
}
@@ -361,6 +375,7 @@
// Get application counts per stage per job.
global $wpdb;
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$counts = $wpdb->get_results(
$wpdb->prepare(
"SELECT
@@ -368,14 +383,16 @@
stage_id,
COUNT(application_id) as candidates
FROM
- {$wpdb->crewhrm_applications}
+ %i
WHERE
job_id IN ({$ids_places})
GROUP BY job_id, stage_id",
+ $wpdb->crewhrm_applications,
...$job_ids
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
if ( empty( $counts ) ) {
return array();
@@ -397,6 +414,7 @@
// Get the stages sequence to sort.
// Exclude disqualified as it is used in special way and has no usage in frontend view.
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$sequences = $wpdb->get_results(
$wpdb->prepare(
"SELECT
@@ -405,14 +423,16 @@
stage_name,
sequence
FROM
- {$wpdb->crewhrm_stages}
+ %i
WHERE job_id IN ({$ids_places})
AND stage_name!='_disqualified_'
ORDER BY sequence",
+ $wpdb->crewhrm_stages,
...$job_ids
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$sequences = _Array::castRecursive( $sequences );
// Generate new stage array per job based on sequence order
--- a/hr-management/classes/Models/User.php
+++ b/hr-management/classes/Models/User.php
@@ -105,12 +105,26 @@
global $wpdb;
- $keyword = esc_sql( $keyword );
+ $keyword = sanitize_text_field( $keyword );
$skip_ids = array_values( _Array::getArray( $skip_ids, false, 0 ) );
$ids_places = _String::getPlaceHolders( $skip_ids );
+ $role_clause = ! empty( $role ) ? ' AND _meta.meta_value=%s' : '';
+ $query_args = array(
+ self::META_KEY_CREW_FLAG,
+ $keyword,
+ $keyword,
+ $keyword,
+ '%' . $wpdb->esc_like( $keyword ) . '%',
+ '%' . $wpdb->esc_like( $keyword ) . '%',
+ );
+
+ if ( ! empty( $role ) ) {
+ $query_args[] = $role;
+ }
- $role_clause = ! empty( $role ) ? $wpdb->prepare( ' AND _meta.meta_value=%s', $role ) : '';
+ $query_args = array_merge( $query_args, $skip_ids );
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$users = $wpdb->get_results(
$wpdb->prepare(
"SELECT
@@ -128,20 +142,15 @@
OR _user.display_name LIKE %s
OR _user.user_nicename LIKE %s
)
- AND _user.ID NOT IN ({$ids_places})
- {$role_clause}
- LIMIT 50",
- self::META_KEY_CREW_FLAG,
- $keyword,
- $keyword,
- $keyword,
- "%{$wpdb->esc_like( $keyword )}%",
- "%{$wpdb->esc_like( $keyword )}%",
- ...$skip_ids
- ),
- ARRAY_A
- );
+ AND _user.ID NOT IN ({$ids_places})
+ {$role_clause}
+ LIMIT 50",
+ ...$query_args
+ ),
+ ARRAY_A
+ );
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$users_array = array();
// Convert to generic data structure in favour of instant search component
@@ -339,74 +348,98 @@
$wp_collate = $wpdb->collate;
$where_clause = '';
+ $where_args = array();
// Search employee by keyword
if ( ! empty( $args['search'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND _user.display_name LIKE %s', "%{$wpdb->esc_like( $args['search'] )}%" );
+ $where_clause .= ' AND _user.display_name LIKE %s';
+ $where_args[] = '%' . $wpdb->esc_like( $args['search'] ) . '%';
}
// Get by department ID
if ( ! empty( $args['department_id'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND _employment.department_id=%d', $args['department_id'] );
+ $where_clause .= ' AND _employment.department_id=%d';
+ $where_args[] = $args['department_id'];
}
// Employment status filter
if ( ! empty( $args['employment_status'] ) ) {
- $where_clause .= $wpdb->prepare( ' AND _employment.employment_status=%s', $args['employment_status'] );
+ $where_clause .= ' AND _employment.employment_status=%s';
+ $where_args[] = $args['employment_status'];
}
+ $user_query_args = array_merge(
+ array(
+ self::META_KEY_CREW_FLAG,
+ self::ROLE_EMPLOYEE,
+ ),
+ $where_args,
+ array(
+ $limit,
+ $offset,
+ )
+ );
+
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$users = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT
- _user.ID AS user_id,
- _user.display_name,
- _user.user_email,
- _employment.employment_id,
- _employment.designation,
- _employment.employment_status,
- _employment.department_id,
- _employment.employment_type,
- _employment.hire_date,
- _employment.reporting_person_user_id
- FROM
- {$wpdb->users} _user
- INNER JOIN {$wpdb->usermeta} _meta ON _user.ID=_meta.user_id AND _meta.meta_key=%s AND _meta.meta_value=%s
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ "SELECT
+ _user.ID AS user_id,
+ _user.display_name,
+ _user.user_email,
+ _employment.employment_id,
+ _employment.designation,
+ _employment.employment_status,
+ _employment.department_id,
+ _employment.employment_type,
+ _employment.hire_date,
+ _employment.reporting_person_user_id
+ FROM
+ {$wpdb->users} _user
+ INNER JOIN {$wpdb->usermeta} _meta ON _user.ID=_meta.user_id AND _meta.meta_key=%s AND _meta.meta_value=%s
INNER JOIN {$wpdb->crewhrm_employments} _employment ON _employment.employee_user_id COLLATE $wp_collate=_user.ID
WHERE
1=1
- {$where_clause}
- ORDER BY
- _employment.employment_id DESC
- LIMIT
- %d
- OFFSET
- %d",
- self::META_KEY_CREW_FLAG,
- self::ROLE_EMPLOYEE,
- $limit,
- $offset
+ {$where_clause}
+ ORDER BY
+ _employment.employment_id DESC
+ LIMIT
+ %d
+ OFFSET
+ %d",
+ ...$user_query_args
),
ARRAY_A
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$users = _Array::castRecursive( $users );
+ $count_query_args = array_merge(
+ array(
+ self::META_KEY_CREW_FLAG,
+ self::ROLE_EMPLOYEE,
+ ),
+ $where_args
+ );
+
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$total_count = (int) $wpdb->get_var(
- $wpdb->prepare(
- "SELECT
- COUNT(_user.ID)
- FROM
- {$wpdb->users} _user
- INNER JOIN {$wpdb->usermeta} _meta ON _user.ID=_meta.user_id AND _meta.meta_key=%s AND _meta.meta_value=%s
+ $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ "SELECT
+ COUNT(_user.ID)
+ FROM
+ {$wpdb->users} _user
+ INNER JOIN {$wpdb->usermeta} _meta ON _user.ID=_meta.user_id AND _meta.meta_key=%s AND _meta.meta_value=%s
LEFT JOIN {$wpdb->crewhrm_employments} _employment ON _employment.employee_user_id COLLATE $wp_collate=_user.ID
- WHERE
- 1=1
- {$where_clause}",
- self::META_KEY_CREW_FLAG,
- self::ROLE_EMPLOYEE
+ WHERE
+ 1=1
+ {$where_clause}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ ...$count_query_args
)
);
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$page_count = ceil( $total_count / $limit );
// Loop through users and assign meta data
--- a/hr-management/classes/Models/WeeklySchedule.php
+++ b/hr-management/classes/Models/WeeklySchedule.php
@@ -7,6 +7,11 @@
namespace CrewHRMModels;
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+
use CrewHRMHelpers_String;
class WeeklySchedule {
@@ -82,17 +87,23 @@
}
// If user ID not passed, it means it is global settings
- $where_clause = $employment_id === null ? ' employment_id IS NULL' : $wpdb->prepare( ' employment_id=%d', $employment_id );
+ $where_clause = $employment_id === null ? ' employment_id IS NULL' : ' employment_id=%d';
+ $args = $employment_id === null ? array() : array( $employment_id );
// Delete all slots except remaings
if ( ! empty( $remaining_ids ) ) {
$remaining_ids = array_values( $remaining_ids );
$ids_places = _String::getPlaceHolders( $remaining_ids );
- $where_clause .= $wpdb->prepare( " AND schedule_id NOT IN ({$ids_places})", ...$remaining_ids );
+ $where_clause .= ' AND schedule_id NOT IN (' . $ids_places . ')';
+ $args = array_merge( $args, $remaining_ids );
}
$wpdb->query(
- "DELETE FROM {$wpdb->crewhrm_weekly