WorkScout Freelancer plugin.
Folder structure:
=========================
Folder: Assets
Sub-Folder of Assets: css
Freelancer.css
Icons.css
Sub-Folder of Assets: fonts has various font files
Sub-Folder of Assets: images has various flag images
Sub-Folder of Assets: js
Ajax.search.min.js
Bootstrap-select.min.js
Bootstrap-slider.min.js
Snackbar.js
Tippy.all.min.js
workscout-freelancer-frontend.js
Sub-Folder of Assets: sass (I don’t think you need these)
=========================
Folder: Includes
Sub-Folder of Includes: Admin
– class-workscout-freelancer-admin.php
– class-workscout-freelancer-settings.php
Sub-Folder of Includes: Forms
– class-workscout-freelancer-form-edit-task.php
– class-workscout-freelancer-form-submit-task.php
Sub-Folder of Includes: Paid Listings
Leaving this out because I am not using the paid listings feature. If you find that you are missing code, we can explore this folder.
Misc. PHP files in Folder: Includes
– class-wc-paid-listings-submit-task-form
– class-wc-product-task-package
– class-workscout-freelancer
– class-workscout-freelancer-bid
– class-workscout-freelancer-cpt
– class-workscout-freelancer-emails
– class-workscout-freelancer-forms
– class-workscout-freelancer-meta-boxes
– class-workscout-freelancer-project
– class-workscout-freelancer-reviews
– class-workscout-freelancer-shortcodes
– class-workscout-freelancer-task
– class-workscout-freelancer-templates
– class-workscout-freelancer-user
=========================
Folder: Languages
– workscout-freelancer-pot
Leaving this out since language is not our concern)
=========================
Folder: Lib
Sub-Folder of Lib: cmb2-tabs (note cmb2 is another plugin, similar to Advanced Custom Fields)
Sub-Folder of cmb2-tabs: Assets
cmb2-tabs.css
cmb2-tabs.js
Sub-Folder of cmb2-tabs:
assets.class.php
cmb2-tabs.class.php
Mis. PHP files in Sub-Folder: cmb2-tabs:
autoloader.php
example.php
plugin.php
Misc. PHP file in Folder: Lib
class-gamajo-template-loader
=========================
Folder: Templates
Sub-Folder of Templates: account
freelancer-fields
Sub-Folder of Templates: form-fields
dynamic-input-field.php
radio-field.php
Sub-Folder of Templates: single-partials
single-company.php
single-task-attachments.php
single-task-bids.php
single-task-skills.php
Misc. PHP files in Folder: Templates
archive-task
archive-task-full
content-single-task
content-task
content-task-grid
my-bids
my-projects
no-task-found
project-view
sidebar-tasks
single-task
task-bids
task-dashboard
task-package-selection
task-preview
tasks-end
tasks-start
task-submit
task-submitted
=========================
File: Config.codekit3
File: Workscout-freelancer.php
File: Workscout-freelancer-functions.php
All code below:
workscout-freelancer.php
<?php
/**
* Plugin Name: WorkScout Freelancer For WP Job Manager
* Description: This plugin adds freelancer functionality for WorkScout WP Job Manager
* Version: 1.1
* Author: Purethemes
* Author URI: https://purethemes.net/
*
* Text Domain: workscout-freelancer
* Domain Path: /languages/
*
* @package WorkScout Freelancer
* @category Core
* @author PureThemes
*/
// Exit if accessed directly.
if (!defined(‘ABSPATH’)) {
exit;
}
/**
* WorkScout_Freelancer class.
*/
class WorkScout_Freelancer
{
const JOB_MANAGER_CORE_MIN_VERSION = ‘1.31.1’;
public $post_types;
public $emails;
public $writepanels;
public $bid;
public $task;
public $forms;
public $reviews;
public $freelancer_project;
/**
* __construct function.
*/
public function __construct()
{
// Define constants.
define(‘WORKSCOUT_FREELANCER_VERSION’, ‘1.1’);
define(‘WORKSCOUT_FREELANCER_PLUGIN_DIR’, untrailingslashit(plugin_dir_path(__FILE__)));
define(‘WORKSCOUT_FREELANCER_PLUGIN_URL’, untrailingslashit(plugins_url(basename(plugin_dir_path(__FILE__)), basename(__FILE__))));
// Includes.
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-cpt.php’;
// Init class needed for activation.
$this->post_types = WorkScout_Freelancer_CPT::instance();
register_activation_hook(basename(dirname(__FILE__)) . ‘/’ . basename(__FILE__), ‘flush_rewrite_rules’, 15);
register_activation_hook(basename(dirname(__FILE__)) . ‘/’ . basename(__FILE__), array($this, ‘package_terms’), 15);
add_action(‘plugins_loaded’, array($this, ‘init_plugin’), 13);
add_action(‘plugins_loaded’, array($this, ‘admin’), 14);
add_action(‘admin_notices’, array($this, ‘version_check’));
add_action(‘after_setup_theme’, array($this, ‘include_template_functions’), 11);
add_action(‘wp_enqueue_scripts’, array($this, ‘enqueue_styles’), 10);
add_action(‘wp_enqueue_scripts’, array($this, ‘enqueue_scripts’), 10);
add_filter(‘template_include’, array($this, ‘task_templates’));
add_filter(‘get_the_author_url’, array(__CLASS__, ‘author_link’), 10, 2);
add_filter(‘author_link’, array(__CLASS__, ‘author_link’), 10, 2);
}
/**
* Initializes plugin.
*/
public function init_plugin()
{
if (!class_exists(‘WP_Job_Manager’)) {
return;
}
// Includes.
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-meta-boxes.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-bid.php’;
// include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-user.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-forms.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-shortcodes.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-task.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-reviews.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-project.php’;
include_once dirname(__FILE__) . ‘/includes/class-workscout-freelancer-emails.php’;
if(class_exists(‘WP_Job_Manager_Paid_Listings’) || class_exists(‘WC_Paid_Listings’)){
include_once dirname(__FILE__) . ‘/includes/class-wc-paid-listings-submit-task-form.php’;
include(dirname(__FILE__) . ‘/includes/paid-listings/class-workscout-freelancer-paid-listings.php’);
include(dirname(__FILE__) . ‘/includes/paid-listings/class-wc-product-task-package.php’);
include(dirname(__FILE__) . ‘/includes/paid-listings/class-workscout-freelancer-paid-listings-admin.php’);
include(dirname(__FILE__) . ‘/includes/paid-listings/class-workscout-freelancer-paid-listings-admin-listings.php’);
}
include_once dirname(__FILE__) . ‘/includes/paid-listings/user-functions.php’;
// // Init classes.
$this->writepanels = new WorkScout_Freelancer_Meta_Boxes();
$this->bid = new WorkScout_Freelancer_Bid();
$this->task = new WorkScout_Freelancer_Task();
$this->forms = new WorkScout_Freelancer_Forms();
$this->reviews = new WorkScout_Freelancer_Reviews();
$this->freelancer_project = new WorkScout_Freelancer_Project();
$this->emails = WorkScout_Freelancer_Emails::instance();
add_action(‘switch_theme’, ‘flush_rewrite_rules’, 15);
self::maybe_schedule_cron_jobs();
}
public function include_template_functions()
{
include(dirname(__FILE__) . ‘/workscout-freelancer-functions.php’);
}
static function author_link($permalink, $user_id)
{
$author_id = get_user_meta($user_id, ‘freelancer_profile’, true);
if ($author_id) {
$permalink = get_post_permalink($author_id);
}
return $permalink;
}
/* handles single listing and archive listing view */
public static function task_templates($template)
{
$post_type = get_post_type();
$custom_post_types = array(‘task’);
$template_loader = new WorkScout_Freelancer_Template_Loader;
if (in_array($post_type, $custom_post_types)) {
if (is_archive() && !is_author()) {
$template = $template_loader->locate_template(‘archive-‘ . $post_type . ‘.php’);
return $template;
}
if (is_single()) {
$template = $template_loader->locate_template(‘single-‘ . $post_type . ‘.php’);
return $template;
}
}
return $template;
}
/**
* Checks WPJM core version.
*/
public function version_check()
{
if (!class_exists(‘WP_Job_Manager’) || !defined(‘JOB_MANAGER_VERSION’)) {
$screen = get_current_screen();
if (null !== $screen && ‘plugins’ === $screen->id) {
$this->display_error(__(‘<em>WorkScout Freelancer</em> requires WP Job Manager to be installed and activated.’, ‘workscout-freelancer’));
}
}
}
/**
* Schedule cron jobs for Listeo_Core events.
*/
public static function maybe_schedule_cron_jobs()
{
if (!wp_next_scheduled(‘workscout_freelancer_check_for_expired_tasks’)) {
wp_schedule_event(time(), ‘hourly’, ‘workscout_freelancer_check_for_expired_tasks’);
}
}
/**
* Display error message notice in the admin.
*
* @param string $message
*/
private function display_error($message)
{
echo ‘<div class=”error”>’;
echo ‘<p>’ . wp_kses_post($message) . ‘</p>’;
echo ‘</div>’;
}
function package_terms(){
if (!get_term_by(‘slug’, sanitize_title(‘task_package’), ‘product_type’)) {
wp_insert_term(‘task_package’, ‘product_type’);
}
if (!get_term_by(‘slug’, sanitize_title(‘task_package_subscription’), ‘product_type’)) {
wp_insert_term(‘task_package_subscription’, ‘product_type’);
}
}
// /**
// * Loads the REST API functionality.
// */
// public function rest_init()
// {
// include_once RESUME_MANAGER_PLUGIN_DIR . ‘/includes/class-wp-resume-manager-rest-api.php’;
// WP_Resume_Manager_REST_API::init();
// }
/**
* Include admin
*/
public function admin()
{
if (is_admin() && class_exists(‘WP_Job_Manager’)) {
include_once ‘includes/admin/class-workscout-freelancer-admin.php’;
}
}
/**
* Localisation
*
* @access private
* @return void
*/
public function load_plugin_textdomain()
{
$locale = apply_filters(‘plugin_locale’, get_locale(), ‘workscout-freelancer’);
load_textdomain(‘workscout-freelancer’, WP_LANG_DIR . “/workscout-freelancer/workscout-freelancer-$locale.mo”);
load_plugin_textdomain(‘workscout-freelancer’, false, dirname(plugin_basename(__FILE__)) . ‘/languages/’);
}
/**
* Frontend_scripts function.
*
* @access public
* @return void
*/
public function frontend_scripts()
{
global $post;
$ajax_url = admin_url(‘admin-ajax.php’, ‘relative’);
$ajax_filter_deps = array(‘jquery’);
// WPML workaround until this is standardized.
if (defined(‘ICL_LANGUAGE_CODE’)) {
$ajax_url = add_query_arg(‘lang’, ICL_LANGUAGE_CODE, $ajax_url);
}
if (wp_script_is(‘select2’, ‘registered’)) {
$ajax_filter_deps[] = ‘select2’;
wp_enqueue_style(‘select2’);
}
}
/**
* Load frontend CSS.
* @access public
* @since 1.0.0
* @return void
*/
public function enqueue_styles()
{
//wp_register_style(‘workscout-freelancer-icons’, WORKSCOUT_FREELANCER_PLUGIN_URL. ‘/assets/css/icons.css’, array(), WORKSCOUT_FREELANCER_VERSION);
wp_register_style(‘workscout-freelancer-frontend’, WORKSCOUT_FREELANCER_PLUGIN_URL. ‘/assets/css/freelancer.css’, array(), WORKSCOUT_FREELANCER_VERSION);
//wp_enqueue_style(‘workscout-freelancer-icons’);
wp_enqueue_style(‘workscout-freelancer-frontend’);
} // End enqueue_styles ()
/**
* Load frontend JS.
* @access public
* @since 1.0.0
* @return void
*/
public function enqueue_scripts()
{
wp_register_script(‘bootstrap-select’, WORKSCOUT_FREELANCER_PLUGIN_URL . ‘/assets/js/bootstrap-select.min.js’, array(‘jquery’), WORKSCOUT_FREELANCER_VERSION, true);
wp_register_script(‘snackbar’, WORKSCOUT_FREELANCER_PLUGIN_URL . ‘/assets/js/snackbar.js’, array(‘jquery’), WORKSCOUT_FREELANCER_VERSION, true);
wp_register_script(‘tippy’, WORKSCOUT_FREELANCER_PLUGIN_URL . ‘/assets/js/tippy.all.min.js’, array(‘jquery’), WORKSCOUT_FREELANCER_VERSION, true);
wp_register_script(‘workscout-freelancer-frontend’, WORKSCOUT_FREELANCER_PLUGIN_URL . ‘/assets/js/workscout-freelancer-frontend.js’, array(‘bootstrap-slider’, ‘snackbar’, ‘tippy’, ‘bootstrap-select’, ‘workscout_core-frontend’), WORKSCOUT_FREELANCER_VERSION, true);
wp_enqueue_script(‘workscout-freelancer-frontend’);
wp_register_script(‘workscout-freelancer-ajaxsearch’, WORKSCOUT_FREELANCER_PLUGIN_URL . ‘/assets/js/ajax.search.min.js’, array(‘jquery’), WORKSCOUT_FREELANCER_VERSION, true);
// wp_enqueue_script(‘ajaxsearch’);
} // End enqueue_styles ()
}
$GLOBALS[‘workscout_freelancer’] = new WorkScout_Freelancer();
if (!class_exists(‘Gamajo_Template_Loader’)) {
require_once dirname(__FILE__) . ‘/lib/class-gamajo-template-loader.php’;
}
include(dirname(__FILE__) . ‘/includes/class-workscout-freelancer-templates.php’);
if (file_exists(dirname(__FILE__) . ‘/lib/cmb2-tabs/plugin.php’)) {
require_once dirname(__FILE__) . ‘/lib/cmb2-tabs/plugin.php’;
}
Workscout-freelancer-functions.php
<?php
function task_publish_date($post = null)
{
$date_format = get_option(‘job_manager_date_format’);
if (‘default’ === $date_format) {
$display_date = wp_date(get_option(‘date_format’), get_post_timestamp($post));
} else {
// translators: Placeholder %s is the relative, human readable time since the job listing was posted.
$display_date = human_time_diff(get_post_timestamp($post), time());
}
echo ‘<time datetime=”‘ . esc_attr(get_post_datetime($post)->format(‘Y-m-d’)) . ‘”>’ . wp_kses_post($display_date) . ‘</time>’;
}
function workscoutThousandsCurrencyFormat($num)
{
if ($num > 1000) {
// get option for separator
$separator = get_option(‘workscout_thousand_separator’, ‘.’);
$x = round($num);
$x_number_format = number_format($x);
$x_array = explode(‘,’, $x_number_format);
$x_parts = array(‘k’, ‘m’, ‘b’, ‘t’);
$x_count_parts = count($x_array) – 1;
$x_display = $x;
$x_display = $x_array[0] . ((int) $x_array[1][0] !== 0 ? $separator . $x_array[1][0] : ”);
$x_display .= $x_parts[$x_count_parts – 1];
return $x_display;
}
return $num;
}
/**
* True if an the user can bid a task.
*
* @param $task_id
*
* @return bool
*/
function workscout_freelancer_user_can_bid($task_id) {
$can_bid = true;
if (!$task_id || !is_user_logged_in()) {
$can_bid = false;
} else {
$task = get_post($task_id);
$get_bids = get_posts(array(
‘post_type’ => ‘bid’,
‘post_parent’ => $task_id,
‘post_status’ => ‘publish’,
‘author’ => get_current_user_id(),
‘posts_per_page’ => -1
));
//check if current user is author of any of the posts from $get_bids
if (count($get_bids) > 0) {
$can_bid = false;
}
}
return apply_filters(‘workscout_freelancer_user_can_bid’, $can_bid, $task_id);
}
/**
* True if an the user can edit a task.
*
* @param $task_id
*
* @return bool
*/
function workscout_freelancer_user_can_edit_task($task_id)
{
$can_edit = true;
if (!$task_id || !is_user_logged_in()) {
$can_edit = false;
if (
$task_id
// && !task_manager_user_requires_account()
&& isset($_COOKIE[‘wp-job-manager-submitting-task-key-‘ . $task_id])
&& $_COOKIE[‘wp-job-manager-submitting-task-key-‘ . $task_id] === get_post_meta($task_id, ‘_submitting_key’, true)
) {
$can_edit = true;
}
} else {
$task = get_post($task_id);
if (!$task || (absint($task->post_author) !== get_current_user_id() && !current_user_can(‘edit_post’, $task_id))) {
$can_edit = false;
}
}
return apply_filters(‘workscout_freelancer_user_can_edit_task’, $can_edit, $task_id);
}
/**
* Checks if users are allowed to edit submissions that are pending approval.
*
* @since 1.16.1
* @return bool
*/
function workscout_freelancer_user_can_edit_pending_submissions()
{
return apply_filters(‘workscout_freelancer_user_can_edit_pending_submissions’, 1 === intval(get_option(‘workscout_freelancer_user_can_edit_pending_submissions’)));
}
/**
* Checks if users are allowed to edit published submissions.
*
* @since 1.29.0
* @return bool
*/
function workscout_freelancer_user_can_edit_published_submissions()
{
/**
* Override the setting for allowing a user to edit published job listings.
*
* @since 1.29.0
*
* @param bool $can_edit_published_submissions
*/
return apply_filters(‘workscout_freelancer_user_can_edit_published_submissions’, in_array(get_option(‘workscout_freelancer_user_edit_published_submissions’), [‘yes’, ‘yes_moderated’], true));
}
/**
* True if an the user can post a task. By default, you must be logged in.
*
* @return bool
*/
function workscout_freelancer_user_can_post_task()
{
$can_post = true;
if (!is_user_logged_in()) {
// if (task_manager_user_requires_account() && !task_manager_enable_registration()) {
$can_post = false;
//}
}
return apply_filters(‘task_manager_user_can_post_task’, $can_post);
}
/**
* True if an account is required to post.
*
* @return bool
*/
function workscout_freelancer_user_requires_account()
{
return apply_filters(‘task_manager_user_requires_account’, get_option(‘task_manager_user_requires_account’) == 1 ? true : false);
}
/**
* Outputs the jobs status
*
* @param WP_Post|int $post (default: null)
*/
function the_task_status($post = null)
{
echo get_the_task_status($post);
}
/**
* Gets the jobs status
*
* @param WP_Post|int $post (default: null)
* @return string
*/
function get_the_task_status($post = null)
{
$post = get_post($post);
$status = $post->post_status;
if ($status == ‘publish’) {
$status = __(‘Published’, ‘workscout-freelancer’);
} elseif ($status == ‘expired’) {
$status = __(‘Expired’, ‘workscout-freelancer’);
} elseif ($status == ‘pending’) {
$status = __(‘Pending Review’, ‘workscout-freelancer’);
} elseif ($status == ‘hidden’) {
$status = __(‘Hidden’, ‘workscout-freelancer’);
} elseif ($status == ‘in_progress’) {
$status = __(‘In Progress’, ‘workscout-freelancer’);
} elseif ($status == ‘completed’) {
$status = __(‘Completed’, ‘workscout-freelancer’);
} else {
$status = __(‘Inactive’, ‘workscout-freelancer’);
}
return apply_filters(‘the_task_status’, $status, $post);
}
/**
* Gets the jobs status
*
* @param WP_Post|int $post (default: null)
* @return string
*/
function get_the_task_status_class($post = null)
{
$post = get_post($post);
$status = $post->post_status;
return apply_filters(‘the_task_status_class’, $status, $post);
}
if (!function_exists(‘get_task_bidders_count’)) {
/**
* Get number of applications for a job
*
* @param int $task_id
* @return int
*/
function get_task_bidders_count($task_id)
{
$count = count(
get_posts(
[
‘post_type’ => ‘bid’,
‘post_status’ => [‘publish’],
‘posts_per_page’ => -1,
‘fields’ => ‘ids’,
‘post_parent’ => $task_id,
]
)
);
wp_reset_postdata();
return $count;
}
}
function workscout_freelancer_ajax_pagination($pages = ”, $current = false, $range = 2)
{
if (!empty($current)) {
$paged = $current;
} else {
global $paged;
}
$output = false;
if (empty($paged)) $paged = 1;
$prev = $paged – 1;
$next = $paged + 1;
$showitems = ($range * 2) + 1;
$range = 2; // change it to show more links
if ($pages == ”) {
global $wp_query;
$pages = $wp_query->max_num_pages;
if (!$pages) {
$pages = 1;
}
}
if (1 != $pages) {
$output .= ‘<nav class=”pagination margin-top-30″><ul class=”pagination”>’;
$output .= ($paged > 2 && $paged > $range + 1 && $showitems < $pages) ? ‘<li data-paged=”prev”><a href=”#”><i class=”sl sl-icon-arrow-left”></i></a></li>’ : ”;
//$output .= ( $paged > 1 ) ? ‘<li><a class=”previouspostslink” href=”#””>’.__(‘Previous’,’workscout_core’).'</a></li>’ : ”;
for ($i = 1; $i <= $pages; $i++) {
if (1 != $pages && (!($i >= $paged + $range + 1 || $i <= $paged – $range – 1) || $pages <= $showitems)) {
if ($paged == $i) {
$output .= ‘<li class=”current” data-paged=”‘ . $i . ‘”><a href=”#”>’ . $i . ‘ </a></li>’;
} else {
$output .= ‘<li data-paged=”‘ . $i . ‘”><a href=”#”>’ . $i . ‘</a></li>’;
}
}
}
// $output .= ( $paged < $pages ) ? ‘<li><a class=”nextpostslink” href=”#”>’.__(‘Next’,’workscout_core’).'</a></li>’ : ”;
$output .= ($paged < $pages – 1 && $paged + $range – 1 < $pages && $showitems < $pages) ? ‘<li data-paged=”next”><a href=”#”><i class=”sl sl-icon-arrow-right”></i></a></li>’ : ”;
$output .= ‘</ul></nav>’;
}
return $output;
}
function workscout_freelancer_pagination($pages = ”, $current = false, $range = 2)
{
if (!empty($current)) {
$paged = $current;
} else {
global $paged;
}
if (empty($paged)) $paged = 1;
$prev = $paged – 1;
$next = $paged + 1;
$showitems = ($range * 2) + 1;
$range = 2; // change it to show more links
if ($pages == ”) {
global $wp_query;
$pages = $wp_query->max_num_pages;
if (!$pages) {
$pages = 1;
}
}
// check on wchih page we are
if (1 != $pages) {
echo ‘<nav class=”pagination margin-top-30″><ul class=”pagination”>’;
echo ($paged > 2 && $paged > $range + 1 && $showitems < $pages) ? ‘<li><a href=”‘ . get_pagenum_link(1) . ‘”><i class=”sl sl-icon-arrow-left”></i></a></li>’ : ”;
// echo ( $paged > 1 ) ? ‘<li><a class=”previouspostslink” href=”‘.get_pagenum_link($prev).'”>’.__(‘Previous’,’workscout_core’).'</a></li>’ : ”;
for ($i = 1; $i <= $pages; $i++) {
if (1 != $pages && (!($i >= $paged + $range + 1 || $i <= $paged – $range – 1) || $pages <= $showitems)) {
if ($paged == $i) {
echo ‘<li class=”current” data-paged=”‘ . $i . ‘”><a href=”‘ . get_pagenum_link($i) . ‘”>’ . $i . ‘ </a></li>’;
} else {
echo ‘<li data-paged=”‘ . $i . ‘”><a href=”‘ . get_pagenum_link($i) . ‘”>’ . $i . ‘</a></li>’;
}
}
}
// echo ( $paged < $pages ) ? ‘<li><a class=”nextpostslink” href=”‘.get_pagenum_link($next).'”>’.__(‘Next’,’workscout_core’).'</a></li>’ : ”;
echo ($paged < $pages – 1 && $paged + $range – 1 < $pages && $showitems < $pages) ? ‘<li><a href=”‘ . get_pagenum_link($pages) . ‘”><i class=”sl sl-icon-arrow-right”></i></a></li>’ : ”;
echo ‘</ul></nav>’;
}
}
if (!function_exists(‘workscout_generate_tasks_sidebar’)) {
function workscout_generate_tasks_sidebar()
{
$template_loader = new WorkScout_Freelancer_Template_Loader;
ob_start();
$template_loader->get_template_part(‘sidebar-tasks’);
$result = ob_get_clean();
return $result;
}
}
function workscout_get_options_array($type, $data)
{
$options = array();
if ($type == ‘taxonomy’) {
$args = array(
‘taxonomy’ => $data,
‘hide_empty’ => true,
‘orderby’ => ‘term_order’
);
$args = apply_filters(‘listeo_taxonomy_dropdown_options_args’, $args);
$categories = get_terms($data, $args);
$options = array();
foreach ($categories as $cat) {
$options[$cat->term_id] = array(
‘name’ => $cat->name,
‘slug’ => $cat->slug,
‘id’ => $cat->term_id,
);
}
}
return $options;
}
function get_workscout_task_type($post = null)
{
$post = get_post($post);
if (is_null($post)) {
return false;
}
switch (get_post_meta($post->ID, ‘_task_type’, true)) {
case ‘fixed’:
return __(‘Fixed’, ‘workscout-freelancer’);
break;
case ‘hourly’:
return __(‘Hourly’, ‘workscout-freelancer’);
break;
default:
return __(‘Fixed’, ‘workscout-freelancer’);
break;
}
}
function get_workscout_task_range($post= null){
$post = get_post($post);
if (is_null($post)) {
return false;
}
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$task_type = get_post_meta($post->ID, ‘_task_type’, true);
ob_start();
if($task_type == ‘hourly’) {
$hourly_min = get_post_meta($post->ID, ‘_hourly_min’, true);
$hourly_max = get_post_meta($post->ID, ‘_hourly_max’, true);
if ($hourly_min) {
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_min));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
if ($hourly_max && $hourly_max > $hourly_min) {
if ($hourly_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_max));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
}
if ($task_type == ‘fixed’) {
$budget_min = get_post_meta($post->ID, ‘_budget_min’, true);
$budget_max = get_post_meta($post->ID, ‘_budget_max’, true);
if ($budget_min) {
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_min));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
if ($budget_max && $budget_max > $budget_min) {
if ($budget_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_max));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
}
$output = ob_get_clean();
return $output;
}
function get_workscout_task_bidders_average($task = null)
{
$task = get_post($task);
if (is_null($task)) {
return false;
}
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$counter = 0;
$cumulative_value = 0;
$avg_query = new WP_Query([
‘post_type’ => ‘bid’,
‘post_status’ => [‘publish’],
‘posts_per_page’ => -1,
‘fields’ => ‘ids’,
‘post_parent’ => $task->ID,
]);
if (
$avg_query->have_posts()
) :
while ($avg_query->have_posts()) : $avg_query->the_post();
$post = get_post();
if ($rating_value = get_post_meta($post->ID, ‘_budget’, true)) :
$cumulative_value += $rating_value;
$counter++;
endif;
endwhile;
endif;
if($counter == 0){
return 0;
}
$avg_value = $cumulative_value / $counter;
ob_start();
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo $avg_value;
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
$avg = ob_get_clean();
return $avg;
}
function workscout_get_bidding_deadline($id){
$deadline_date = get_post_meta($id, ‘_task_deadline’, true);
if ($deadline_date) {
// show how many days and hours are until the timestamp
//$time_left = human_time_diff(current_time(‘U’), $deadline_date);
// change 2023-10-31 to timestamp
$deadline_date = strtotime($deadline_date);
$currentTime = time();
$timeDifference = $deadline_date – $currentTime;
if ($timeDifference > 0) {
$days = floor($timeDifference / (60 * 60 * 24));
$hours = floor(($timeDifference % (60 * 60 * 24)) / (60 * 60));
$deadline = array(
‘days’ => sprintf(_n(‘%s day’, ‘%s days’, $days, ‘workscout-freelancer’), $days),
‘hours’ => sprintf(_n(‘, %s hour’, ‘, %s hours’, $hours, ‘workscout-freelancer’), $hours)
);
return $deadline;
} else {
return true;
}
} else {
return false;
}
}
function workscout_get_task_range($task_id){
if(!$task_id){
return false;
}
$task_type = get_post_meta($task_id, ‘_task_type’, true);
$budget_min = get_post_meta($task_id, ‘_budget_min’, true);
$budget_max = get_post_meta($task_id, ‘_budget_max’, true);
$hourly_min = get_post_meta($task_id, ‘_hourly_min’, true);
$hourly_max = get_post_meta($task_id, ‘_hourly_max’, true);
if ($task_type == ‘hourly’) {
$range_min = $hourly_min;
$range_max = $hourly_max;
} else {
$range_min = $budget_min;
$range_max = $budget_max;
}
if (empty($range_min) && !empty($range_max)) {
$range_min = $range_max – ($range_max * 0.3);
}
if (empty($range_max) && !empty($range_min)) {
$range_max = $range_min – ($range_max * 0.3);
}
$range = $range_max – $range_min;
if ($range <= 1000) {
$step = 1; // Set a small step for a narrow range
} else if ($range <= 10000) {
$step = 100; // Set a medium step for a moderate range
} else {
$step = 500; // Set a larger step for a wide range
}
$range_array = array(
‘min’ => $range_min,
‘max’ => $range_max,
‘step’ => $step
);
return $range_array;
}
function workscout_get_reviews_criteria()
{
$criteria = array(
‘quality’ => array(
‘label’ => esc_html__(‘Quality of Work’, ‘workscout-freelancer’),
‘tooltip’ => esc_html__(‘Quality of customer service and attitude to work with you’, ‘workscout-freelancer’)
),
‘communication-skills’ => array(
‘label’ => esc_html__(‘Communication Skills:’, ‘workscout-freelancer’),
‘tooltip’ => esc_html__(‘Effective communication is crucial for a successful collaboration.’, ‘workscout-freelancer’)
),
‘professionalism’ => array(
‘label’ => esc_html__(‘Professionalism’, ‘workscout-freelancer’),
‘tooltip’ => esc_html__(‘Professionalism encompasses various aspects, including responsiveness, politeness, and the ability to handle challenges with a positive attitude.’, ‘workscout-freelancer’)
),
);
return apply_filters(‘workscout_reviews_criteria’, $criteria);
}
function calculate_task_expiry($id)
{
// Get duration from the product if set…
$duration = get_post_meta($id, ‘_duration’, true);
// …otherwise use the global option
if (!$duration) {
$duration = absint(get_option(‘workscout_freelancer_default_duration’));
}
if ($duration > 0) {
$new_date = date_i18n(‘Y-m-d’, strtotime(“+{$duration} days”, current_time(‘timestamp’)));
return $new_date;
}
return ”;
}
if (!function_exists(‘ws_task_location’)) :
function ws_task_location($map_link = true, $post = null)
{
if (!$post) {
global $post;
}
if ($post) {
if ($post->_remote_position) {
$remote_label = apply_filters(‘the_task_location_anywhere_text’, __(‘Remote’, ‘workscout-freelancer’));
$location = $remote_label;
}
$location = $post->_task_location;
if ($location) {
echo wp_kses_post($location);
} else {
echo wp_kses_post(apply_filters(‘the_job_location_anywhere_text’, __(‘Anywhere’, ‘workscout-freelancer’)));
}
}
}
endif;
workscout-freelancer-frontend.js
/* —————– Start Document —————– */
(function ($) {
“use strict”;
$(document).ready(function () {
// Bidding Slider Average Value
// Thousand Separator
function ThousandSeparator(nStr) {
nStr += “”;
var x = nStr.split(“.”);
var x1 = x[0];
var x2 = x.length > 1 ? “.” + x[1] : “”;
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, “$1” + “,” + “$2”);
}
return x1 + x2;
}
// Bidding Slider Average Value
var avgValue =
(parseInt($(“.bidding-slider”).attr(“data-slider-min”)) +
parseInt($(“.bidding-slider”).attr(“data-slider-max”))) /
2;
if ($(“.bidding-slider”).data(“slider-value”) === “auto”) {
$(“.bidding-slider”).attr({ “data-slider-value”: avgValue });
}
// Bidding Slider Init
$(“.bidding-slider”).bootstrapSlider();
$(“.bidding-slider”).on(“slide”, function (slideEvt) {
$(“.biddingVal”).text(ThousandSeparator(parseInt(slideEvt.value)));
});
$(“.bidding-slider-widget”).on(“slide”, function (slideEvt) {
$(“.bidding-slider”).bootstrapSlider(“setValue”, slideEvt.value);
});
$(“.bidding-slider-popup”).on(“slide”, function (slideEvt) {
$(“.bidding-slider”).bootstrapSlider(“setValue”, slideEvt.value);
});
$(“.biddingVal”).text(
ThousandSeparator(parseInt($(“.bidding-slider”).val()))
);
//$(“.range-slider-single”).slider();
/*————————————————–*/
/* Quantity Buttons
/*————————————————–*/
function qtySum() {
var arr = document.getElementsByName(“qtyInput”);
var tot = 0;
for (var i = 0; i < arr.length; i++) {
if (parseInt(arr[i].value)) tot += parseInt(arr[i].value);
}
}
qtySum();
$(“.qtyDec, .qtyInc”).on(“click”, function () {
var $button = $(this);
var oldValue = $button.parent().find(“input”).val();
if ($button.hasClass(“qtyInc”)) {
$button
.parent()
.find(“input”)
.val(parseFloat(oldValue) + 1);
} else {
if (oldValue > 1) {
$button
.parent()
.find(“input”)
.val(parseFloat(oldValue) – 1);
} else {
$button.parent().find(“input”).val(1);
}
}
qtySum();
$(“.bidding-time”).trigger(“change”);
$(“.qtyTotal”).addClass(“rotate-x”);
});
$(“.bidding-time-widget”).on(“change”, function () {
var value = $(this).val();
$(“.bidding-time-popup”).val(value);
});
$(“.bidding-time-popup”).on(“change”, function () {
var value = $(this).val();
$(“.bidding-time-widget”).val(value);
});
/*————————————————–*/
/* Bidding
/*————————————————–*/
$(“.bid-now-btn”).on(“click”, function (e) {
e.preventDefault();
$(“.trigger-bid-popup”).trigger(“click”);
});
$(“#form-bidding”).on(“submit”, function (e) {
var success;
var task_id = $(“#form-bidding”).data(“post_id”);
var budget = $(“.bidding-slider”).val();
var time = $(“input[name=’bid-time’]”).val();
var proposal = $(“textarea#bid-proposal”).val();
var ajax_data = {
action: “workscout_task_bid”,
nonce: workscout_core.nonce, // pass the nonce here
task_id: task_id,
budget: budget,
proposal: proposal,
time: time,
//’nonce’: nonce
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
//refresh bids
$(“.mfp-close”).trigger(“click”);
$(“.bidding-inner”).hide();
$(“.bidding-inner-success”).show();
Snackbar.show({
text: “Your bid has been placed!”,
});
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
})
.then(function (data, textStatus, response) {
if (success) {
alert(“then”);
}
// In case your working with a deferred.promise, use this method
// Again, you’ll have to manually separates success/error
});
e.preventDefault();
});
/*————————————————–*/
/* Bidding actions
/*————————————————–*/
$(document).on(“click”, “.bids-action-delete-bid”, function (e) {
e.preventDefault();
var bid_id = $(this).parent().data(“bid-id”);
var ajax_data = {
action: “workscout_remove_bid”,
nonce: workscout_core.nonce, // pass the nonce here
bid_id: bid_id,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: ws.ajax_url,
data: ajax_data,
})
.done(function (data) {
//refresh bids
console.log(data);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
});
// var referral = $(this).data(“booking_id”);
// $(“#send-message-from-widget textarea”)
// .data(“referral”, referral)
// .data(“recipient”, recipient);
});
$(document).on(“click”, “.bids-action-accept-offer”, function (e) {
e.preventDefault();
$(this).addClass(“loading”);
var bid_id = $(this).parent().data(“bid-id”);
var ajax_data = {
action: “workscout_get_bid_data”,
nonce: workscout_core.nonce, // pass the nonce here
bid_id: bid_id,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
//refresh bids
console.log(data);
$(“.bid-accept-popup h3”).html(data.title);
$(“.bid-accept-popup .bid-acceptance”).html(data.content);
$(“.bid-accept-popup .bid-proposal .bid-proposal-text”).html(
data.proposal
);
$(“.bid-accept-popup #task_id”).val(data.task_id);
$(“.bid-accept-popup #bid_id”).val(data.bid_id);
$(“.bids-popup-accept-offer”).trigger(“click”);
$(“.bids-action-accept-offer”).removeClass(“loading”);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
});
// var referral = $(this).data(“booking_id”);
// $(“#send-message-from-widget textarea”)
// .data(“referral”, referral)
// .data(“recipient”, recipient);
});
$(document).on(“submit”, “#accept-bid-form”, function (e) {
e.preventDefault();
var task_id = $(“.bid-accept-popup #task_id”).val();
var bid_id = $(“.bid-accept-popup #bid_id”).val();
var ajax_data = {
action: “workscout_accept_bid_on_task”,
nonce: workscout_core.nonce, // pass the nonce here
bid_id: bid_id,
task_id: task_id,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
success: function (data) {
if (data.type == “success”) {
window.setTimeout(closepopup, 3000);
//redirect to previous page
if (data.redirect) {
window.location.href = data.redirect;
} else {
history.back();
}
}
},
});
});
$(“.fieldset-competencies > .field”).sortable({
items: “.resume-manager-data-row”,
cursor: “move”,
axis: “y”,
scrollSensitivity: 40,
forcePlaceholderSize: !0,
helper: “clone”,
opacity: 0.65,
});
$(document).on(
“click”,
“.task-dashboard-action-contact-bidder”,
function (e) {
e.preventDefault();
var task = $(this).data(“task”);
var ajax_data = {
action: “workscout_get_bid_data_for_contact”,
nonce: workscout_core.nonce, // pass the nonce here
task_id: task,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
$(“.bidding-widget”).html(data.message);
$(“.contact-popup”).trigger(“click”);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
});
// $(“.popup-with-zoom-anim”).trigger(“click”);
}
);
$(document).on(“click”, “.task-dashboard-action-review”, function (e) {
e.preventDefault();
var task = $(this).data(“task”);
var ajax_data = {
action: “workscout_get_review_form”,
nonce: workscout_core.nonce, // pass the nonce here
task_id: task,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
$(“.rate-form”).html(data.message);
$(“.rate-popup”).trigger(“click”);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
});
});
$(document).on(“submit”, “#popup-commentform”, function (e) {
$(“#popup-commentform button”).addClass(“loading”).prop(“disabled”, true);
$.ajax({
type: “POST”,
dataType: “json”,
url: ws.ajaxurl,
data: {
action: “workscout_review_freelancer”,
data: $(this).serialize(),
//’nonce’: nonce
},
success: function (data) {
if (data.success == true) {
$(“#popup-commentform”).removeClass(“loading”).hide();
$(“#popup-commentform”).hide();
$(“.workscout-rate-popup .notification”).show().html(data.message);
window.setTimeout(closepopup, 3000);
} else {
$(“.workscout-rate-popup .notification”)
.removeClass(“success”)
.addClass(“error”)
.show()
.html(data.message);
$(“#popup-commentform button”)
.removeClass(“loading”)
.prop(“disabled”, false);
}
},
});
e.preventDefault();
});
$(“.delete-milestone”).on(“click”, function (e) {
e.preventDefault();
if (!confirm(workscout_core.i18n_confirm_delete)) {
return;
}
var $button = $(this);
var milestone_id = $button.data(“milestone-id”);
var project_id = $button.data(“project-id”);
$.ajax({
url: ws.ajaxurl,
type: “POST”,
data: {
action: “ws_delete_milestone”,
milestone_id: milestone_id,
project_id: project_id,
nonce: workscout_core.nonce,
},
success: function (response) {
if (response.success) {
// Remove milestone from DOM
$button.closest(“.milestone-item”).fadeOut(function () {
$(this).remove();
});
// Update remaining percentage display if needed
if (response.data.remaining_percentage !== undefined) {
$(“#remaining-percentage”).text(
response.data.remaining_percentage.toFixed(1)
);
}
// Show success message
Snackbar.show({
text: workscout_core.i18n_milestone_deleted,
});
} else {
// Show error message
Snackbar.show({
text: response.data.message || workscout_core.i18n_error,
});
}
},
});
});
// Edit milestone button click
$(“.edit-milestone”).on(“click”, function (e) {
e.preventDefault();
var $button = $(this);
var milestone_id = $button.data(“milestone-id”);
var project_id = $button.data(“project-id”);
// Reset form
//$(“#edit-milestone-form”)[0].reset();
// Load milestone data
$.ajax({
url: workscout_core.ajax_url,
type: “POST”,
data: {
action: “get_milestone_for_edit”,
milestone_id: milestone_id,
project_id: project_id,
nonce: workscout_core.nonce,
},
success: function (response) {
if (response.success) {
var milestone = response.data.milestone;
// Populate form fields
$(“#edit-project-id”).val(project_id);
$(“#edit-milestone-id”).val(milestone_id);
$(“#edit-milestone-title”).val(milestone.title);
$(“#edit-milestone-percentage”).val(milestone.percentage);
$(“#edit-milestone-description”).val(milestone.description);
$(“#edit-remaining-percentage”).attr(“max”, response.data.remaining_percentage);
// Update amount preview
updateAmountPreview(
milestone.percentage,
response.data.project_value
);
// Open popup
$.magnificPopup.open({
items: {
src: “#edit-milestone-popup”,
type: “inline”,
},
});
} else {
Snackbar.show({
text: response.data.message || workscout_core.i18n_error,
});
}
},
});
});
// Handle percentage input changes
$(“#edit-milestone-percentage,#milestone-percentage”).on(
“input”,
function () {
var percentage = parseFloat($(this).val()) || 0;
var projectValue = parseFloat(
$(“#milestone-form”).data(“project-budget”)
);
updateAmountPreview(percentage, projectValue);
}
);
if($(“#milestone-percentage”).length) {
$(“#milestone-percentage”)
.bootstrapSlider()
.on(“slide”, function (e) {
var percentage = parseFloat(e.value) || 0;
var projectValue = parseFloat(
$(“#milestone-form”).data(“project-budget”)
);
updateAmountPreview(percentage, projectValue);
});
}
// Update amount preview
function updateAmountPreview(percentage, projectValue) {
var amount = (projectValue * percentage) / 100;
$(“#amount-preview”).text(formatCurrency(amount));
$(“#edit-amount-preview”).text(formatCurrency(amount));
}
// Handle form submission
$(“#edit-milestone-form”).on(“submit”, function (e) {
e.preventDefault();
var $form = $(this);
var $submitButton = $form.find(‘button[type=”submit”]’);
$submitButton.prop(“disabled”, true);
$.ajax({
url: workscout_core.ajax_url,
type: “POST”,
data: {
action: “update_milestone”,
project_id: $(“#edit-project-id”).val(),
milestone_id: $(“#edit-milestone-id”).val(),
title: $(“#edit-milestone-title”).val(),
percentage: $(“#edit-milestone-percentage”).val(),
description: $(“#edit-milestone-description”).val(),
nonce: workscout_core.nonce,
},
success: function (response) {
if (response.success) {
// Close popup
$.magnificPopup.close();
// Update milestone display in the page
updateMilestoneDisplay(response.data.milestone);
// Update remaining percentage display
$(“#remaining-percentage”).text(
response.data.remaining_percentage.toFixed(1)
);
// Show success message
Snackbar.show({
text: workscout_core.i18n_milestone_updated,
});
// Reload page to refresh milestone display
location.reload();
} else {
Snackbar.show({
text: response.data.message || workscout_core.i18n_error,
});
}
},
complete: function () {
$submitButton.prop(“disabled”, false);
},
});
});
// Helper function to update milestone display
function updateMilestoneDisplay(milestone) {
var $milestoneItem = $(‘.milestone-item[data-id=”‘ + milestone.id + ‘”]’);
$milestoneItem.find(“.milestone-title”).text(milestone.title);
$milestoneItem.find(“.milestone-description”).html(milestone.description);
$milestoneItem
.find(“.milestone-percentage”)
.text(milestone.percentage + “%”);
$milestoneItem
.find(“.milestone-amount”)
.text(formatCurrency(milestone.amount));
}
// Helper function to format currency
function formatCurrency(amount) {
return amount.toLocaleString(undefined);
}
$(“.tasks-sort-by”).on(“change”, function () {
//refresh current page with value of select added to URL
//submit form
$(“#tasks-sort-by-form”).submit();
});
//message
$(document).on(“click”, “.bids-action-send-msg”, function (e) {
var recipient = $(this).data(“recipient”);
var referral = $(this).data(“bid_id”);
$(“#send-message-from-task textarea”).val(“”);
$(“#send-message-from-task .notification”).hide();
$(“#send-message-from-task textarea”)
.data(“referral”, referral)
.data(“recipient”, recipient);
$(“.popup-with-zoom-anim”).trigger(“click”);
});
$(“body”).on(“submit”, “#send-message-from-task”, function (e) {
$(“#send-message-from-task button”)
.addClass(“loading”)
.prop(“disabled”, true);
$.ajax({
type: “POST”,
dataType: “json”,
url: ws.ajaxurl,
data: {
action: “workscout_send_message”,
recipient: $(this).find(“textarea#contact-message”).data(“recipient”),
referral: $(this).find(“textarea#contact-message”).data(“referral”),
message: $(this).find(“textarea#contact-message”).val(),
//’nonce’: nonce
},
success: function (data) {
if (data.type == “success”) {
$(“#send-message-from-task button”).removeClass(“loading”);
$(“#send-message-from-task .notification”)
.show()
.html(data.message);
window.setTimeout(closepopup, 3000);
} else {
$(“#send-message-from-task .notification”)
.removeClass(“success”)
.addClass(“error”)
.show()
.html(data.message);
$(“#send-message-from-task button”)
.removeClass(“loading”)
.prop(“disabled”, false);
}
},
});
e.preventDefault();
});
function closepopup() {
var magnificPopup = $.magnificPopup.instance;
if (magnificPopup) {
magnificPopup.close();
$(“#send-message-from-task button”)
.removeClass(“loading”)
.prop(“disabled”, false);
}
}
//
// Edit bid on My Bids page
//
$(document).on(“click”, “.bids-action-edit-bid”, function (e) {
e.preventDefault();
var bid_id = $(this).parent().data(“bid-id”);
var ajax_data = {
action: “workscout_get_bid_data_for_edit”,
nonce: workscout_core.nonce, // pass the nonce here
bid_id: bid_id,
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
if (data.task_type == “hourly”) {
$(“.bidding-detail-hourly”).show();
$(“.bidding-detail-fixed”).hide();
} else {
$(“.bidding-detail-hourly”).hide();
$(“.bidding-detail-fixed”).show();
}
$(“.bidding-time”).val(data.time);
$(“.biddingVal”).text(ThousandSeparator(parseInt(data.budget)));
$(“.bidding-widget #bid-proposal”).val(data.proposal);
$(“.bidding-widget #bid_id”).val(data.bid_id);
// Bidding Slider Init
$(“.bidding-slider-popup”).attr(“data-slider-min”, data.range_min);
$(“.bidding-slider-popup”).attr(“data-slider-max”, data.range_max);
$(“.bidding-slider-popup”).attr(“data-slider-step”, data.slider_step);
// console.log(mySlider);
$(“.bidding-slider-popup”).bootstrapSlider();
$(“.bidding-slider-popup”).bootstrapSlider(“setValue”, data.budget);
$(“.bidding-slider-popup”).on(“slide”, function (slideEvt) {
$(“.biddingVal”).text(ThousandSeparator(parseInt(slideEvt.value)));
});
$(“.popup-with-zoom-anim”).trigger(“click”);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
});
});
$(“#form-bidding-update”).on(“submit”, function (e) {
var success;
var bid_id = $(“input[name=’bid_id’]”).val();
var budget = $(“.bidding-slider-popup”).val();
var time = $(“input[name=’bid-time’]”).val();
var proposal = $(“textarea#bid-proposal”).val();
var ajax_data = {
action: “workscout_update_bid”,
nonce: workscout_core.nonce, // pass the nonce here
budget: budget,
proposal: proposal,
time: time,
bid_id: bid_id,
//’nonce’: nonce
};
$.ajax({
type: “POST”,
dataType: “json”,
url: workscout_core.ajax_url,
data: ajax_data,
})
.done(function (data) {
//refresh bids
$(“.mfp-close”).trigger(“click”);
$(“.bidding-inner”).hide();
$(“.bidding-inner-success”).show();
Snackbar.show({
text: “Your bid has been updated!”,
});
$(“#my-bids-bid-id-” + bid_id + ” #bid-info-budget strong”).html(
ThousandSeparator(parseInt(budget))
);
$(“#my-bids-bid-id-” + bid_id + ” #bid-info-time strong”).html(time);
})
.fail(function (reason) {
// Handles errors only
console.debug(“reason” + reason);
})
.then(function (data, textStatus, response) {
if (success) {
alert(“then”);
}
// In case your working with a deferred.promise, use this method
// Again, you’ll have to manually separates success/error
});
e.preventDefault();
});
var $tabsNav = $(“.popup-tabs-nav”),
$tabsNavLis = $tabsNav.children(“li”);
$tabsNav.each(function () {
var $this = $(this);
$this
.next()
.children(“.popup-tab-content”)
.stop(true, true)
.hide()
.first()
.show();
$this.children(“li”).first().addClass(“active”).stop(true, true).show();
});
$tabsNavLis.on(“click”, function (e) {
var $this = $(this);
$this.siblings().removeClass(“active”).end().addClass(“active”);
$this
.parent()
.next()
.children(“.popup-tab-content”)
.stop(true, true)
.hide()
.siblings($this.find(“a”).attr(“href”))
.fadeIn();
e.preventDefault();
});
var hash = window.location.hash;
var anchor = $(‘.tabs-nav a[href=”‘ + hash + ‘”]’);
if (anchor.length === 0) {
$(“.popup-tabs-nav li:first”).addClass(“active”).show(); //Activate first tab
$(“.popup-tab-content:first”).show(); //Show first tab content
} else {
anchor.parent(“li”).click();
}
$(
“.workscout-bid-action-delete,.task-dashboard-action-delete,.bids-action-delete-bid”
).click(function () {
return window.confirm(ws.i18n_confirm_delete);
});
/*————————————————–*/
/* Keywords
/*————————————————–*/
$(“.keyword-input-container input”).autocomplete({
source: function (req, response) {
$.getJSON(
workscout_core.ajax_url +
“?callback=?&action=workscout_incremental_skills_suggest”,
req,
response
);
},
select: function (event, ui) {
// use ui.item.label as the input’s value to display the label
// use ui.item.value to display the value
$(“.keyword-input”).val(ui.item.label);
$(“.keyword-input-button”).trigger(“click”);
$(“.keyword-input”).val(“”);
//window.location.href = ui.item.link;
},
close: function (event, ui) {
$(“.keyword-input”).val(“”);
},
minLength: 3,
});
$(“.keywords-container”).each(function () {
var keywordLimit = $(this).data(“limit”);
//if keywordlimit is undefined set it to 5
if (typeof keywordLimit === “undefined”) {
keywordLimit = 5;
}
var keywordInput = $(this).find(“.keyword-input”);
var keywordsList = $(this).find(“.keywords-list”);
var hiddenInput = $(this).find(“.keyword-input-real”);
var keywordCounter = keywordsList.children(“span”).length;
// adding keyword
function addKeyword() {
var $newKeyword = $(
“<span class=’keyword’><span class=’keyword-remove’></span><span class=’keyword-text’>” +
keywordInput.val() +
“</span></span>”
);
keywordsList.append($newKeyword).trigger(“resizeContainer”);
keywordInput.val(“”);
// add $newkeyword to hidden input for form submit
var keywordValue = keywordsList
.find(“.keyword-text”)
.map(function () {
return $(this).text();
})
.get();
keywordCounter++;
hiddenInput.val(keywordValue);
}
// add via enter key
keywordInput.on(“keyup”, function (e) {
if (e.keyCode == 13 && keywordInput.val() !== “”) {
if (keywordCounter < keywordLimit) {
addKeyword();
} else {
Snackbar.show({
text: “You can only add ” + keywordLimit + ” skills”,
});
}
}
});
// add via button
$(“.keyword-input-button”).on(“click”, function (e) {
e.preventDefault();
if (keywordInput.val() !== “”) {
if (keywordCounter < keywordLimit) {
addKeyword();
} else {
Snackbar.show({
text: “You can only add ” + keywordLimit + ” keywords”,
});
}
}
});
// removing keyword
$(document).on(“click”, “.keyword-remove”, function () {
$(this).parent().addClass(“keyword-removed”);
function removeFromMarkup() {
$(“.keyword-removed”).remove();
keywordInput.val(“”);
// add $newkeyword to hidden input for form submit
var keywordValue = keywordsList
.find(“.keyword-text”)
.map(function () {
return $(this).text();
})
.get();
hiddenInput.val(keywordValue);
}
setTimeout(removeFromMarkup, 500);
keywordsList.css({ height: “auto” }).height();
keywordLimit–;
});
// animating container height
keywordsList.on(“resizeContainer”, function () {
var heightnow = $(this).height();
var heightfull = $(this)
.css({ “max-height”: “auto”, height: “auto” })
.height();
$(this).css({ height: heightnow }).animate({ height: heightfull }, 200);
});
$(window).on(“resize”, function () {
keywordsList.css({ height: “auto” }).height();
});
// Auto Height for keywords that are pre-added
$(window).on(“load”, function () {
var keywordCount = $(“.keywords-list”).children(“span”).length;
// Enables scrollbar if more than 3 items
if (keywordCount > 0) {
keywordsList.css({ height: “auto” }).height();
}
});
});
// if checkbox with id remote-job is checked, make input with id location not required
// check also on page load if this chekcbox is checked
if ($(“#remote_position”).is(“:checked”)) {
$(“#task_location”).prop(“required”, false);
} else {
$(“#task_location”).prop(“required”, true);
}
$(“#remote_position”).on(“change”, function () {
if ($(this).is(“:checked”)) {
$(“#task_location”).prop(“required”, false);
} else {
$(“#task_location”).prop(“required”, true);
}
});
/*————————————————–*/
/* Full Screen Tasks
/*————————————————–*/
/*————————————————–*/
/* Tippy JS
/*————————————————–*/
/* global tippy */
tippy(“[data-tippy-placement]”, {
delay: 100,
arrow: true,
arrowType: “sharp”,
size: “regular”,
duration: 200,
// ‘shift-toward’, ‘fade’, ‘scale’, ‘perspective’
animation: “shift-away”,
animateFill: true,
theme: “dark”,
// How far the tooltip is from its reference element in pixels
distance: 10,
});
tippy(“div.resumes”, {
target: “strong”,
});
/*—————————————————-*/
/* Indicator Bar
/*—————————————————-*/
$(“.indicator-bar”).each(function () {
var indicatorLenght = $(this).attr(“data-indicator-percentage”);
$(this)
.find(“span”)
.css({
width: indicatorLenght + “%”,
});
});
/*—————————————————-*/
/* Ratings Script
/*—————————————————-*/
/* Numerical Script
/*————————–*/
$(“.numerical-rating”).numericalRating();
$(“.star-rating”).starRating();
//submit
var hourly_min_field = $(“.task-submit-form-container-hourly_min”);
var hourly_max_field = $(“.task-submit-form-container-hourly_max”);
var budget_min_field = $(“.task-submit-form-container-budget_min”);
var budget_max_field = $(“.task-submit-form-container-budget_max”);
$(‘input[name=”task_type”]’).on(“change”, function () {
var this_val = $(this).val();
if (this_val == “fixed”) {
//using replaceWith switch the element
hourly_min_field.replaceWith(budget_min_field);
hourly_max_field.replaceWith(budget_max_field);
hourly_min_field.find(“input”).attr(“required”, false);
hourly_max_field.find(“input”).attr(“required”, false);
budget_min_field.find(“input”).attr(“required”, true);
budget_max_field.find(“input”).attr(“required”, true);
} else {
budget_min_field.replaceWith(hourly_min_field);
budget_max_field.replaceWith(hourly_max_field);
// Set the input fields as required
hourly_min_field.find(“input”).attr(“required”, true);
hourly_max_field.find(“input”).attr(“required”, true);
budget_min_field.find(“input”).attr(“required”, false);
budget_max_field.find(“input”).attr(“required”, false);
}
});
//check which radio button is seelcted by defaulot
// Project View
const projectValue = $(“#milestone-form”).data(“project-budget”);
const form = $(“#milestone-form”);
const percentageInput = form.find(‘input[name=”percentage”]’);
const amountPreview = $(“#amount-preview”);
const remainingPercentageSpan = $(“#remaining-percentage”);
// Update amount preview when percentage changes
percentageInput.on(“input”, function () {
const percentage = parseFloat($(this).val()) || 0;
const amount = (projectValue * percentage) / 100;
amountPreview.text(amount.toFixed(2));
});
$(“#milestone-form”).on(“submit”, function (e) {
e.preventDefault();
$.ajax({
url: ws.ajaxurl,
type: “POST”,
data: {
action: “save_milestone”,
project_id: $(‘input[name=”project_id”]’).val(),
nonce: $(“#milestone_nonce”).val(),
title: $(“#milestone-title”).val(),
percentage: $(“#milestone-percentage”).val(),
description: $(“#milestone-description”).val(),
due_date: $(“#milestone-due-date”).val(),
amount: $(“#milestone-amount”).val(),
},
success: function (response) {
if (response.success) {
location.reload();
} else {
alert(“Error saving milestone”);
}
},
});
});
// Handle milestone approval
$(“.approve-milestone”).on(“click”, function () {
const milestoneId = $(this).data(“id”);
var button = $(this);
$.ajax({
url: ws.ajaxurl,
type: “POST”,
data: {
action: “approve_milestone”,
milestone_id: milestoneId,
project_id: $(‘input[name=”project_id”]’).val(),
nonce: $(“#milestone_nonce”).val(),
},
success: function (response) {
console.log(response);
if (response.success) {
location.reload();
} else {
alert(“Error approving milestone”);
}
},
});
});
$(“.workscout-create-stripe-express-link-account”).on(“click”, function (e) {
e.preventDefault();
var $this = $(this);
$(this).addClass(“loading”);
$.ajax({
type: “POST”,
url: ws.ajaxurl,
data: {
action: “create_express_stripe_account”,
// security: workscout_core.security,
},
success: function (response) {
if (response.success) {
get_workscout_stripe_account_link();
} else {
$this.removeClass(“loading”);
$this.after(“<p class=’error’>” + (response.data || ‘An error occurred’) + “</p>”);
}
},
error: function(xhr, status, error) {
$this.removeClass(“loading”);
$this.after(“<p class=’error’>Request failed: ” + error + “</p>”);
},
});
});
function get_workscout_stripe_account_link() {
$.ajax({
type: “POST”,
dataType: “json”,
url: ws.ajaxurl,
data: {
action: “get_express_stripe_account_link”,
},
success: function (data) {
if (data.success) {
$(“.workscout-create-stripe-express-link-account”).hide();
$(“.real-conntect-w-stripe-btn”).attr(“href”, data.data).show();
} else {
$(“.workscout-create-stripe-express-link-account”).removeClass(
“loading”
);
$(“.workscout-create-stripe-express-link-account”).after(
“<p>” + data.data + “</p>”
);
}
},
});
}
// —————— End Document —————— //
});
})(this.jQuery);
/* —————– Start Document —————– */
(function ($) {
“use strict”;
function starsOutput(firstStar, secondStar, thirdStar, fourthStar, fifthStar) {
return(”+
‘<span class=”‘+firstStar+'”></span>’+
‘<span class=”‘+secondStar+'”></span>’+
‘<span class=”‘+thirdStar+'”></span>’+
‘<span class=”‘+fourthStar+'”></span>’+
‘<span class=”‘+fifthStar+'”></span>’);
}
$.fn.numericalRating = function(){
this.each(function() {
var dataRating = $(this).attr(‘data-rating’);
// Rules
if (dataRating >= 4.0) {
$(this).addClass(‘high’);
} else if (dataRating >= 3.0) {
$(this).addClass(‘mid’);
} else if (dataRating < 3.0) {
$(this).addClass(‘low’);
}
});
};
/* Star Rating
/*————————–*/
$.fn.starRating = function(){
this.each(function() {
var dataRating = $(this).attr(‘data-rating’);
if(dataRating > 0) {
// Rating Stars Output
var fiveStars = starsOutput(‘star’,’star’,’star’,’star’,’star’);
var fourHalfStars = starsOutput(‘star’,’star’,’star’,’star’,’star half’);
var fourStars = starsOutput(‘star’,’star’,’star’,’star’,’star empty’);
var threeHalfStars = starsOutput(‘star’,’star’,’star’,’star half’,’star empty’);
var threeStars = starsOutput(‘star’,’star’,’star’,’star empty’,’star empty’);
var twoHalfStars = starsOutput(‘star’,’star’,’star half’,’star empty’,’star empty’);
var twoStars = starsOutput(‘star’,’star’,’star empty’,’star empty’,’star empty’);
var oneHalfStar = starsOutput(‘star’,’star half’,’star empty’,’star empty’,’star empty’);
var oneStar = starsOutput(‘star’,’star empty’,’star empty’,’star empty’,’star empty’);
// Rules
if (dataRating >= 4.75) {
$(this).append(fiveStars);
} else if (dataRating >= 4.25) {
$(this).append(fourHalfStars);
} else if (dataRating >= 3.75) {
$(this).append(fourStars);
} else if (dataRating >= 3.25) {
$(this).append(threeHalfStars);
} else if (dataRating >= 2.75) {
$(this).append(threeStars);
} else if (dataRating >= 2.25) {
$(this).append(twoHalfStars);
} else if (dataRating >= 1.75) {
$(this).append(twoStars);
} else if (dataRating >= 1.25) {
$(this).append(oneHalfStar);
} else if (dataRating < 1.25) {
$(this).append(oneStar);
}
}
});
};
})(jQuery);
Freelancer.css
.project-discussion-content,
.project-view-content {
padding: 20px 35px;
}
/* Project Comments Styles */
.project-comment-form {
margin-top: 30px;
padding: 25px;
background: #f9f9f9;
border-radius: 4px;
}
.project-comment-form textarea {
min-height: 120px;
}
.milestone-comment {
background: #f0f7ff;
border-left: 4px solid #2a41e8;
}
.milestone-header {
margin-bottom: 10px;
}
.milestone-tag {
background: #2a41e8;
color: #fff;
padding: 3px 8px;
border-radius: 4px;
font-size: 12px;
margin-right: 10px;
}
.milestone-status {
font-size: 12px;
font-weight: 600;
}
.project-view-content ul { list-style: none; }
.milestone-status.pending {
color: #ffa700;
}
.milestone-status.completed {
color: #40b660;
}
.project-comment-list {
list-style: none;
padding: 0;
}
.project-comment-list .project_comment {
background-color: #f6f6f6;
padding: 20px;
border-radius: 6px;
margin: 0 0 10px 0;
}
li.project_comment.comment,
li.project_comment.comment p{
font-size: 14px;
}
.project-comment-content p { margin: 0; }
.project-comment-content {
border-top: 1px solid #e0e0e0;
padding-top: 10px;
margin-top: 10px;
}
.project-comment-attachments {
margin-top: 15px;
padding: 15px;
background: rgba(0, 0, 0, 0.03);
border-radius: 4px;
}
.project-comment-attachments h4 {
font-size: 14px;
margin-bottom: 10px;
}
.project-comment-attachments ul {
margin: 0;
padding: 0;
list-style: none;
}
.project-comment-attachments li {
margin-bottom: 5px;
}
.project-comment-attachments a {
color: #2a41e8;
text-decoration: none;
}
.project-comment-attachments a:hover {
text-decoration: underline;
}
.milestone-approvals {
margin-top: 15px;
}
.milestones-action,
.project-task-files,
.project-files,
.milestones-list {
padding: 20px 35px;
}
.milestones-action { border-top: 1px solid #e0e0e0 }
.approval-status {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
.approval-status span {
padding: 2px 10px;
border-radius: 4px;
background: #f0f0f0;
font-size: 13px;
}
.milestone-item h4 {font-size: 16px;}
.approval-status span.approved {
background: #e8f5e9;
color: #2e7d32;
}
.milestone-actions {
margin-top: 10px;
}
.percentage-input-wrapper {
position: relative;
display: inline-block;
}
.percentage-symbol {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
.amount-preview {
margin-top: 5px;
color: #666;
}
.project-info {
margin-bottom: 20px;
padding: 15px;
background: #f5f5f5;
border-radius: 4px;
}
.project-view-details {
padding: 0;
margin: 0;
padding: 20px;
border-radius: 5px;
margin-bottom: 23px;
margin-top: 5px;
}
.project-view-details .bid-proposal-text {
margin: 0;
}
.milestone-item .badge {
font-size: 12px;
background: #f2f2f2;
border-radius: 4px;
color: #808080;
padding: 0 5px;
display: inline-block;
line-height: 22px;
margin-left: 5px;
top: -2px;
position: relative
}
.milestone-meta {
border: 1px solid #e0e0e0;
border-radius: 4px;
padding: 5px 10px;
}
.approve-milestone.button {
padding: 0 13px;
height: 40px;
line-height: 40px;
}
.approve-milestone.button[disabled] {
background: #e0e0e0;
color: #808080;
cursor: default;
}
.project-view-description .single-page-section { margin-bottom: 10px; }
body .freelancer-overview.project-view {
padding: 20px 35px;
border-bottom: 1px solid #e0e0e0;
}
body .freelancer-overview.project-view .freelancer-name { margin-left: 18px; }
.freelancer-overview.project-view .freelancer-name h4,
.freelancer-overview.project-view .freelancer-name h4 a {
margin-bottom: 0;
}
.milestone-item {
border-bottom: 1px solid #e0e0e0;
margin-bottom: 20px;
padding-bottom: 20px;
}
.milestone-item:last-child {
border-bottom: none;
margin-bottom: 20;
padding-bottom: 0;
}
#edit-milestone-popup.small-dialog { padding: 0px;}
.mfp-content #edit-milestone-popup.small-dialog .mfp-close{ top: 9px;}
#milestone-form .slider.slider-horizontal {
min-width: 250px;
}
@property –progress-value {
syntax: ‘<integer>’;
inherits: true;
initial-value: 0;
}
:root {
–progress-bar-color: #cfd8dc;
–progress-value-color: #2196f3;
–progress-empty-color-h: 4.1;
–progress-empty-color-s: 89.6;
–progress-empty-color-l: 58.4;
–progress-filled-color-h: 122.4;
–progress-filled-color-s: 39.4;
–progress-filled-color-l: 49.2;
}
progress[value] {
display: block;
position: relative;
appearance: none;
width: 80%;
height: 6px;
border: 0;
–border-radius: 10px;
border-radius: var(–border-radius);
counter-reset: progress var(–progress-value);
–progress-value-string: counter(progress) ‘%’;
–progress-max-decimal: calc(var(–value, 0) / var(–max, 0));
–progress-value-decimal: calc(var(–progress-value, 0) / var(–max, 0));
@supports selector(::-moz-progress-bar) {
–progress-value-decimal: calc(var(–value, 0) / var(–max, 0));
}
–progress-value-percent: calc(var(–progress-value-decimal) * 100%);
–progress-value-color: hsl(calc((var(–progress-empty-color-h) + (var(–progress-filled-color-h) – var(–progress-empty-color-h)) * var(–progress-value-decimal)) * 1deg) calc((var(–progress-empty-color-s) + (var(–progress-filled-color-s) – var(–progress-empty-color-s)) * var(–progress-value-decimal)) * 1%) calc((var(–progress-empty-color-l) + (var(–progress-filled-color-l) – var(–progress-empty-color-l)) * var(–progress-value-decimal)) * 1%));
animation: calc(3s * var(–progress-max-decimal)) linear 0.5s 1 normal both progress;
}
progress[value]::-webkit-progress-bar {
background-color: var(–progress-bar-color);
border-radius: var(–border-radius);
overflow: hidden;
}
progress[value]::-webkit-progress-value {
width: var(–progress-value-percent) !important;
background-color: var(–progress-value-color);
border-radius: var(–border-radius);
}
progress[value]::-moz-progress-bar {
width: var(–progress-value-percent) !important;
background-color: var(–progress-value-color);
border-radius: var(–border-radius);
}
@keyframes progress {
from {
–progress-value: 0;
}
to {
–progress-value: var(–value);
}
}
Class-workscout-freelancer-admi.php
<?php
/**
* File containing the class Workscout_Freelancer_Admin.
*
* @package wp-job-manager-resumes
*/
if ( ! defined( ‘ABSPATH’ ) ) {
exit;
}
/**
* Workscout_Freelancer_Admin class.
*/
class Workscout_Freelancer_Admin {
/**
* __construct function.
*
* @access public
* @return void
*/
public function __construct()
{
include_once ‘class-workscout-freelancer-settings.php’;
add_filter(‘job_manager_admin_screen_ids’, [$this, ‘add_screen_ids’]);
add_action(‘admin_menu’, [$this, ‘admin_menu’], 12);
add_action(‘admin_enqueue_scripts’, [$this, ‘admin_enqueue_scripts’], 20);
$this->settings_page = new Workscout_Freelancer_Settings();
}
/**
* Add screen ids
*
* @param array $screen_ids
* @return array
*/
public function add_screen_ids($screen_ids)
{
$screen_ids[] = ‘edit-task’;
$screen_ids[] = ‘task’;
$screen_ids[] = ‘task_page_workscout-freelancer-settings’;
return $screen_ids;
}
/**
* admin_enqueue_scripts function.
*
* @access public
* @return void
*/
public function admin_enqueue_scripts()
{
global $wp_scripts;
// $jquery_version = isset($wp_scripts->registered[‘jquery-ui-core’]->ver) ? $wp_scripts->registered[‘jquery-ui-core’]->ver : ‘1.9.2’;
// $jquery_version = preg_replace(‘/-wp/’, ”, $jquery_version);
// wp_enqueue_style(‘jquery-ui-style’, ‘//ajax.googleapis.com/ajax/libs/jqueryui/’ . $jquery_version . ‘/themes/smoothness/jquery-ui.css’);
// wp_enqueue_style(‘resume_manager_admin_css’, RESUME_MANAGER_PLUGIN_URL . ‘/assets/dist/css/admin.css’, [‘dashicons’], RESUME_MANAGER_VERSION);
// wp_enqueue_script(‘resume_manager_admin_js’, RESUME_MANAGER_PLUGIN_URL . ‘/assets/dist/js/admin.js’, [‘jquery’, ‘jquery-tiptip’, ‘jquery-ui-datepicker’, ‘jquery-ui-sortable’], RESUME_MANAGER_VERSION, true);
}
/**
* admin_menu function.
*
* @access public
* @return void
*/
public function admin_menu()
{
add_submenu_page(‘edit.php?post_type=task’, __(‘Task Settings’, ‘workscout-freelancer’), __(‘Task Settings’, ‘workscout-freelancer’), ‘manage_options’, ‘workscout-freelancer-settings’, [$this->settings_page, ‘output’]);
}
}
new Workscout_Freelancer_Admin();
class-workscout-freelancer-settings.php
<?php
/**
* File containing the class WP_Resume_Manager_Settings.
*
* @package wp-job-manager-resumes
*/
if (!defined(‘ABSPATH’)) {
exit;
}
/**
* WP_Resume_Manager_Settings class.
*/
class Workscout_Freelancer_Settings extends WP_Job_Manager_Settings
{
/**
* __construct function.
*
* @access public
* @return void
*/
public function __construct()
{
$this->settings_group = ‘workscout-freelancer’;
add_action(‘admin_init’, [$this, ‘register_settings’]);
add_action(‘admin_action_update’, [$this, ‘pre_process_settings_save’]);
}
/**
* Init_settings function.
*
* @access protected
* @return void
*/
protected function init_settings()
{
// Prepare roles option.
$roles = get_editable_roles();
$account_roles = [];
foreach ($roles as $key => $role) {
if (‘administrator’ === $key) {
continue;
}
$account_roles[$key] = $role[‘name’];
}
$empty_trash_days = defined(‘EMPTY_TRASH_DAYS ‘) ? EMPTY_TRASH_DAYS : 30;
if (empty($empty_trash_days) || $empty_trash_days < 0) {
$trash_description = __(‘They will then need to be manually removed from the trash’, ‘workscout-freelancer’);
} else {
// translators: Placeholder %d is the number of days before items are removed from trash.
$trash_description = sprintf(__(‘They will then be permanently deleted after %d days.’, ‘workscout-freelancer’), $empty_trash_days);
}
$this->settings = apply_filters(
‘workscout_freelancer_settings’,
[
‘tasks’ => [
__(‘Task Listings’, ‘workscout-freelancer’),
[
// [
// ‘name’ => ‘task_per_page’,
// ‘std’ => ’10’,
// ‘placeholder’ => ”,
// ‘label’ => __(‘Task Per Page’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Task Per Page’, ‘workscout-freelancer’),
// ‘desc’ => __(‘How many task should be shown per page by default?’, ‘workscout-freelancer’),
// ‘attributes’ => [],
// ],
// [
// ‘name’ => ‘task_ajax_browsing’,
// ‘std’ => ’10’,
// ‘placeholder’ => ”,
// ‘label’ => __(‘Use ajax browsing’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Use ajax browsing’, ‘workscout-freelancer’),
// ‘desc’ => __(‘If enabled search results will be automatically updated after every change’, ‘workscout-freelancer’),
// ‘attributes’ => [],
// ‘type’ => ‘checkbox’,
// ],
// [
// ‘name’ => ‘task_list_layout’,
// ‘std’ => ‘list-1’,
// ‘label’ => __(‘Task list layout’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Task list layout’, ‘workscout-freelancer’),
// ‘desc’ => __(‘Set layout for list of tasks’, ‘workscout-freelancer’),
// ‘type’ => ‘radio’,
// ‘options’ => [
// ‘list-1’ => __(‘List layout 1’, ‘workscout-freelancer’),
// ‘list-2’ => __(‘List layout 2’, ‘workscout-freelancer’),
// ‘grid’ => __(‘Grid’, ‘workscout-freelancer’),
// ‘full’ => __(‘Full page grid’, ‘workscout-freelancer’),
// ],
// ‘attributes’ => [],
// ],
// [
// ‘name’ => ‘task_list_layout_sidebar’,
// ‘std’ => ‘left’,
// ‘label’ => __(‘Sidebar side’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Does not apply to full page’, ‘workscout-freelancer’),
// ‘desc’ => __(‘Set sidebar side for list of tasks’, ‘workscout-freelancer’),
// ‘type’ => ‘radio’,
// ‘options’ => [
// ‘left’ => __(‘Left sidebar’, ‘workscout-freelancer’),
// ‘right’ => __(‘Right sidebar’, ‘workscout-freelancer’),
// ],
// ‘attributes’ => [],
// ],
[
‘name’ => ‘task_paid_listings_flow’,
‘std’ => ‘before’,
‘label’ => __(‘Paid listings flow’, ‘workscout-freelancer’),
‘cb_label’ => __(‘Paid listings flow’, ‘workscout-freelancer’),
‘desc’ => __(‘Set when the package option will appear’, ‘workscout-freelancer’),
‘type’ => ‘radio’,
‘options’ => [
‘before’ => __(‘Before submit form’, ‘workscout-freelancer’),
‘after’ => __(‘After submit form’, ‘workscout-freelancer’),
],
‘attributes’ => [],
],
// option to hide list of bidders
[
‘name’ => ‘task_hide_bidders’,
‘std’ => ‘0’,
‘label’ => __(‘Hide list of bidders’, ‘workscout-freelancer’),
‘cb_label’ => __(‘Hide list of bidders’, ‘workscout-freelancer’),
‘desc’ => __(‘Hide list of bidders on task page’, ‘workscout-freelancer’),
‘type’ => ‘checkbox’,
‘attributes’ => [],
],
],
],
// ‘project_options’ => [
// __(‘Project Options’,’workscout-freelancer’),
// [
// // add option for commission for project payments
// [
// ‘name’ => ‘workscout_freelancer_project_commission’,
// ‘std’ => ‘0’,
// ‘label’ => __(‘Project Commission’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Enable Project Commission’, ‘workscout-freelancer’),
// ‘desc’ => __(‘Enable project commission for project payments’, ‘workscout-freelancer’),
// ‘type’ => ‘checkbox’,
// ‘attributes’ => [],
// ],
// [
// ‘name’ => ‘workscout_commission_rate’,
// ‘std’ => ’10’,
// ‘label’ => __(‘Project Commission Rate’, ‘workscout-freelancer’),
// ‘cb_label’ => __(‘Project Commission Rate’, ‘workscout-freelancer’),
// ‘desc’ => __(‘Set the project commission rate in percentage’, ‘workscout-freelancer’),
// ‘type’ => ‘text’,
// ‘attributes’ => [],
// ],
// // [
// // ‘name’ => ‘workscout_freelancer_project_commission_type’,
// // ‘std’ => ‘fixed’,
// // ‘label’ => __(‘Project Commission Type’, ‘workscout-freelancer’),
// // ‘cb_label’ => __(‘Project Commission Type’, ‘workscout-freelancer’),
// // ‘desc’ => __(‘Set the project commission type’, ‘workscout-freelancer’),
// // ‘type’ => ‘radio’,
// // ‘options’ => [
// // ‘fixed’ => __(‘Fixed’, ‘workscout-freelancer’),
// // ‘percentage’ => __(‘Percentage’, ‘workscout-freelancer’),
// // ],
// // ‘attributes’ => [],
// // ],
// ]
// ],
‘task_submission’ => [
__(‘Task Submission’, ‘workscout-freelancer’),
[
[
‘name’ => ‘workscout_freelancer_task_submission_requires_approval’,
‘std’ => ‘1’,
‘label’ => __(‘Approval Required’, ‘workscout-freelancer’),
‘cb_label’ => __(‘New submissions require admin approval’, ‘workscout-freelancer’),
‘desc’ => __(‘If enabled, new submissions will be inactive, pending admin approval.’, ‘workscout-freelancer’),
‘type’ => ‘checkbox’,
‘attributes’ => [],
],
[
‘name’ => ‘workscout_freelancer_user_can_edit_pending_submissions’,
‘std’ => ‘0’,
‘label’ => __(‘Allow Pending Edits’, ‘workscout-freelancer’),
‘cb_label’ => __(‘Allow editing of pending tasks’, ‘workscout-freelancer’),
‘desc’ => __(‘Users can continue to edit pending tasks until they are approved by an admin.’, ‘workscout-freelancer’),
‘type’ => ‘checkbox’,
‘attributes’ => [],
],
[
‘name’ => ‘workscout_freelancer_user_edit_published_submissions’,
‘std’ => ‘yes’,
‘label’ => __(‘Allow Published Edits’, ‘workscout-freelancer’),
‘cb_label’ => __(‘Allow editing of published tasks’, ‘workscout-freelancer’),
‘desc’ => __(‘Choose whether published tasks can be edited and if edits require admin approval. When moderation is required, the original resume will be unpublished while edits await admin approval.’, ‘workscout-freelancer’),
‘type’ => ‘radio’,
‘options’ => [
‘no’ => __(‘Users cannot edit’, ‘workscout-freelancer’),
‘yes’ => __(‘Users can edit without admin approval’, ‘workscout-freelancer’),
‘yes_moderated’ => __(‘Users can edit, but edits require admin approval’, ‘workscout-freelancer’),
],
‘attributes’ => [],
],
],
],
‘task_pages’ => [
__(‘Pages’, ‘workscout-freelancer’),
[
[
‘name’ => ‘workscout_freelancer_submit_task_form_page_id’,
‘std’ => ”,
‘label’ => __(‘Submit Task Page’, ‘workscout-freelancer’),
‘desc’ => __(‘Select the page where you have placed the [workscout_submit_task] shortcode. This lets the plugin know where the form is located.’, ‘workscout-freelancer’),
‘type’ => ‘page’,
],
[
‘name’ => ‘workscout_freelancer_task_dashboard_page_id’,
‘std’ => ”,
‘label’ => __(‘Manage Task Page’, ‘workscout-freelancer’),
‘desc’ => __(‘Select the page where you have placed the [workscout_task_dashboard] shortcode. This lets the plugin know where the dashboard is located.’, ‘workscout-freelancer’),
‘type’ => ‘page’,
],
[
‘name’ => ‘workscout_freelancer_manage_my_bids_page_id’,
‘std’ => ”,
‘label’ => __(‘Manage My Bids Page’, ‘workscout-freelancer’),
‘desc’ => __(‘Select the page where you have placed the [workscout_my_bids] shortcode. This lets the plugin know where the dashboard is located.’, ‘workscout-freelancer’),
‘type’ => ‘page’,
],
[
‘name’ => ‘workscout_freelancer_manage_my_project_page_id’,
‘std’ => ”,
‘label’ => __(‘Freelancer Projects Page’, ‘workscout-freelancer’),
‘desc’ => __(‘Select the page where you have placed the [workscout_freelancer_project_view] shortcode. This lets the plugin know where the project list is located.’, ‘workscout-freelancer’),
‘type’ => ‘page’,
],
],
],
’emails’ => [
__(‘Email Notifications’, ‘workscout-freelancer’),
[
// Freelancer New Project Notification
[
‘name’ => ‘workscout_freelancer_new_project_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_freelancer_new_project_notification_enable’,
‘cb_label’ => __(‘Enable freelancer notifications about new project ‘, ‘workscout-freelancer’),
‘desc’ => __(‘Notifies freelancer when a new project is created for him by employer.
Available shortcodes:
{project_title}, {project_url}, {project_budget}, {project_description} {employer_name}, {freelancer_name}’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_freelancer_new_project_subject’,
‘std’ => ‘The project {project_title} has been created for you’,
‘label’ => __(‘New Project Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for new project notifications to freelancers.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_freelancer_new_project_content’,
‘std’ => “Hi {user_name},\n\nEmployer has created a new project for you:\n\nProject: {project_title}\nBudget: {project_budget}\nDescription: {project_description}\n\nView project: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘New Project Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for new project notifications to freelancers.’, ‘workscout-freelancer’),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
// Employer New Milestone Notification
[
‘name’ => ‘workscout_employer_new_milestone_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_employer_new_milestone_notification_enable’,
‘cb_label’ => __(‘Enable employer notifications about new milestone ‘, ‘workscout-freelancer’),
‘desc’ => __(‘Notifies employer when a new milestone is created. Available shortcodes:
{project_title}, {project_url}, {project_budget}, {project_description} {employer_name}, {freelancer_name}, {milestone_title},{milestone_amount}’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_employer_new_milestone_subject’,
‘std’ => ‘New Milestone Created: {project_title}’,
‘label’ => __(‘New Milestone Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for new milestone notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_employer_new_milestone_content’,
‘std’ => “Hi {user_name},\n\nA new milestone has been created for your project:\n\nProject: {project_title}\nMilestone: {milestone_title}\nAmount: {milestone_amount}\n\nView milestone: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘New Milestone Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for new milestone notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
// Employer Milestone Edited Notification
[
‘name’ => ‘workscout_employer_milestone_edited_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_employer_milestone_edited_notification_enable’,
‘cb_label’ => __(‘Enable employer milestone edited notifications’, ‘workscout-freelancer’),
‘desc’ => __(
‘Notifies employer when a milestone is editedAvailable shortcodes:
{project_title}, {project_url}, {project_budget}, {project_description} {employer_name}, {freelancer_name}, {milestone_title},{milestone_amount}’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_employer_milestone_edited_notification_subject’,
‘std’ => ‘Milestone Updated: {project_title}’,
‘label’ => __(‘Milestone Edited Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for milestone edited notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_employer_milestone_edited_notification_content’,
‘std’ => “Hi {user_name},\n\nA milestone has been updated:\n\nProject: {project_title}\nMilestone: {milestone_title}\nNew Amount: {milestone_amount}\n\nView changes: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘Milestone Edited Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for milestone edited notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
// Employer Milestone Approval Notification
[
‘name’ => ‘workscout_employer_milestone_approval_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_employer_milestone_approval_notification_enable’,
‘cb_label’ => __(‘Enable employer notifications about milestone for review ‘, ‘workscout-freelancer’),
‘desc’ => __(‘Notifies employer when a milestone needs approval’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_employer_milestone_approval_subject’,
‘std’ => ‘Milestone Ready for Review: {project_title}’,
‘label’ => __(‘Milestone Approval Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for milestone approval notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_employer_milestone_approval_content’,
‘std’ => “Hi {user_name},\n\nA milestone is ready for your review:\n\nProject: {project_title}\nMilestone: {milestone_title}\nAmount: {milestone_amount}\n\nPlease review and approve: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘Milestone Approval Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for milestone approval notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
// Employer Milestone Completion Notification
[
‘name’ => ‘workscout_freelancer_milestone_completion_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_freelancer_milestone_completion_notification_enable’,
‘cb_label’ => __(‘Enable freelancer notifications about milestone completion’, ‘workscout-freelancer’),
‘desc’ => __(‘Notifies freelancer when a milestone is completed and approved by employer’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_freelancer_milestone_completion_notification_subject’,
‘std’ => ‘Milestone Completed: {project_title}’,
‘label’ => __(‘Milestone Completion Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for milestone completion notifications to employers.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_freelancer_milestone_completion_notification_content’,
‘std’ => “Hi {user_name},\n\nA milestone has been completed:\n\nProject: {project_title}\nMilestone: {milestone_title}\nAmount: {milestone_amount}\n\nView details: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘Milestone Completion Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for milestone completion notifications to employers.’,
‘workscout-freelancer’
),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
// Existing New Order Email
[
‘name’ => ‘workscout_freelancer_new_order_notification’,
‘type’ => ‘multi_enable_expand’,
‘class’ => ’email-setting-row no-separator’,
‘enable_field’ => [
‘name’ => ‘workscout_freelancer_new_order_notification_enable’,
‘cb_label’ => __(‘Enable new milestone payment email notifications’, ‘workscout-freelancer’),
‘desc’ => __(‘Notifies employer about new order generated when milestone is mark as complete’, ‘workscout-freelancer’),
‘force_value’ => null,
],
‘label’ => false,
‘settings’ => [
[
‘name’ => ‘workscout_freelancer_new_order_subject’,
‘std’ => ‘New Order Created #{milestone_id} for {project_title}’,
‘label’ => __(‘New Milestone Payment Email Subject’, ‘workscout-freelancer’),
‘desc’ => __(‘The email subject for Milestone Paymen notifications.’, ‘workscout-freelancer’),
‘type’ => ‘text’,
],
[
‘name’ => ‘workscout_freelancer_new_order_content’,
‘std’ => “Hi {user_name},\n\nA new order #{order_id} has been created for your project {project_title}.\nAmount: {order_amount}\nView project: {project_url}\n\nBest regards,\n{site_name}”,
‘label’ => __(‘New Milestone Payment Email Content’, ‘workscout-freelancer’),
‘desc’ => __(‘The email content for new order notifications.’, ‘workscout-freelancer’),
‘type’ => ‘textarea’,
]
],
‘track’ => ‘bool’,
],
],
],
]
);
}
/**
* Outputs the capabilities or roles input field.
*
* @param array $option Option arguments for settings input.
* @param string[] $attributes Attributes on the HTML element. Strings must already be escaped.
* @param mixed $value Current value.
* @param string $ignored_placeholder We set the placeholder in the method. This is ignored.
*/
protected function input_capabilities($option, $attributes, $value, $ignored_placeholder)
{
$value = self::capabilities_string_to_array($value);
$option[‘options’] = self::get_capabilities_and_roles($value);
$option[‘placeholder’] = esc_html__(‘Everyone (Public)’, ‘workscout-freelancer’);
?>
<select id=”setting-<?php echo esc_attr($option[‘name’]); ?>” class=”regular-text settings-role-select” name=”<?php echo esc_attr($option[‘name’]); ?>[]” multiple=”multiple” data-placeholder=”<?php echo esc_attr($option[‘placeholder’]); ?>” <?php
echo implode(‘ ‘, $attributes); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>>
<?php
foreach ($option[‘options’] as $key => $name) {
echo ‘<option value=”‘ . esc_attr($key) . ‘” ‘ . selected(in_array($key, $value, true) ? $key : null, $key, false) . ‘>’ . esc_html($name) . ‘</option>’;
}
?>
</select>
<?php
if (!empty($option[‘desc’])) {
echo ‘ <p class=”description”>’ . wp_kses_post($option[‘desc’]) . ‘</p>’;
}
}
/**
* Role settings should be saved as a comma-separated list.
*/
public function pre_process_settings_save()
{
$screen = get_current_screen();
if (!$screen || ‘options’ !== $screen->id) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing — Settings save will handle the nonce check.
if (!isset($_POST[‘option_page’]) || ‘workscout-freelancer’ !== $_POST[‘option_page’]) {
return;
}
$capabilities_fields = [
‘resume_manager_view_name_capability’,
‘resume_manager_browse_resume_capability’,
‘resume_manager_view_resume_capability’,
‘resume_manager_contact_resume_capability’,
];
foreach ($capabilities_fields as $capabilities_field) {
// phpcs:disable WordPress.Security.NonceVerification.Missing — Settings save will handle the nonce check.
if (isset($_POST[$capabilities_field])) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized — Sanitized by `WP_Resume_Manager_Settings::capabilities_array_to_string()`
$input_capabilities_field_value = wp_unslash($_POST[$capabilities_field]);
if (is_array($input_capabilities_field_value)) {
$_POST[$capabilities_field] = self::capabilities_array_to_string($input_capabilities_field_value);
}
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
}
/**
* Convert list of capabilities and roles into array of values.
*
* @param string $value Comma separated list of capabilities and roles.
* @return array
*/
private static function capabilities_string_to_array($value)
{
return array_filter(
array_map(
function ($value) {
return trim(sanitize_text_field($value));
},
explode(‘,’, $value)
)
);
}
/**
* Convert array of capabilities and roles into a comma separated list.
*
* @param array $value Array of capabilities and roles.
* @return string
*/
private static function capabilities_array_to_string($value)
{
if (!is_array($value)) {
return ”;
}
$caps = array_filter(array_map(‘sanitize_text_field’, $value));
return implode(‘,’, $caps);
}
/**
* Get the list of roles and capabilities to use in select dropdown.
*
* @param array $caps Selected capabilities to ensure they show up in the list.
* @return array
*/
private static function get_capabilities_and_roles($caps = [])
{
$capabilities_and_roles = [];
$roles = get_editable_roles();
foreach ($roles as $key => $role) {
$capabilities_and_roles[$key] = $role[‘name’];
}
// Go through custom user selected capabilities and add them to the list.
foreach ($caps as $value) {
if (isset($capabilities_and_roles[$value])) {
continue;
}
$capabilities_and_roles[$value] = $value;
}
return $capabilities_and_roles;
}
}
class-workscout-freelancer-form-edit-task.php
<?php
/**
* File containing the WP_Resume_Manager_Form_Edit_Resume.
*
* @package wp-job-manager-tasks
*/
if (!defined(‘ABSPATH’)) {
exit;
}
require_once ‘class-workscout-freelancer-form-submit-task.php’;
/**
* WP_Resume_Manager_Form_Edit_Resume class.
*/
class WorkScout_Freelancer_Form_Edit_Task extends WorkScout_Freelancer_Form_Submit_Task
{
/**
* Form name slug.
*
* @var string
*/
public $form_name = ‘edit-task’;
/**
* Messaged shown on save.
*
* @var bool|string
*/
private $save_message = false;
/**
* Message shown on error.
*
* @var bool|string
*/
private $save_error = false;
/**
* The single instance of the class.
*
* @var WorkScout_Freelancer_Form_Edit_Task
*/
protected static $instance = null;
/**
* Main Instance
*/
public static function instance()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
public function __construct()
{
add_action(‘wp’, [$this, ‘submit_handler’]);
add_action(‘submit_task_form_start’, [$this, ‘output_submit_form_nonce_field’]);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
$this->task_id = !empty($_REQUEST[‘task_id’]) ? absint($_REQUEST[‘task_id’]) : 0;
if (!workscout_freelancer_user_can_edit_task($this->task_id)) {
$this->task_id = 0;
}
if (!empty($this->task_id)) {
$published_statuses = [‘publish’, ‘hidden’];
$post_status = get_post_status($this->task_id);
if (
(in_array($post_status, $published_statuses, true) && !workscout_freelancer_user_can_edit_published_submissions())
|| (!in_array($post_status, $published_statuses, true) && !workscout_freelancer_user_can_edit_pending_submissions())
) {
$this->task_id = 0;
}
}
}
/**
* Output the edit task form.
*
* @param array $atts Attributes passed (ignored).
*/
public function output($atts = [])
{
if (!empty($this->save_message)) {
echo ‘<div class=”job-manager-message”>’ . wp_kses_post($this->save_message) . ‘</div>’;
return;
}
if (!empty($this->save_error)) {
echo ‘<div class=”job-manager-error”>’ . wp_kses_post($this->save_error) . ‘</div>’;
}
$this->submit();
}
/**
* Submit step.
*/
public function submit()
{
$task = get_post($this->task_id);
if (empty($this->task_id)) {
echo wp_kses_post(wpautop(__(‘Invalid task’, ‘workscout-freelancer’)));
return;
}
$this->init_fields();
foreach ($this->fields as $group_key => $group_fields) {
foreach ($group_fields as $key => $field) {
if (!isset($this->fields[$group_key][$key][‘value’])) {
if (‘task_title’ === $key) {
$this->fields[$group_key][$key][‘value’] = $task->post_title;
} elseif (‘task_content’ === $key) {
$this->fields[$group_key][$key][‘value’] = $task->post_content;
} elseif (!empty($field[‘taxonomy’])) {
$this->fields[$group_key][$key][‘value’] = wp_get_object_terms($task->ID, $field[‘taxonomy’], [‘fields’ => ‘ids’]);
} elseif (‘task_skills’ === $key) {
$this->fields[$group_key][$key][‘value’] = implode(‘, ‘, wp_get_object_terms($task->ID, ‘task_skill’, [‘fields’ => ‘names’]));
} else {
$this->fields[$group_key][$key][‘value’] = get_post_meta($task->ID, ‘_’ . $key, true);
}
}
}
}
$this->fields = apply_filters(‘submit_task_form_fields_get_task_data’, $this->fields, $task);
$save_button_text = __(‘Save changes’, ‘workscout-freelancer’);
$published_statuses = [‘publish’, ‘hidden’];
if (
in_array(get_post_status($this->task_id), $published_statuses, true)
&& wpjm_published_submission_edits_require_moderation()
) {
$save_button_text = __(‘Submit changes for approval’, ‘workscout-freelancer’);
}
/**
* Change button text for submitting changes to a task.
*
* @since 1.18.0
*
* @param string $save_button_text Button text to filter.
* @param int $task_id Resume post ID.
*/
$save_button_text = apply_filters(‘task_manager_update_task_form_submit_button_text’, $save_button_text, $this->task_id);
get_job_manager_template(
‘task-submit.php’,
[
‘class’ => $this,
‘form’ => $this->form_name,
‘job_id’ => ”,
‘task_id’ => $this->get_task_id(),
‘action’ => $this->get_action(),
‘company_fields’ => $this->get_fields(‘company_fields’),
‘task_fields’ => $this->get_fields(‘task_fields’),
‘step’ => $this->get_step(),
‘submit_button_text’ => $save_button_text,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
}
/**
* Submit Step is posted.
*/
public function submit_handler()
{
// phpcs:ignore WordPress.Security.NonceVerification.Missing — Check happens later when possible.
if (empty($_POST[‘submit_task’])) {
return;
}
$this->check_submit_form_nonce_field();
try {
// Init fields.
$this->init_fields();
// Get posted values.
$values = $this->get_posted_fields();
// Validate required.
$validation_result = $this->validate_fields($values);
if (is_wp_error($validation_result)) {
throw new Exception($validation_result->get_error_message());
}
$original_post_status = get_post_status($this->task_id);
$save_post_status = $original_post_status;
if (wpjm_published_submission_edits_require_moderation()) {
$save_post_status = ‘pending’;
}
// Update the task.
$this->save_task($values[‘task_fields’][‘task_title’], $values[‘task_fields’][‘task_content’], $save_post_status, $values);
$this->update_task_data($values);
// Successful.
$save_message = __(‘Your changes have been saved.’, ‘workscout-freelancer’);
$post_status = get_post_status($this->task_id);
update_post_meta($this->task_id, ‘_task_edited’, time());
update_post_meta($this->task_id, ‘_task_edited_original_status’, $original_post_status);
$published_statuses = [‘publish’, ‘hidden’];
if (‘publish’ === $post_status) {
$save_message = $save_message . ‘ <a href=”‘ . get_permalink($this->task_id) . ‘”>’ . __(‘View →’, ‘workscout-freelancer’) . ‘</a>’;
} elseif (in_array($original_post_status, $published_statuses, true) && ‘pending’ === $post_status) {
$save_message = __(‘Your changes have been submitted and your task will be available again once approved.’, ‘workscout-freelancer’);
/**
* Resets the task expiration date when a user submits their task listing edit for re-approval.
* Defaults to `false`.
*
* @since 1.18.0
*
* @param bool $reset_expiration If true, reset expiration date.
*/
if (apply_filters(‘task_manager_reset_listing_expiration_on_user_edit’, false)) {
delete_post_meta($this->task_id, ‘_task_expires’);
}
}
/**
* Change the message that appears when a user edits a task.
*
* @since 1.18.0
*
* @param string $save_message Save message to filter.
* @param int $task_id Resume ID.
* @param array $values Submitted values for task.
*/
$this->save_message = apply_filters(‘task_manager_update_task_listings_message’, $save_message, $this->task_id, $values);
// Add the message and redirect to the candidate dashboard if possible.
if (WP_Resume_Manager_Shortcodes::add_candidate_dashboard_message($this->save_message)) {
$candidate_dashboard_page_id = get_option(‘task_manager_candidate_dashboard_page_id’);
$candidate_dashboard_url = get_permalink($candidate_dashboard_page_id);
if ($candidate_dashboard_url) {
wp_safe_redirect($candidate_dashboard_url);
exit;
}
}
} catch (Exception $e) {
$this->save_error = $e->getMessage();
}
}
}
class-workscout-freelancer-form-submit-task.php
<?php
/**
* File containing the WP_Task_Manager_Form_Submit_Task.
*
* @package wp-job-manager-tasks
*/
if ( ! defined( ‘ABSPATH’ ) ) {
exit;
}
/**
* WP_Task_Manager_Form_Submit_Task class.
*/
class WorkScout_Freelancer_Form_Submit_Task extends WP_Job_Manager_Form {
/**
* Form name slug.
*
* @var string
*/
public $form_name = ‘submit-task’;
/**
* Current task ID.
*
* @var int
*/
protected $task_id;
/**
* The single instance of the class.
*
* @var WorkScout_Freelancer_Form_Submit_Task
*/
protected static $instance = null;
/**
* Main Instance.
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
public function __construct() {
add_action( ‘wp’, [ $this, ‘process’ ] );
add_action( ‘submit_task_form_start’, [ $this, ‘output_submit_form_nonce_field’ ] );
add_action( ‘preview_task_form_start’, [ $this, ‘output_preview_form_nonce_field’ ] );
$this->steps = (array) apply_filters(
‘submit_task_steps’,
[
‘submit’ => [
‘name’ => __( ‘Submit Details’, ‘workscout-freelancer’ ),
‘view’ => [ $this, ‘submit’ ],
‘handler’ => [ $this, ‘submit_handler’ ],
‘priority’ => 10,
],
‘preview’ => [
‘name’ => __( ‘Preview’, ‘workscout-freelancer’ ),
‘view’ => [ $this, ‘preview’ ],
‘handler’ => [ $this, ‘preview_handler’ ],
‘priority’ => 20,
],
‘done’ => [
‘name’ => __( ‘Done’, ‘workscout-freelancer’ ),
‘view’ => [ $this, ‘done’ ],
‘handler’ => ”,
‘priority’ => 30,
],
]
);
uasort( $this->steps, [ $this, ‘sort_by_priority’ ] );
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended — Input is used safely.
// Get step/job.
if ( isset( $_REQUEST[‘step’] ) ) {
$this->step = is_numeric( $_REQUEST[‘step’] ) ? max( absint( $_REQUEST[‘step’] ), 0 ) : array_search( sanitize_text_field( $_REQUEST[‘step’] ), array_keys( $this->steps ), true );
} elseif (!empty($_GET[‘step’])) {
$this->step = is_numeric($_GET[‘step’]) ? max(absint($_GET[‘step’]), 0) : array_search(sanitize_text_field($_GET[‘step’]), array_keys($this->steps), true);
}
$this->task_id = !empty($_GET[‘task_id’]) ? absint($_GET[‘task_id’]) : 0;
if (0 === $this->task_id) {
$this->task_id = !empty($_POST[‘task_id’]) ? absint($_POST[‘task_id’]) : 0;
}
// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
if ( !workscout_freelancer_user_can_edit_task( $this->task_id ) ) {
$this->task_id = 0;
}
// Load task details.
if ( $this->task_id ) {
$task_status = get_post_status( $this->task_id );
if ( ‘expired’ === $task_status ) {
if ( !workscout_freelancer_user_can_edit_task( $this->task_id ) ) {
$this->task_id = 0;
$this->step = 0;
}
} elseif (
0 === $this->step
&& ! in_array( $task_status, apply_filters( ‘workscout_freelancer_valid_submit_task_statuses’, [ ‘preview’ ] ), true )
) // phpcs:ignore WordPress.Security.NonceVerification.Missing — Safe use of input.
{
$this->task_id = 0;
$this->step = 0;
}
}
// // Clear job ID if it isn’t a published job.
// if (
// empty( $this->task_id )
// || ‘task’ !== get_post_type( $this->task_id )
// || ‘publish’ !== get_post_status( $this->task_id )
// ) {
// $this->task_id = 0;
// }
}
/**
* Get the submitted task ID.
*
* @return int
*/
public function get_task_id() {
return absint( $this->task_id );
}
/**
* Get the job ID if applying.
*
* @return int
*/
// public function get_job_id() {
// return absint( $this->job_id );
// }
/**
* Get a field from either task manager or job manager. Used by `task-submit.php`
* and `form-fields/repeated-field.php` templates.
*
* @param string $key Name of field.
* @param array $field Configuration arguments for the field.
*/
public function get_field_template( $key, $field ) {
switch ( $field[‘type’] ) {
case ‘radio’:
get_job_manager_template(
‘form-fields/’ . $field[‘type’] . ‘-field.php’,
[
‘key’ => $key,
‘field’ => $field,
‘class’ => $this,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
break;
case ‘dynamic-input’:
get_job_manager_template(
‘form-fields/’ . $field[‘type’] . ‘-field.php’,
[
‘key’ => $key,
‘field’ => $field,
‘class’ => $this,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
break;
default:
get_job_manager_template(
‘form-fields/’ . $field[‘type’] . ‘-field.php’,
[
‘key’ => $key,
‘field’ => $field,
‘class’ => $this,
],
);
break;
}
}
/**
* Initialize fields.
*/
public function init_fields() {
if ( $this->fields ) {
return;
}
$max_skills = get_option( ‘task_manager_max_skills’ );
$max_skills_notice = null;
if ( $max_skills ) {
// translators: Placeholder %d is the maximum number of skills a visitor can add.
$max_skills_notice = ‘ ‘ . sprintf( __( ‘Maximum of %d.’, ‘workscout-freelancer’ ), $max_skills );
}
$this->fields = apply_filters(
‘submit_task_form_fields’,
[
‘company_fields’ => [
‘company_id’ => array(
‘label’ => esc_html__(‘Company’, ‘mas-wp-job-manager-company’),
‘type’ => ‘select’,
‘required’ => false,
‘placeholder’ => esc_html__(‘Choose a Company’, ‘mas-wp-job-manager-company’),
‘priority’ => 0,
‘options’ => $this->get_companies_list(),
),
],
‘task_fields’ => [
‘task_title’ => [
‘label’ => __(‘Project Name’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
‘required’ => true,
‘placeholder’ => __( ‘e.g build me a website’, ‘workscout-freelancer’ ),
‘priority’ => 1,
‘width’ => 4
],
‘task_category’ => [
‘label’ => __(‘Category’, ‘workscout-freelancer’),
‘type’ => ‘term-select’,
‘taxonomy’ => ‘task_category’,
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 2,
‘default’ => ”,
‘width’ => 4
],
‘task_location’ => [
‘label’ => __( ‘Location’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
‘required’ => true,
‘placeholder’ => __( ‘e.g. “London, UK”, “New York”, “Houston, TX”‘, ‘workscout-freelancer’ ),
‘priority’ => 3,
‘width’ => 4
],
‘remote_position’ => [
‘label’ => __(‘Remote Position’, ‘workscout-freelancer’),
‘description’ => __(‘Select if remote job.’, ‘workscout-freelancer’),
‘type’ => ‘checkbox’,
‘required’ => false,
‘priority’ => 4,
‘width’ => 2
],
‘task_deadline’ => [
‘label’ => __( ‘Deadline’, ‘workscout-freelancer’ ),
‘type’ => ‘date’,
‘required’ => true,
‘priority’ => 11,
‘width’ => 2
],
‘task_type’ => [
‘label’ => __(‘Billing type’, ‘workscout-freelancer’),
‘description’ => __(‘Select billing type.’, ‘workscout-freelancer’),
‘type’ => ‘radio’,
‘required’ => false,
‘options’ => array(
‘fixed’ => __(‘Fixed Price Project’, ‘workscout-freelancer’),
‘hourly’ => __(‘Hourly Project’, ‘workscout-freelancer’),
),
‘priority’ => 5,
‘width’ => 4
],
‘budget_min’ => [
‘label’ => __(‘What is your estimated budget?’, ‘workscout-freelancer’ ),
‘type’ => ‘number’,
‘required’ => false,
‘placeholder’ => __(‘Budget Min.’, ‘workscout-freelancer’ ),
‘currency’ => get_workscout_currency_symbol(),
‘priority’ => 7,
‘width’ => 3
],
‘budget_max’ => [
‘label’ => ‘ ’,
‘type’ => ‘number’,
‘required’ => false,
‘placeholder’ => __( ‘Budget Max.’, ‘workscout-freelancer’ ),
‘currency’ => get_workscout_currency_symbol(),
‘priority’ => 8,
‘width’ => 3
],
‘hourly_min’ => [
‘label’ => __(‘What is your min hourly rate ?’, ‘workscout-freelancer’ ),
‘type’ => ‘number’,
‘required’ => false,
‘placeholder’ => __( ‘Minimum’, ‘workscout-freelancer’ ),
‘priority’ => 9,
‘currency’ => get_workscout_currency_symbol(),
‘width’ => 3
],
‘hourly_max’ => [
‘label’ =>’ ’,
‘type’ => ‘number’,
‘required’ => false,
‘placeholder’ => __( ‘Maximum’, ‘workscout-freelancer’ ),
‘priority’ => 10,
‘currency’ => get_workscout_currency_symbol(),
‘width’ => 3
],
‘task_skill’ => [
‘label’ => __(‘Skills’, ‘workscout-freelancer’),
‘type’ => ‘dynamic-input’,
‘taxonomy’ => ‘task_skill’,
‘required’ => true,
‘multiple’ => true,
‘placeholder’ => ”,
‘priority’ =>11,
‘default’ => ”,
‘width’ => 4
],
‘task_content’ => [
‘label’ => __(‘Describe your Project’, ‘workscout-freelancer’),
‘type’ => ‘wp-editor’,
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 12,
‘personal_data’ => true,
‘width’ => 12
],
‘task_file’ => [
‘label’ => __( ‘Attachments (e.g. project brief)’, ‘workscout-freelancer’ ),
‘type’ => ‘attachments’,
‘required’ => false,
‘ajax’ => true,
‘multiple’ => true,
// translators: Placeholder %s is the maximum file size of the upload.
‘description’ => sprintf( __( ‘Optionally upload your documents to view. Max. file size: %s.’, ‘workscout-freelancer’ ), size_format( wp_max_upload_size() ) ),
‘priority’ => 13,
‘placeholder’ => ”,
‘personal_data’ => true,
‘width’ => 12
],
],
]
);
}
/**
* Reset the `fields` variable so it gets reinitialized. This should only be
* used for testing!
*/
public function reset_fields() {
$this->fields = null;
}
/**
* Get the value of a repeated fields (e.g. education, links).
*
* @param string $field_prefix Prefix added to the field names.
* @param array $fields List of the fields to be repeated.
* @return array
*/
public function get_repeated_field( $field_prefix, $fields ) {
$items = [];
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized — Safe use of input and sanitized below.
$input_repeated_row = ! empty( $_POST[ ‘repeated-row-‘ . $field_prefix ] ) ? wp_unslash( $_POST[ ‘repeated-row-‘ . $field_prefix ] ) : false;
if ( $input_repeated_row && is_array( $input_repeated_row ) ) {
// Sanitize the input “repeated-row-{$field_prefix}” from above.
$indexes = array_map( ‘absint’, $input_repeated_row );
foreach ( $indexes as $index ) {
$item = [];
foreach ( $fields as $key => $field ) {
$field_name = $field_prefix . ‘_’ . $key . ‘_’ . $index;
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized — Input sanitized below. Nonce check in standard edit/submit flows.
$input_field_value = isset( $_POST[ $field_name ] ) ? wp_unslash( $_POST[ $field_name ] ) : null;
switch ( $field[‘type’] ) {
case ‘textarea’:
// Sanitize text area input.
$item[ $key ] = wp_kses_post( $input_field_value );
break;
case ‘file’:
try {
$file = $this->upload_file( $field_name, $field );
} catch ( Exception $e ) {
$file = false;
}
// Fetch and sanitize file input using `\WP_Job_Manager_Form::get_posted_field()`.
if ( ! $file ) {
$file = $this->get_posted_field( ‘current_’ . $field_name, $field );
} elseif ( is_array( $file ) ) {
$file = array_filter( array_merge( $file, (array) $this->get_posted_field( ‘current_’ . $field_name, $field ) ) );
}
$item[ $key ] = $file;
break;
default:
$sanitize_callback = ‘sanitize_text_field’;
if ( isset( $field[‘sanitizer’] ) ) {
$sanitize_callback = $field[‘sanitizer’];
}
// Fetch and sanitize all other input.
if ( is_array( $input_field_value ) ) {
$item[ $key ] = array_filter( array_map( $sanitize_callback, $input_field_value ) );
} else {
$item[ $key ] = call_user_func( $sanitize_callback, $input_field_value );
}
break;
}
if ( empty( $item[ $key ] ) && ! empty( $field[‘required’] ) ) {
continue 2;
}
}
$items[] = $item;
}
}
return $items;
}
/**
* Get the value of a posted repeated field
*
* @since 1.22.4
* @param string $key
* @param array $field
* @return string
*/
public function get_posted_repeated_field( $key, $field ) {
return apply_filters( ‘submit_task_form_fields_get_repeated_field_data’, $this->get_repeated_field( $key, $field[‘fields’] ) );
}
/**
* Get the value of a posted file field
*
* @param string $key
* @param array $field
* @return string
*/
public function get_posted_links_field( $key, $field ) {
return apply_filters( ‘submit_task_form_fields_get_links_data’, $this->get_repeated_field( $key, $field[‘fields’] ) );
}
/**
* Get the value of a posted file field.
*
* @param string $key
* @param array $field
* @return string
*/
public function get_posted_education_field( $key, $field ) {
return apply_filters( ‘submit_task_form_fields_get_education_data’, $this->get_repeated_field( $key, $field[‘fields’] ) );
}
/**
* Get the value of a posted file field.
*
* @param string $key
* @param array $field
* @return string
*/
public function get_posted_experience_field( $key, $field ) {
return apply_filters( ‘submit_task_form_fields_get_experience_data’, $this->get_repeated_field( $key, $field[‘fields’] ) );
}
/**
* Validate the posted fields.
*
* @param array $values Input values submitted.
* @return WP_Error|bool
* @throws Exception During validation error.
*/
protected function validate_fields( $values ) {
foreach ( $this->fields as $group_key => $fields ) {
foreach ( $fields as $key => $field ) {
if ( $field[‘required’] && empty( $values[ $group_key ][ $key ] ) ) {
// translators: Placeholder %s is the name of the required field.
// check if the fields with id remote_job is checked if it is don’t require location tab
if($key == ‘task_location’ && isset($values[ $group_key ][‘remote_position’]) && $values[ $group_key ][‘remote_position’] == 1){
continue;
}
return new WP_Error( ‘validation-error’, sprintf( __( ‘%s is a required field’, ‘workscout-freelancer’ ), $field[‘label’] ) );
}
if ( ! empty( $field[‘taxonomy’] ) && in_array( $field[‘type’], [ ‘term-checklist’, ‘term-select’, ‘term-multiselect’ ], true ) ) {
if ( is_array( $values[ $group_key ][ $key ] ) ) {
foreach ( $values[ $group_key ][ $key ] as $term ) {
if ( ! term_exists( $term, $field[‘taxonomy’] ) ) {
// translators: Placeholder %s is the name of the invalid field.
return new WP_Error( ‘validation-error’, sprintf( __( ‘%s is invalid’, ‘workscout-freelancer’ ), $field[‘label’] ) );
}
}
} elseif ( ! empty( $values[ $group_key ][ $key ] ) ) {
if ( ! term_exists( $values[ $group_key ][ $key ], $field[‘taxonomy’] ) ) {
// translators: Placeholder %s is the name of the invalid field.
return new WP_Error( ‘validation-error’, sprintf( __( ‘%s is invalid’, ‘workscout-freelancer’ ), $field[‘label’] ) );
}
}
}
if ( ‘candidate_email’ === $key ) {
if ( ! empty( $values[ $group_key ][ $key ] ) && ! is_email( $values[ $group_key ][ $key ] ) ) {
throw new Exception( __( ‘Please enter a valid email address’, ‘workscout-freelancer’ ) );
}
}
if ( ‘task_skill’ === $key ) {
if ( is_string( $values[ $group_key ][ $key ] ) ) {
$raw_skills = explode( ‘,’, $values[ $group_key ][ $key ] );
} else {
$raw_skills = $values[ $group_key ][ $key ];
}
$max = get_option( ‘task_manager_max_skills’ );
if ( $max && count( $raw_skills ) > $max ) {
// translators: Placeholder %d is the maximum number of skills they can enter.
return new WP_Error( ‘validation-error’, sprintf( __( ‘Please enter no more than %d skills.’, ‘workscout-freelancer’ ), $max ) );
}
}
if ( ‘file’ === $field[‘type’] ) {
if ( is_array( $values[ $group_key ][ $key ] ) ) {
$check_value = array_filter( $values[ $group_key ][ $key ] );
} else {
$check_value = array_filter( [ $values[ $group_key ][ $key ] ] );
}
if ( ! empty( $check_value ) ) {
foreach ( $check_value as $file_url ) {
if ( is_numeric( $file_url ) ) {
continue;
}
$file_url = esc_url( $file_url, [ ‘http’, ‘https’ ] );
if ( empty( $file_url ) ) {
throw new Exception( __( ‘Invalid attachment provided.’, ‘workscout-freelancer’ ) );
}
}
}
}
}
}
return apply_filters( ‘submit_task_form_validate_fields’, true, $this->fields, $values );
}
/**
* Submit Step
*/
public function submit() {
$this->init_fields();
// Load data if neccessary.
if ( $this->task_id ) {
$task = get_post( $this->task_id );
foreach ( $this->fields as $group_key => $fields ) {
foreach ( $fields as $key => $field ) {
switch ( $key ) {
case ‘task_title’:
$this->fields[ $group_key ][ $key ][‘value’] = $task->post_title;
break;
case ‘task_content’:
$this->fields[ $group_key ][ $key ][‘value’] = $task->post_content;
break;
case ‘task_skill’:
$this->fields[ $group_key ][ $key ][‘value’] = implode( ‘, ‘, wp_get_object_terms( $task->ID, ‘task_skill’, [ ‘fields’ => ‘names’ ] ) );
break;
case ‘task_category’:
$this->fields[ $group_key ][ $key ][‘value’] = wp_get_object_terms( $task->ID, ‘task_category’, [ ‘fields’ => ‘ids’ ] );
break;
default:
$this->fields[ $group_key ][ $key ][‘value’] = get_post_meta( $task->ID, ‘_’ . $key, true );
break;
}
}
}
$this->fields = apply_filters( ‘submit_task_form_fields_get_task_data’, $this->fields, $task );
} elseif (
is_user_logged_in()
&& empty( $_POST[‘submit_task’] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing — Using input safely.
) {
$user = wp_get_current_user();
foreach ( $this->fields as $group_key => $fields ) {
foreach ( $fields as $key => $field ) {
switch ( $key ) {
case ‘candidate_name’:
$this->fields[ $group_key ][ $key ][‘value’] = $user->first_name . ‘ ‘ . $user->last_name;
break;
case ‘candidate_email’:
$this->fields[ $group_key ][ $key ][‘value’] = $user->user_email;
break;
}
}
}
$this->fields = apply_filters( ‘submit_task_form_fields_get_user_data’, $this->fields, get_current_user_id() );
}
get_job_manager_template(
‘task-submit.php’,
[
‘class’ => $this,
‘form’ => $this->form_name,
‘task_id’ => $this->get_task_id(),
// ‘job_id’ => $this->get_job_id(),
‘action’ => $this->get_action(),
‘company_fields’ => $this->get_fields( ‘company_fields’ ),
‘task_fields’ => $this->get_fields( ‘task_fields’ ),
‘step’ => $this->get_step(),
‘submit_button_text’ => apply_filters( ‘submit_task_form_submit_button_text’, __( ‘Preview →’, ‘workscout-freelancer’ ) ),
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
}
/**
* Submit Step is posted.
*/
public function submit_handler() {
try {
// Init fields.
$this->init_fields();
// Get posted values.
$values = $this->get_posted_fields();
// phpcs:ignore WordPress.Security.NonceVerification.Missing — Check happens later when possible.
if ( empty( $_POST[‘submit_task’] ) ) {
return;
}
$this->check_submit_form_nonce_field();
// Validate required.
$validation_result = $this->validate_fields( $values );
if ( is_wp_error( ( $validation_result ) ) ) {
throw new Exception( $validation_result->get_error_message() );
}
// Account creation.
if ( ! is_user_logged_in() ) {
throw new Exception( __( ‘You must be signed in to post your task.’, ‘workscout-freelancer’ ) );
}
// Update the job.
$this->save_task( $values[‘task_fields’][‘task_title’], $values[‘task_fields’][‘task_content’], $this->task_id ? ” : ‘preview’, $values );
$this->update_task_data( $values );
// Successful, show next step.
$this->step++;
} catch ( Exception $e ) {
$this->add_error( $e->getMessage() );
return;
}
}
/**
* Update or create a job listing from posted data.
*
* @param string $post_title Post title.
* @param string $post_content Post content.
* @param string $status Post status to save.
* @param array $values Values from the form.
*/
protected function save_task( $post_title, $post_content, $status = ‘preview’, $values = [] ) {
$task_data = [
‘post_title’ => $post_title,
‘post_content’ => $post_content,
‘post_type’ => ‘task’,
‘comment_status’ => ‘closed’,
];
if ($status) {
$task_data[‘post_status’] = $status;
}
$task_data = apply_filters(‘submit_task_form_save_job_data’, $task_data, $post_title, $post_content, $status, $values);
if ($this->task_id) {
$task_data[‘ID’] = $this->task_id;
wp_update_post($task_data);
} else {
$this->task_id = wp_insert_post($task_data);
if (!headers_sent()) {
$submitting_key = uniqid();
setcookie(‘wp-job-manager-submitting-task-id’, $this->task_id, false, COOKIEPATH, COOKIE_DOMAIN, false);
setcookie(‘wp-job-manager-submitting-task-key’, $submitting_key, false, COOKIEPATH, COOKIE_DOMAIN, false);
update_post_meta($this->task_id, ‘_submitting_key’, $submitting_key);
}
}
// // Get random key.
// if ( $this->task_id ) {
// $prefix = get_post_meta( $this->task_id, ‘_task_name_prefix’, true );
// if ( ! $prefix ) {
// $prefix = wp_generate_password( 10 );
// }
// } else {
// $prefix = wp_generate_password( 10 );
// }
// $task_slug = [];
// $task_slug[] = current( explode( ‘ ‘, $post_title ) );
// $task_slug[] = $prefix;
// if ( ! empty( $values[‘task_fields’][‘task_title’] ) ) {
// $task_slug[] = $values[‘task_fields’][‘task_title’];
// }
// if ( ! empty( $values[‘task_fields’][‘task_location’] ) ) {
// $task_slug[] = $values[‘task_fields’][‘task_location’];
// }
// $data = [
// ‘post_title’ => $post_title,
// ‘post_content’ => $post_content,
// ‘post_type’ => ‘task’,
// ‘comment_status’ => ‘closed’,
// ‘post_password’ => ”,
// ‘post_name’ => sanitize_title( implode( ‘-‘, $task_slug ) ),
// ];
// if ( $status ) {
// $data[‘post_status’] = $status;
// }
// $data = apply_filters( ‘submit_task_form_save_task_data’, $data, $post_title, $post_content, $status, $values, $this );
// if ( $this->task_id ) {
// $data[‘ID’] = $this->task_id;
// wp_update_post( $data );
// } else {
// $this->task_id = wp_insert_post( $data );
// update_post_meta( $this->task_id, ‘_task_name_prefix’, $prefix );
// update_post_meta( $this->task_id, ‘_public_submission’, true );
// // If and only if we’re dealing with a logged out user and that is allowed, allow the user to continue a submission after it was started.
// if ( ! is_user_logged_in() ) {
// $submitting_key = sha1( uniqid() );
// setcookie( ‘wp-job-manager-submitting-task-key-‘ . $this->task_id, $submitting_key, 0, COOKIEPATH, COOKIE_DOMAIN, is_ssl() );
// update_post_meta( $this->task_id, ‘_submitting_key’, $submitting_key );
// }
// }
}
/**
* Set job meta + terms based on posted values
*
* @param array $values
*/
protected function update_task_data( $values ) {
// Set defaults.
add_post_meta( $this->task_id, ‘_featured’, 0, true );
// Reset submission lifecycle flag.
delete_post_meta( $this->task_id, ‘_submission_finalized’ );
$maybe_attach = [];
// Loop fields and save meta and term data.
foreach ( $this->fields as $group_key => $group_fields ) {
foreach ( $group_fields as $key => $field ) {
// Save taxonomies.
if ( ! empty( $field[‘taxonomy’] ) ) {
if( $field[‘type’] != ‘dynamic-input’ ){
if ( is_array( $values[ $group_key ][ $key ] ) ) {
wp_set_object_terms( $this->task_id, $values[ $group_key ][ $key ], $field[‘taxonomy’], false );
} else {
wp_set_object_terms( $this->task_id, [ $values[ $group_key ][ $key ] ], $field[‘taxonomy’], false );
}
}
// Save meta data.
} else {
if (‘task_location’ === $key ) {
if ( ! WP_Job_Manager_Geocode::has_location_data($this->task_id ) ) {
WP_Job_Manager_Geocode::generate_location_data($this->task_id, sanitize_text_field( $values[$group_key][$key] ) );
}
}
update_post_meta( $this->task_id, ‘_’ . $key, $values[ $group_key ][ $key ] );
}
// Handle attachments.
if ( ‘file’ === $field[‘type’] ) {
// Must be absolute.
if ( is_array( $values[ $group_key ][ $key ] ) ) {
foreach ( $values[ $group_key ][ $key ] as $file_url ) {
$maybe_attach[] = str_replace( [ WP_CONTENT_URL, site_url() ], [ WP_CONTENT_DIR, ABSPATH ], $file_url );
}
} else {
$maybe_attach[] = str_replace( [ WP_CONTENT_URL, site_url() ], [ WP_CONTENT_DIR, ABSPATH ], $values[ $group_key ][ $key ] );
}
}
}
}
if ( isset( $values[‘task_fields’][‘task_skill’] ) ) {
$tags = [];
$raw_tags = $values[‘task_fields’][‘task_skill’];
if ( is_string( $raw_tags ) ) {
// Explode and clean.
$raw_tags = array_filter( array_map( ‘sanitize_text_field’, explode( ‘,’, $raw_tags ) ) );
if ( ! empty( $raw_tags ) ) {
foreach ( $raw_tags as $tag ) {
$term = get_term_by( ‘name’, $tag, ‘task_skill’ );
if ( $term ) {
$tags[] = $term->term_id;
} else {
$term = wp_insert_term( $tag, ‘task_skill’ );
if ( ! is_wp_error( $term ) ) {
$tags[] = $term[‘term_id’];
}
}
}
}
} else {
$tags = array_map( ‘absint’, $raw_tags );
}
wp_set_object_terms( $this->task_id, $tags, ‘task_skill’, false );
}
// Handle attachments.
if ( count( $maybe_attach ) ) {
/** WordPress Administration Image API */
include_once ABSPATH . ‘wp-admin/includes/image.php’;
// Get attachments.
$attachments = get_posts( ‘post_parent=’ . $this->task_id . ‘&post_type=attachment&fields=ids&post_mime_type=image&numberposts=-1’ );
$attachment_urls = [];
// Loop attachments already attached to the job.
foreach ( $attachments as $attachment_key => $attachment ) {
$attachment_urls[] = str_replace( [ WP_CONTENT_URL, site_url() ], [ WP_CONTENT_DIR, ABSPATH ], wp_get_attachment_url( $attachment ) );
}
foreach ( $maybe_attach as $attachment_url ) {
$attachment_url = esc_url( $attachment_url, [ ‘http’, ‘https’ ] );
if ( empty( $attachment_url ) ) {
continue;
}
if ( ! in_array( $attachment_url, $attachment_urls, true ) ) {
$attachment = [
‘post_title’ => get_the_title( $this->task_id ),
‘post_content’ => ”,
‘post_status’ => ‘inherit’,
‘post_parent’ => $this->task_id,
‘guid’ => $attachment_url,
];
$info = wp_check_filetype( $attachment_url );
if ( $info ) {
$attachment[‘post_mime_type’] = $info[‘type’];
}
$attachment_id = wp_insert_attachment( $attachment, $attachment_url, $this->task_id );
if ( ! is_wp_error( $attachment_id ) ) {
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $attachment_url ) );
}
}
}
}
do_action( ‘workscout_freelancer_update_task_data’, $this->task_id, $values );
}
/**
* Preview Step
*/
public function preview() {
global $post, $task_preview;
$this->check_valid_task();
// wp_enqueue_script( ‘wp-task-manager-task-submission’ );
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited — Job preview depends on temporary override. Reset below.
$post = get_post( $this->task_id );
$task_preview = true;
setup_postdata( $post );
get_job_manager_template(
‘task-preview.php’,
[
‘form’ => $this,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
wp_reset_postdata();
}
/**
* Preview Step Form handler
*/
public function preview_handler() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing — Input is used safely.
if ( empty( $_POST ) ) {
return;
}
$this->check_preview_form_nonce_field();
$this->check_valid_task();
// Edit = show submit form again.
if ( ! empty( $_POST[‘edit_task’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing — Nonce was checked above.
$this->step–;
}
// Continue = change job status then show next screen.
if ( ! empty( $_POST[‘continue’] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing — Nonce was checked above.
$task = get_post( $this->task_id );
if ( in_array( $task->post_status, [ ‘preview’, ‘expired’ ], true ) ) {
// Reset expiry.
delete_post_meta( $task->ID, ‘_task_expires’ );
// Update listing.
$update_task = [];
$update_task[‘ID’] = $task->ID;
$update_task[‘post_date’] = current_time( ‘mysql’ );
$update_task[‘post_date_gmt’] = current_time( ‘mysql’, 1 );
$update_task[‘post_author’] = get_current_user_id();
$update_task[‘post_status’] = apply_filters( ‘submit_task_post_status’, get_option( ‘task_manager_submission_requires_approval’ ) ? ‘pending’ : ‘publish’, $task );
wp_update_post( $update_task );
}
$this->step++;
/**
* Do not redirect if WCPL is set to choose package before submitting listing
*
* By not redirecting, we allow $this->process() (@see abstract-wp-job-manager-form.php) to call the ‘wc-process-package’
* handler first, instead of view, which does not exist in ‘wc-process-package’ (and would be called first on redirect).
*/
if ( ‘before’ !== get_option( ‘task_paid_listings_flow’ ) ) {
wp_safe_redirect(
esc_url_raw(
add_query_arg(
[
‘step’ => $this->step,
‘task_id’ => $this->task_id,
]
)
)
);
exit;
}
}
}
/**
* Done Step.
*/
public function done() {
$this->check_valid_task();
get_job_manager_template(
‘task-submitted.php’,
[
‘task’ => get_post( $this->task_id ),
‘task_id’ => $this->task_id,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
delete_post_meta( $this->task_id, ‘_submitting_key’ );
// Allow application.
}
/**
* Validate the task ID passed. Respond with a 400 Bad Request error if an invalid ID is passed.
* `self::$task_id` is already cleared out in the constructor if the user doesn’t have
* permission to access it, but we still file actions without checking its value.
*/
private function check_valid_task() {
if (
! empty( $this->task_id )
&& ‘task’ === get_post_type( $this->task_id )
) {
return;
}
wp_die(
esc_html__( ‘Invalid task’, ‘workscout-freelancer’ ),
”,
[
‘response’ => 400,
‘back_link’ => true,
]
);
}
/**
* Output the nonce field on job preview form.
*
* @access private
*/
public function output_preview_form_nonce_field() {
wp_nonce_field( ‘preview-task-‘ . $this->task_id, ‘_wpjm_nonce’ );
}
/**
* Check the nonce field on the preview form.
*
* @access private
*/
public function check_preview_form_nonce_field() {
if (
empty( $_REQUEST[‘_wpjm_nonce’] )
|| ! wp_verify_nonce( wp_unslash( $_REQUEST[‘_wpjm_nonce’] ), ‘preview-task-‘ . $this->task_id ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized — Nonce should not be modified.
) {
wp_nonce_ays( ‘preview-task-‘ . $this->task_id );
die();
}
}
/**
* Output the nonce field on job submission form.
*
* @access private
*/
public function output_submit_form_nonce_field() {
wp_nonce_field( ‘submit-task-‘ . $this->task_id, ‘_wpjm_nonce’ );
}
/**
* Check the nonce field on the submit form.
*
* @access private
*/
public function check_submit_form_nonce_field() {
if (
empty( $_REQUEST[‘_wpjm_nonce’] )
|| ! wp_verify_nonce( wp_unslash( $_REQUEST[‘_wpjm_nonce’] ), ‘submit-task-‘ . $this->task_id ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized — Nonce should not be modified.
) {
wp_nonce_ays( ‘submit-task-‘ . $this->task_id );
die();
}
}
/**
* Get the task fields use on the submission form.
*
* @return array
*/
public static function get_task_fields() {
$instance = self::instance();
$instance->init_fields();
return $instance->get_fields( ‘task_fields’ );
}
public function get_companies_list(){
global $current_user;
$options = array(
” => esc_html__(‘Private Listing’, ‘workscout-freelancer’),
);
if (is_user_logged_in() && !empty($current_user)) {
$args = array(
‘post_type’ => ‘company’,
‘orderby’ => ‘title’,
‘order’ => ‘ASC’,
‘numberposts’ => -1,
);
$args[‘author’] = $current_user->ID;
$companies = get_posts(apply_filters(‘masjm_get_current_user_companies_args’, $args));
if (!empty($companies)) {
foreach ($companies as $company) {
$options[$company->ID] = get_the_title($company);
}
} else {
$options = array(
” => esc_html__(‘Private Listing’, ‘workscout-freelancer’),
);
}
} else {
$options = array(
” => esc_html__(‘User Not Logged In’, ‘workscout-freelancer’),
);
}
return $options;
}
}
Class-wc-paid-listings-submit-task-form.php
<?php
if ( ! defined( ‘ABSPATH’ ) ) {
exit;
}
/**
* Form Integration
*/
class WP_Job_Manager_WCPL_Submit_Task_Form {
private static $package_id = 0;
private static $is_user_package = false;
/**
* Init
*/
public static function init() {
// add_filter( ‘the_title’, array( __CLASS__, ‘append_package_name’ ) );
add_action( ‘wp_enqueue_scripts’, array( __CLASS__, ‘styles’ ) );
add_filter( ‘submit_task_steps’, array( __CLASS__, ‘submit_task_steps’ ), 10 );
// Posted Data
if ( ! empty( $_POST[‘task_package’] ) ) {
if ( is_numeric( $_POST[‘task_package’] ) ) {
self::$package_id = absint( $_POST[‘task_package’] );
self::$is_user_package = false;
} else {
self::$package_id = absint( substr( $_POST[‘task_package’], 5 ) );
self::$is_user_package = true;
}
} elseif ( ! empty( $_COOKIE[‘chosen_package_id’] ) ) {
self::$package_id = absint( $_COOKIE[‘chosen_package_id’] );
self::$is_user_package = absint( $_COOKIE[‘chosen_package_is_user_package’] ) === 1;
}
}
/**
* Replace a page title with the endpoint title
*
* @param string $title
* @return string
*/
public static function append_package_name( $title ) {
if ( ! empty( $_POST ) && ! is_admin() && is_main_query() && in_the_loop() && is_page( get_option(‘workscout_freelancer_submit_task_form_page_id’ ) ) && self::$package_id && ‘before’ === get_option(‘task_paid_listings_flow’ ) && apply_filters( ‘wcpl_append_package_name’, true ) ) {
if ( self::$is_user_package ) {
$package = wc_paid_listings_get_user_package( self::$package_id );
$title .= ‘ – ‘ . $package->get_title();
} else {
$post = get_post( self::$package_id );
if ( $post ) {
$title .= ‘ – ‘ . $post->post_title;
}
}
remove_filter( ‘the_title’, array( __CLASS__, ‘append_package_name’ ) );
}
return $title;
}
/**
* Add form styles
*/
public static function styles() {
wp_enqueue_style( ‘wc-paid-listings-packages’ );
}
/**
* Change submit button text
*
* @return string
*/
public static function submit_button_text() {
return __( ‘Choose a package →’, ‘workscout-freelancer’ );
}
/**
* Change initial job status
*
* @return string
*/
public static function submit_task_post_status( $status, $task ) {
switch ( $task->post_status ) {
case ‘preview’:
return ‘pending_payment’;
break;
case ‘expired’:
return ‘expired’;
break;
default:
return $status;
break;
}
}
/**
* Return packages
*
* @return array
*/
public static function get_packages() {
return get_posts(
apply_filters(
‘wcpl_get_task_packages_args’,
array(
‘post_type’ => ‘product’,
‘posts_per_page’ => -1,
‘order’ => ‘asc’,
‘orderby’ => ‘menu_order’,
‘suppress_filters’ => false,
‘tax_query’ => WC()->query->get_tax_query(
array(
‘relation’ => ‘AND’,
array(
‘taxonomy’ => ‘product_type’,
‘field’ => ‘slug’,
‘terms’ => array( ‘task_package’, ‘task_package_subscription’ ),
‘operator’ => ‘IN’,
),
)
),
‘meta_query’ => WC()->query->get_meta_query(),
)
)
);
}
/**
* Change the steps during the submission process
*
* @param array $steps
* @return array
*/
public static function submit_task_steps( $steps ) {
if ( self::get_packages() && apply_filters( ‘wcpl_enable_paid_task_submission’, true ) ) {
// We need to hijack the preview submission to redirect to WooCommerce and add a step to select a package.
// Add a step to allow the user to choose a package. Comes after preview.
$steps[‘wc-choose-package’] = array(
‘name’ => __( ‘Choose a package’, ‘workscout-freelancer’ ),
‘view’ => array( __CLASS__, ‘choose_package’ ),
‘handler’ => array( __CLASS__, ‘choose_package_handler’ ),
‘priority’ => 25,
);
// If we instead want to show the package selection FIRST, change the priority and add a new handler.
if ( ‘before’ === get_option( ‘task_paid_listings_flow’ ) ) {
$steps[‘wc-choose-package’][‘priority’] = 5;
$steps[‘wc-process-package’] = array(
‘name’ => ”,
‘view’ => false,
‘handler’ => array( __CLASS__, ‘choose_package_handler’ ),
‘priority’ => 25,
);
// If showing the package step after preview, the preview button text should be changed to show this.
} elseif ( ‘before’ !== get_option( ‘task_paid_listings_flow’ ) ) {
add_filter( ‘submit_task_step_preview_submit_text’, array( __CLASS__, ‘submit_button_text’ ), 10 );
}
// We should make sure new jobs are pending payment and not published or pending.
add_filter( ‘submit_task_post_status’, array( __CLASS__, ‘submit_task_post_status’ ), 10, 2 );
}
return $steps;
}
/**
* Get the package ID being used for task submission, expanding any user package
*
* @return int
*/
public static function get_package_id() {
if ( self::$is_user_package ) {
$package = wc_paid_listings_get_user_package( self::$package_id );
return $package->get_product_id();
}
return self::$package_id;
}
/**
* Choose package form
*/
public static function choose_package() {
$form = WorkScout_Freelancer_Form_Submit_Task::instance();
$task_id = $form->get_task_id();
$step = $form->get_step();
$form_name = $form->form_name;
$packages = self::get_packages();
$user_packages = wc_paid_listings_get_user_packages( get_current_user_id(), ‘task’ );
$button_text = ‘before’ !== get_option(‘task_paid_listings_flow’ ) ? __( ‘Submit →’, ‘workscout-freelancer’ ) : __( ‘Listing Details →’, ‘workscout-freelancer’ );
get_job_manager_template(
‘task-package-selection.php’,
array(
‘packages’ => $packages,
‘user_packages’ => $user_packages,
‘task_id’ => $task_id,
‘step’ => $step,
‘form_name’ => $form_name,
‘button_text’ => $button_text,
),
‘wp-job-manager-tasks’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
?>
<?php
}
/**
* Validate package
*
* @param int $package_id
* @param bool $is_user_package
* @return bool|WP_Error
*/
private static function validate_package( $package_id, $is_user_package ) {
if ( empty( $package_id ) ) {
return new WP_Error( ‘error’, __( ‘Invalid Package’, ‘workscout-freelancer’ ) );
} elseif ( $is_user_package ) {
if ( ! wc_paid_listings_package_is_valid( get_current_user_id(), $package_id ) ) {
return new WP_Error( ‘error’, __( ‘Invalid Package’, ‘workscout-freelancer’ ) );
}
} else {
$package = wc_get_product( $package_id );
if ( ! $package->is_type( ‘task_package’ ) && ! $package->is_type( ‘task_package_subscription’ ) ) {
return new WP_Error( ‘error’, __( ‘Invalid Package’, ‘workscout-freelancer’ ) );
}
// Don’t let them buy the same subscription twice
if ( class_exists( ‘WC_Subscriptions’ )
&& is_user_logged_in()
&& $package->is_type( ‘task_package_subscription’ )
&& $package instanceof WC_Product_task_Package_Subscription
&& ‘package’ === $package->get_package_subscription_type()
) {
if ( wcs_user_has_subscription( get_current_user_id(), $package_id, ‘active’ ) ) {
return new WP_Error( ‘error’, __( ‘You already have this subscription.’, ‘workscout-freelancer’ ) );
}
}
}
return true;
}
/**
* Purchase a job package
*
* @param int|string $package_id
* @param bool $is_user_package
* @param int $task_id
* @return bool Did it work or not?
*/
private static function process_package( $package_id, $is_user_package, $task_id ) {
// Make sure the job has the correct status
if ( ‘preview’ === get_post_status( $task_id ) ) {
// Update job listing
$update = array();
$update[‘ID’] = $task_id;
$update[‘post_status’] = ‘pending_payment’;
$update[‘post_date’] = current_time( ‘mysql’ );
$update[‘post_date_gmt’] = current_time( ‘mysql’, 1 );
$update[‘post_author’] = get_current_user_id();
wp_update_post( $update );
}
if ( $is_user_package ) {
$package = workscout_freelancer_get_user_package( $package_id );
// Give task the package attributes
update_post_meta( $task_id, ‘_featured’, $package->is_featured() ? 1 : 0 );
update_post_meta( $task_id, ‘_task_duration’, $package->get_duration() );
update_post_meta( $task_id, ‘_package_id’, $package->get_product_id() );
update_post_meta( $task_id, ‘_user_package_id’, $package_id );
// Approve the task
if ( in_array( get_post_status( $task_id ), array( ‘pending_payment’, ‘expired’ ) ) ) {
workscout_freelancer_approve_listing_with_package( $task_id, get_current_user_id(), $package_id );
}
do_action( ‘wcpl_process_package_for_task’, $package_id, $is_user_package, $task_id );
return true;
} elseif ( $package_id ) {
$package = wc_get_product( $package_id );
$is_featured = false;
if ( $package instanceof WC_Product_task_Package || $package instanceof WC_Product_task_Package_Subscription ) {
$is_featured = $package->is_task_featured();
}
// Give task the package attributes
update_post_meta( $task_id, ‘_featured’, $is_featured ? 1 : 0 );
update_post_meta( $task_id, ‘_task_duration’, $package->get_duration() );
update_post_meta( $task_id, ‘_package_id’, $package->get_product_id() );
// Add package to the cart
WC()->cart->add_to_cart(
$package_id,
1,
”,
”,
array(
‘task_id’ => $task_id,
)
);
wc_add_to_cart_message( $package_id );
// Clear cookie
wc_setcookie( ‘chosen_package_id’, ”, time() – HOUR_IN_SECONDS );
wc_setcookie( ‘chosen_package_is_user_package’, ”, time() – HOUR_IN_SECONDS );
do_action( ‘wcpl_process_package_for_task’, $package_id, $is_user_package, $task_id );
// Redirect to checkout page
wp_redirect( get_permalink( wc_get_page_id( ‘checkout’ ) ) );
exit;
}// End if().
}
/**
* Choose package handler
*
* @return bool
*/
public static function choose_package_handler() {
$form = WorkScout_Freelancer_Form_Submit_Task::instance();
// Validate Selected Package
$validation = self::validate_package( self::$package_id, self::$is_user_package );
// Error? Go back to choose package step.
if ( is_wp_error( $validation ) ) {
$form->add_error( $validation->get_error_message() );
$form->set_step( array_search( ‘wc-choose-package’, array_keys( $form->get_steps() ) ) );
return false;
}
// Store selection in cookie
wc_setcookie( ‘chosen_package_id’, self::$package_id );
wc_setcookie( ‘chosen_package_is_user_package’, self::$is_user_package ? 1 : 0 );
// Process the package unless we’re doing this before a task is submitted
if ( ‘before’ !== get_option(‘task_paid_listings_flow’ ) || ‘wc-process-package’ === $form->get_step_key() ) {
// Product the package
if ( self::process_package( self::$package_id, self::$is_user_package, $form->get_task_id() ) ) {
$form->next_step();
}
} else {
$form->next_step();
}
}
}
WP_Job_Manager_WCPL_Submit_task_Form::init();
class-wc-product-task-package.php
<?php
if ( ! defined( ‘ABSPATH’ ) ) {
exit;
}
/**
* Task Package Product Type
*/
class WC_Product_Task_Package extends WP_Job_Manager_WCPL_Package_Product {
/**
* Constructor
*
* @param int|WC_Product|object $product Product ID, post object, or product object
*/
public function __construct( $product ) {
parent::__construct( $product );
}
/**
* Get internal type.
*
* @return string
*/
public function get_type() {
return ‘task_package’;
}
/**
* We want to sell jobs one at a time
*
* @return boolean
*/
public function is_sold_individually() {
return apply_filters( ‘wcpl_’ . $this->get_type() . ‘_is_sold_individually’, true );
}
/**
* Get the add to url used mainly in loops.
*
* @access public
* @return string
*/
public function add_to_cart_url() {
return apply_filters( ‘woocommerce_product_add_to_cart_url’, $this->is_in_stock() ? remove_query_arg( ‘added-to-cart’, add_query_arg( ‘add-to-cart’, $this->get_id() ) ) : get_permalink( $this->get_id() ), $this );
}
/**
* Get the add to cart button text
*
* @access public
* @return string
*/
public function add_to_cart_text() {
$text = $this->is_purchasable() && $this->is_in_stock() ? __( ‘Add to cart’, ‘workscout-freelancer’ ) : __( ‘Read More’, ‘workscout-freelancer’ );
return apply_filters( ‘woocommerce_product_add_to_cart_text’, $text, $this );
}
/**
* Return listing duration granted
*
* @return int
*/
public function get_duration() {
$task_duration = $this->get_task_duration();
if ( $task_duration ) {
return $task_duration;
} else {
return get_option( ‘task_submission_duration’ );
}
}
/**
* Return task limit
*
* @return int 0 if unlimited
*/
public function get_limit() {
$task_limit = $this->get_task_limit();
if ( $task_limit ) {
return $task_limit;
} else {
return 0;
}
}
/**
* Return if featured
*
* @return bool true if featured
*/
public function is_task_featured() {
return ‘yes’ === $this->get_task_featured();
}
/**
* Get task featured flag
*
* @return string
*/
public function get_task_featured() {
return $this->get_product_meta( ‘listing_featured’ );
}
/**
* Get task limit
*
* @return int
*/
public function get_task_limit() {
return $this->get_product_meta( ‘listing_limit’ );
}
/**
* Get task duration
*
* @return int
*/
public function get_task_duration() {
return $this->get_product_meta( ‘listing_duration’ );
}
}
class-workscout-freelancer.php
<?php
if ( ! defined( ‘ABSPATH’ ) ) exit;
class WorkScout_Freelancer {
/**
* The single instance of WorkScout_Freelancer.
* @var object
* @access private
* @since 1.0.0
*/
private static $_instance = null;
/**
* Settings class object
* @var object
* @access public
* @since 1.0.0
*/
public $settings = null;
/**
* The version number.
* @var string
* @access public
* @since 1.0.0
*/
public $_version;
/**
* The token.
* @var string
* @access public
* @since 1.0.0
*/
public $_token;
/**
* The main plugin file.
* @var string
* @access public
* @since 1.0.0
*/
public $file;
/**
* The main plugin directory.
* @var string
* @access public
* @since 1.0.0
*/
public $dir;
/**
* The plugin assets directory.
* @var string
* @access public
* @since 1.0.0
*/
public $assets_dir;
/**
* The plugin assets URL.
* @var string
* @access public
* @since 1.0.0
*/
public $assets_url;
/**
* Suffix for Javascripts.
* @var string
* @access public
* @since 1.0.0
*/
public $script_suffix;
/**
* Constructor function.
* @access public
* @since 1.0.0
* @return void
*/
public function __construct($file = ”, $version = ‘1.3.4’)
{
$this->_version = $version;
$this->_token = ‘workscout_freelancer’;
// Load plugin environment variables
$this->file = $file;
$this->dir = dirname($this->file);
$this->assets_dir = trailingslashit($this->dir) . ‘assets’;
$this->assets_url = esc_url(trailingslashit(plugins_url(‘/assets/’, $this->file)));
$this->script_suffix = defined(‘SCRIPT_DEBUG’) && SCRIPT_DEBUG ? ” : ‘.min’;
// register_activation_hook($this->file, array($this, ‘install’));
// add_action(‘wp_enqueue_scripts’, array($this, ‘enqueue_styles’), 10);
add_action(‘after_setup_theme’, array($this, ‘include_template_functions’), 11);
include(‘class-workscout-freelancer-cpt.php’);
//include(‘class-workscout-freelancer-emails.php’);
$this->post_types = WorkScout_Freelancer_CPT::instance();
if (is_admin()) {
include(‘class-workscout-freelancer-admin.php’);
include(‘class-workscout-freelancer-settings.php’);
include(‘class-workscout-freelancer-meta-boxes.php’);
$this->writepanels = new WorkScout_Freelancer_Meta_Boxes();
$this->admin = new Workscout_Freelancer_Admin();
}
add_filter(‘template_include’, array($this, ‘listing_templates’));
// Schedule cron jobs
}
public function include_template_functions()
{
include(WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/workscout-freelancer-functions.php’);
}
/**
* Main WorkScout_Freelancer Instance
*
* Ensures only one instance of WorkScout_Freelancer is loaded or can be loaded.
*
* @since 1.0.0
* @static
* @see WorkScout_Freelancer()
* @return Main WorkScout_Freelancer instance
*/
public static function instance($file = ”, $version = ‘1.2.1’)
{
if (is_null(self::$_instance)) {
self::$_instance = new self($file, $version);
}
return self::$_instance;
} // End instance ()
/* handles single listing and archive listing view */
public static function listing_templates($template)
{
$post_type = get_post_type();
$custom_post_types = array(‘task’);
$template_loader = new WorkScout_Freelancer_Template_Loader;
if (in_array($post_type, $custom_post_types)) {
if (is_archive() && !is_author()) {
$template = $template_loader->locate_template(‘archive-‘ . $post_type . ‘.php’);
return $template;
}
if (is_single()) {
$template = $template_loader->locate_template(‘single-‘ . $post_type . ‘.php’);
return $template;
}
}
if (is_tax(‘listing_category’)) {
$template = $template_loader->locate_template(‘archive-job_listings.php’);
}
if (is_post_type_archive(‘listing’)) {
$template = $template_loader->locate_template(‘archive-job_listings.php’);
}
return $template;
}
/**
* Load frontend CSS.
* @access public
* @since 1.0.0
* @return void
*/
public function enqueue_styles()
{
wp_register_style($this->_token . ‘-frontend’, esc_url($this->assets_url) . ‘css/style.css’, array(), $this->_version);
// wp_register_style($this->_token . ‘-frontend-custom’, esc_url($this->assets_url) . ‘css/custom.css’, array(), $this->_version);
wp_enqueue_style($this->_token . ‘-frontend’);
wp_enqueue_style($this->_token . ‘-frontend-custom’);
} // End enqueue_styles ()
}
?>
class-workscout-freelancer-bid.php
<?php
if (!defined(‘ABSPATH’)) exit;
class WorkScout_Freelancer_Bid
{
/**
* The single instance of WorkScout_Freelancer.
* @var object
* @access private
* @since 1.0.0
*/
private static $_instance = null;
/**
* Constructor function.
* @access public
* @since 1.0.0
* @return void
*/
public function __construct($file = ”, $version = ‘1.3.4’)
{
add_action(‘wp_ajax_workscout_task_bid’, array($this, ‘wp_ajax_workscout_task_bid’));
add_action(‘wp_ajax_workscout_update_bid’, array($this, ‘wp_ajax_workscout_update_bid’));
add_action(‘workscout_freelancer_task_dashboard_content_show_bidders’, [$this, ‘show_bidders’]);
add_action(‘wp_ajax_workscout_get_bid_data’, array($this, ‘get_bid_data’));
add_action(‘wp_ajax_workscout_get_bid_data_for_edit’, array($this, ‘get_bid_data_for_edit’));
add_action(‘wp_ajax_workscout_get_bid_data_for_contact’, array($this, ‘get_bid_data_for_contact’));
add_action(‘wp_ajax_workscout_accept_bid_on_task’, array($this, ‘accept_bid_on_task’));
add_action(‘wp’, array($this, ‘bid_handler’));
}
/**
* Handle the bid form
*/
public function bid_handler()
{
global $wpdb;
if (!is_user_logged_in()) {
return;
}
$action_data = null;
if (!empty($_GET[‘remove_bid’])) {
if (!wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘remove_bid’)) {
$action_data = array(
‘error_code’ => 400,
‘error’ => __(‘Bad request’, ‘workscout-freelancer’),
);
} else {
$post_id = absint($_GET[‘remove_bid’]);
$user_id = get_current_user_id();
$bid = get_post($post_id);
if (absint($bid->post_author) !== $user_id) {
throw new Exception(__(‘Invalid Bid’, ‘workscout-freelancer’));
}
wp_trash_post($post_id);
$action_data = array(‘success’ => true);
}
}
if (
null === $action_data
) {
return;
}
if (!empty($_REQUEST[‘wpjm-ajax’]) && !defined(‘DOING_AJAX’)) {
define(‘DOING_AJAX’, true);
}
if (wp_doing_ajax()) {
wp_send_json($action_data, !empty($action_data[‘error_code’]) ? $action_data[‘error_code’] : 200);
} else {
wp_redirect(remove_query_arg(array(‘submit_bid’, ‘remove_bid’, ‘_wpnonce’, ‘wpjm-ajax’)));
}
}
function get_bid_data()
{
$bid_id = sanitize_text_field($_REQUEST[‘bid_id’]);
$bid = get_post($bid_id);
$bid_meta = get_post_meta($bid_id);
$bid_author = $bid->post_author;
$bid_proposal = $bid->post_content;
// $bid_data = array(
// ‘budget’ => $bid_meta[‘_bid_budget’][0],
// ‘time’ => $bid_meta[‘_bid_time’][0],
// ‘scale’ => $bid_meta[‘_bid_time_scale’][0],
// );
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$currency_symbol = get_workscout_currency_symbol();
$bid_data = ”;
if (
$currency_position == ‘before’
) {
$bid_data .= $currency_symbol;
}
$bid_data .= $bid_meta[‘_budget’][0];
if (
$currency_position == ‘after’
) {
$bid_data .= $currency_symbol;
}
$bid_data .= ‘ in ‘;
$bid_data .= $bid_meta[‘_time’][0];
$bid_data .= ‘ days’;
$popup_data = array(
‘title’ => esc_html__(“Accept offer from “, ‘workscout-freelancer’) . workscout_get_users_name($bid_author),
‘content’ => $bid_data,
‘proposal’ => $bid_proposal,
‘bid_id’ => $bid_id,
‘task_id’ => $bid->post_parent,
);
$result = json_encode($popup_data);
echo $result;
die();
}
function get_bid_data_for_edit()
{
$bid_id = sanitize_text_field($_REQUEST[‘bid_id’]);
$bid = get_post($bid_id);
//$task = get_post($bid->post_parent);
$bid_author = $bid->post_author;
$bid_proposal = $bid->post_content;
$range = workscout_get_task_range($bid->post_parent);
$popup_data = array(
‘task_type’ => get_post_meta($bid->post_parent, ‘_task_type’, true),
‘budget’ => get_post_meta($bid->ID, ‘_budget’, true),
‘time’ => get_post_meta($bid->ID, ‘_time’, true),
‘range_min’ => $range[‘min’],
‘range_max’ => $range[‘max’],
‘slider_step’ => $range[‘step’],
‘proposal’ => $bid_proposal,
‘bid_id’ => $bid_id,
‘task_id’ => $bid->post_parent,
);
$result = json_encode($popup_data);
echo $result;
die();
}
function get_bid_data_for_contact()
{
$task = sanitize_text_field($_REQUEST[‘task_id’]);
if (empty($task)) {
wp_send_json_error();
}
$bid_id = get_post_meta($task, ‘_selected_bid_id’, true);
$bid = get_post($bid_id);
$bid_author = $bid->post_author;
$bid_author_date = get_userdata($bid_author);
$bid_proposal = $bid->post_content;
$bid_data = array(
‘budget’ => get_post_meta($bid->ID, ‘_budget’, true),
‘time’ => get_post_meta($bid->ID, ‘_time’, true),
‘proposal’ => $bid_proposal,
);
ob_start();
?>
<p> <?php esc_html_e(‘You have selected’, ‘workscout-freelancer’); ?> <strong><a href=”<?php echo get_author_posts_url($bid_author); ?>”><?php echo workscout_get_users_name($bid_author); ?></a></strong> <?php esc_html_e(‘for this task’, ‘workscout-freelancer’); ?></p>
<div class=”bidding-detail margin-top-20″>
<strong><?php esc_html_e(‘Budget: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo get_workscout_currency_symbol(); ?><?php echo $bid_data[‘budget’]; ?>
</div>
<div class=”bidding-detail margin-top-20″>
<strong><?php esc_html_e(‘Time: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo $bid_data[‘time’]; ?> days
</div>
<div class=”bidding-detail margin-top-20″>
<strong><?php esc_html_e(‘Proposal: ‘, ‘workscout-freelancer’); ?></strong>
<div class=”bid-proposal-text”><?php echo $bid_data[‘proposal’]; ?></div>
</div>
<p>You can contact him via Messages or using his email: <strong><?php echo ($bid_author_date->user_email); ?></strong></p>
<?php $message = ob_get_clean();
$return = array(
‘message’ => $message,
);
wp_send_json($return);
}
function accept_bid_on_task()
{
$bid_id = sanitize_text_field($_REQUEST[‘bid_id’]);
$task_id = sanitize_text_field($_REQUEST[‘task_id’]);
$bid = get_post($bid_id);
//
if ($task_id == $bid->post_parent) {
// set task statu “in progress”
$update_task = [
‘ID’ => $task_id,
‘post_status’ => ‘in_progress’,
];
$update = wp_update_post($update_task);
update_post_meta($task_id, ‘_selected_bid_id’, $bid_id);
update_post_meta($bid_id, ‘_selected_for_task_id’, $task_id);
//set all other bids as closed
$args = array(
‘post_type’ => ‘bid’,
‘post_status’ => ‘publish’,
‘posts_per_page’ => -1,
‘post_parent’ => $task_id,
‘post__not_in’ => array($bid_id),
);
$bids = get_posts($args);
foreach ($bids as $bid) {
$update_bid = [
‘ID’ => $bid->ID,
‘post_status’ => ‘closed’,
];
$update = wp_update_post($update_bid);
}
//$update = true;
if ($update) {
$result[‘type’] = ‘success’;
$result[‘message’] = __(‘You have successfully choosed a bidder’, ‘workscout-freelancer’);
// create a project
$project_id = $this->create_project($task_id);
if ($project_id) {
$redirect_url = add_query_arg(array(‘action’ => ‘view-project’, ‘task_id’ => $task_id, ‘project_id’ => $project_id), get_permalink(get_option(‘workscout_freelancer_task_dashboard_page_id’)));
if ($redirect_url) {
$result[‘redirect’] = $redirect_url;
} else {
error_log(‘Failed to get permalink for project ID: ‘ . $project_id);
}
} else {
error_log(‘Failed to create project for task ID: ‘ . $task_id);
}
} else {
$result[‘type’] = ‘error’;
$result[‘message’] = __(‘Error, please try again or contact support’, ‘workscout-freelancer’);
}
} else {
$result[‘type’] = ‘error’;
$result[‘message’] = __(‘Error, please try again or contact support’, ‘workscout-freelancer’);
}
wp_send_json($result);
}
// create a new post type project and copy content from task
public function create_project($task_id){
$task = get_post($task_id);
$project_data = array(
‘post_title’ => $task->post_title,
‘post_content’ => $task->post_content,
‘post_status’ => ‘publish’,
‘post_type’ => ‘project’,
‘post_author’ => $task->post_author,
);
$project_id = wp_insert_post($project_data);
if ($project_id) {
update_post_meta($task_id, ‘_project_id’, $project_id);
update_post_meta($project_id, ‘_task_id’, $task_id);
$selected_bid_id = get_post_meta($task_id, ‘_selected_bid_id’, true);
update_post_meta($project_id, ‘_selected_bid_id’, $selected_bid_id);
// get id of author of the selected bid
$bid = get_post($selected_bid_id);
$_freelancer_id = $bid->post_author;
update_post_meta($project_id, ‘_freelancer_id’, $_freelancer_id);
update_post_meta($project_id, ‘_employer_id’, $task->post_author);
update_post_meta($project_id, ‘_project_status’, ‘in_progress’);
update_post_meta($project_id, ‘_project_start_date’, current_time(‘mysql’));
// budget
$budget = get_post_meta($selected_bid_id, ‘_budget’, true);
update_post_meta($project_id, ‘_budget’, $budget);
// copy attachments
$attachments = get_posts(array(
‘post_type’ => ‘attachment’,
‘posts_per_page’ => -1,
‘post_parent’ => $task_id,
));
if ($attachments) {
foreach ($attachments as $attachment) {
$attachment_data = array(
‘post_title’ => $attachment->post_title,
‘post_content’ => $attachment->post_content,
‘post_status’ => ‘inherit’,
‘post_type’ => ‘attachment’,
‘post_author’ => $attachment->post_author,
‘post_parent’ => $project_id,
);
$attachment_id = wp_insert_post($attachment_data);
if ($attachment_id) {
update_post_meta($attachment_id, ‘_wp_attached_file’, get_post_meta($attachment->ID, ‘_wp_attached_file’, true));
update_post_meta($attachment_id, ‘_wp_attachment_metadata’, get_post_meta($attachment->ID, ‘_wp_attachment_metadata’, true));
}
}
}
// copy meta
$meta = get_post_meta($task_id);
if ($meta) {
foreach ($meta as $key => $value) {
update_post_meta($project_id, $key, $value[0]);
}
}
do_action(‘workscout_freelancer_new_project_created’, $project_id);
return $project_id;
} else {
return false;
}
}
/**
* Show applications on the job dashboard
*/
public function show_bidders($atts)
{
$task_id = absint($_REQUEST[‘task_id’]);
$task = get_post($task_id);
extract(
shortcode_atts(
[
‘posts_per_page’ => ’20’,
],
$atts
)
);
// remove_filter(‘the_title’, [$this, ‘add_breadcrumb_to_the_title’]);
// Permissions
if (!workscout_freelancer_user_can_edit_task($task_id)) {
_e(‘You do not have permission to view this task.’, ‘workscout-freelancer’);
return;
}
$args = apply_filters(
‘workscout_freelancer_task_bidders_args’,
[
‘post_type’ => ‘bid’,
‘post_status’ => [‘publish’],
‘ignore_sticky_posts’ => 1,
‘posts_per_page’ => $posts_per_page,
‘offset’ => (max(1, get_query_var(‘paged’)) – 1) * $posts_per_page,
‘post_parent’ => $task_id,
]
);
// Filters
// $application_status = !empty($_GET[‘application_status’]) ? sanitize_text_field($_GET[‘application_status’]) : ”;
// $application_orderby = !empty($_GET[‘application_orderby’]) ? sanitize_text_field($_GET[‘application_orderby’]) : ”;
// if ($application_status) {
// $args[‘post_status’] = $application_status;
// }
// switch ($application_orderby) {
// case ‘name’:
// $args[‘order’] = ‘ASC’;
// $args[‘orderby’] = ‘post_title’;
// break;
// case ‘rating’:
// $args[‘order’] = ‘DESC’;
// $args[‘orderby’] = ‘meta_value’;
// $args[‘meta_key’] = ‘_rating’;
// break;
// default:
// $args[‘order’] = ‘DESC’;
// $args[‘orderby’] = ‘date’;
// break;
// }
$bids = new WP_Query();
$columns = apply_filters(
‘job_manager_job_applications_columns’,
[
‘name’ => __(‘Name’, ‘workscout-freelancer’),
’email’ => __(‘Email’, ‘workscout-freelancer’),
‘date’ => __(‘Date Received’, ‘workscout-freelancer’),
]
);
get_job_manager_template(
‘task-bids.php’,
[
‘bids’ => $bids->query($args),
‘task_id’ => $task_id,
‘max_num_pages’ => $bids->max_num_pages,
‘columns’ => $columns,
// ‘application_status’ => $application_status,
// ‘application_orderby’ => $application_orderby,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
}
public function wp_ajax_workscout_task_bid()
{
$id = sanitize_text_field($_REQUEST[‘task_id’]);
$data = array(
‘budget’ => sanitize_text_field($_REQUEST[‘budget’]),
‘time’ => sanitize_text_field($_REQUEST[‘time’]),
‘proposal’ => sanitize_textarea_field($_REQUEST[‘proposal’]),
);
$user_id = get_current_user_id();
// check if user can bid on this task
$can_bid = workscout_freelancer_user_can_bid($id);
if ($can_bid) {
$this->create_bid($id, $user_id, $data);
$result[‘type’] = ‘success’;
$result[‘message’] = __(‘Your bid was successfully sent’, ‘workscout-freelancer’);
} else {
$result[‘type’] = ‘error’;
$result[‘message’] = __(‘You can\’t bid on this task’, ‘workscout-freelancer’);
}
$result = json_encode($result);
echo $result;
die();
}
public function wp_ajax_workscout_update_bid()
{
$bid_id = sanitize_text_field($_REQUEST[‘bid_id’]);
$data = array(
‘budget’ => sanitize_text_field($_REQUEST[‘budget’]),
‘time’ => sanitize_text_field($_REQUEST[‘time’]),
‘proposal’ => sanitize_textarea_field($_REQUEST[‘proposal’]),
‘bid_id’ => $bid_id,
);
$user_id = get_current_user_id();
// check if user can bid on this task
$can_bid = workscout_freelancer_user_can_bid($_REQUEST[‘bid_id’]);
if ($can_bid) {
$this->update_bid($bid_id, $user_id, $data);
$result[‘type’] = ‘success’;
$result[‘message’] = __(‘Your bid was successfully updated’, ‘workscout-freelancer’);
} else {
$result[‘type’] = ‘error’;
$result[‘message’] = __(‘You can\’ update this bid’, ‘workscout-freelancer’);
}
$result = json_encode($result);
echo $result;
die();
}
function create_bid($task_id, $freelancer_id, $data = [])
{
$task = get_post($task_id);
if (
!$task || $task->post_type !== ‘task’
) {
return false;
}
$bid_title = get_the_title($task_id) . ‘-‘ . $freelancer_id;
$bid_data = [
‘post_title’ => wp_kses_post($bid_title),
‘post_content’ => wp_kses_post($data[‘proposal’]),
‘post_type’ => ‘bid’,
‘post_status’ => ‘publish’,
‘comment_status’ => ‘closed’,
‘post_author’ => $freelancer_id,
‘post_parent’ => $task_id,
];
$bid_id = wp_insert_post($bid_data);
if ($bid_id) {
update_post_meta($bid_id, ‘_budget’, $data[‘budget’]);
update_post_meta($bid_id, ‘_time’, $data[‘time’]);
return $bid_id;
}
return false;
}
function update_bid($bid_id, $freelancer_id, $data = [])
{
$bid_data = [
‘ID’ => $data[‘bid_id’],
‘post_content’ => wp_kses_post($data[‘proposal’]),
‘post_type’ => ‘bid’,
‘post_status’ => ‘publish’,
‘comment_status’ => ‘closed’,
‘post_author’ => $freelancer_id,
];
$bid_id = wp_update_post($bid_data);
if ($bid_id) {
update_post_meta($bid_id, ‘_budget’, $data[‘budget’]);
update_post_meta($bid_id, ‘_time’, $data[‘time’]);
return $bid_id;
}
return false;
}
/**
* Main WorkScout_Freelancer Instance
*
* Ensures only one instance of WorkScout_Freelancer is loaded or can be loaded.
*
* @since 1.0.0
* @static
* @see WorkScout_Freelancer()
* @return Main WorkScout_Freelancer instance
*/
public static function instance($file = ”, $version = ‘1.2.1’)
{
if (is_null(self::$_instance)) {
self::$_instance = new self($file, $version);
}
return self::$_instance;
} // End instance ()
}
class-workscout-freelancer-cpt.php
<?php
// Exit if accessed directly
if (!defined(‘ABSPATH’))
exit;
/**
* Hireo class.
*/
class WorkScout_Freelancer_CPT
{
/**
* The single instance of the class.
*
* @var self
* @since 1.26
*/
private static $_instance = null;
/**
* Allows for accessing single instance of class. Class should only be constructed once per call.
*
* @since 1.26
* @static
* @return self Main instance.
*/
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Constructor
*/
public function __construct()
{
add_action(‘init’, array($this, ‘register_task_post_types’), 5);
add_action(‘init’, array($this, ‘register_bid_post_types’), 5);
add_action(‘init’, array($this, ‘register_project_post_types’), 5);
add_action(‘workscout_freelancer_check_for_expired_tasks’, array($this, ‘workscout_freelancer_check_for_expired_tasks’));
add_action(‘manage_task_posts_custom_column’, array($this, ‘custom_columns’), 2);
add_filter(‘manage_edit-task_columns’, array($this, ‘columns’));
// add_filter(‘manage_edit-task_sortable_columns’, array($this, ‘sortable_columns’));
// add_action(‘pre_get_posts’, array($this, ‘sort_columns_query’));
add_action(‘admin_init’, array($this, ‘approve_task’));
add_action(‘admin_notices’, array($this, ‘action_notices’));
}
/**
* Set default featured value.
*
* @since 1.25.0
*
* @param int $post_id Post ID.
*/
function set_default_featured($post_id)
{
add_post_meta($post_id, ‘_featured’, ‘0’, true);
}
/**
* Get the permalink settings directly from the option.
*
* @return array Permalink settings option.
*/
public static function get_raw_permalink_settings()
{
/**
* Option `wpjm_permalinks` was renamed to match other options in 1.32.0.
*
* Reference to the old option and support for non-standard plugin updates will be removed in 1.34.0.
*/
$legacy_permalink_settings = ‘[]’;
if (false !== get_option(‘wsf_permalinks’, false)) {
$legacy_permalink_settings = wp_json_encode(get_option(‘wsf_permalinks’, array()));
delete_option(‘wsf_permalinks’);
}
return (array) json_decode(get_option(‘wsf_core_task_permalinks’, $legacy_permalink_settings), true);
}
/**
* Retrieves permalink settings.
*
* @see https://github.com/woocommerce/woocommerce/blob/3.0.8/includes/wc-core-functions.php#L1573
* @since 1.28.0
* @return array
*/
public static function get_permalink_structure()
{
// Switch to the site’s default locale, bypassing the active user’s locale.
if (function_exists(‘switch_to_locale’) && did_action(‘admin_init’)) {
switch_to_locale(get_locale());
}
$permalink_settings = self::get_raw_permalink_settings();
// First-time activations will get this cleared on activation.
if (!array_key_exists(‘tasks_archive’, $permalink_settings)) {
// Create entry to prevent future checks.
$permalink_settings[‘tasks_archive’] = ”;
// This isn’t the first activation and the theme supports it. Set the default to legacy value.
$permalink_settings[‘tasks_archive’] = _x(‘tasks’, ‘Post type archive slug – resave permalinks after changing this’, ‘workscout-freelancer’);
update_option(‘wsf_task_permalinks’, wp_json_encode($permalink_settings));
}
$permalinks = wp_parse_args(
$permalink_settings,
array(
‘task_base’ => ”,
‘task_category_base’ => ”,
‘tasks_archive’ => ”,
)
);
// Ensure rewrite slugs are set. Use legacy translation options if not.
$permalinks[‘task_rewrite_slug’] = untrailingslashit(empty($permalinks[‘task_base’]) ? _x(‘task’, ‘Task permalink – resave permalinks after changing this’, ‘workscout-freelancer’) : $permalinks[‘task_base’]);
$permalinks[‘task_category_rewrite_slug’] = untrailingslashit(empty($permalinks[‘task_category_base’]) ? _x(‘task-category’, ‘Task Listing category slug – resave permalinks after changing this’, ‘workscout-freelancer’) : $permalinks[‘category_base’]);
$permalinks[‘tasks_archive_rewrite_slug’] = untrailingslashit(empty($permalinks[‘tasks_archive’]) ? ‘tasks’ : $permalinks[‘tasks_archive’]);
// Restore the original locale.
if (function_exists(‘restore_current_locale’) && did_action(‘admin_init’)) {
restore_current_locale();
}
return $permalinks;
}
/**
* register_post_types function.
*
* @access public
* @return void
*/
public function register_task_post_types()
{
/*
if ( post_type_exists( “task” ) )
return;*/
// Custom admin capability
$admin_capability = ‘edit_listing’;
$permalink_structure = self::get_permalink_structure();
// Set labels and localize them
$task_name = apply_filters(‘wsf_cpt_task_name’, __(‘Tasks’, ‘workscout-freelancer’));
$task_singular = apply_filters(‘wsf_cpt_task_singular’, __(‘Task’, ‘workscout-freelancer’));
register_post_type(
“task”,
apply_filters(“register_post_type_task”, array(
‘labels’ => array(
‘name’ => $task_name,
‘singular_name’ => $task_singular,
‘menu_name’ => esc_html__(‘Tasks’, ‘workscout-freelancer’),
‘all_items’ => sprintf(esc_html__(‘All %s’, ‘workscout-freelancer’), $task_name),
‘add_new’ => esc_html__(‘Add New’, ‘workscout-freelancer’),
‘add_new_item’ => sprintf(esc_html__(‘Add %s’, ‘workscout-freelancer’), $task_singular),
‘edit’ => esc_html__(‘Edit’, ‘workscout-freelancer’),
‘edit_item’ => sprintf(esc_html__(‘Edit %s’, ‘workscout-freelancer’), $task_singular),
‘new_item’ => sprintf(esc_html__(‘New %s’, ‘workscout-freelancer’), $task_singular),
‘view’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $task_singular),
‘view_item’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $task_singular),
‘search_items’ => sprintf(esc_html__(‘Search %s’, ‘workscout-freelancer’), $task_name),
‘not_found’ => sprintf(esc_html__(‘No %s found’, ‘workscout-freelancer’), $task_name),
‘not_found_in_trash’ => sprintf(esc_html__(‘No %s found in trash’, ‘workscout-freelancer’), $task_name),
‘parent’ => sprintf(esc_html__(‘Parent %s’, ‘workscout-freelancer’), $task_singular),
),
‘description’ => sprintf(esc_html__(‘This is where you can create and manage %s.’, ‘workscout-freelancer’), $task_name),
‘public’ => true,
‘show_ui’ => true,
‘show_in_rest’ => true,
‘capability_type’ => array(‘job_listing’, ‘job_listings’),
‘map_meta_cap’ => true,
‘publicly_queryable’ => true,
‘exclude_from_search’ => false,
‘hierarchical’ => false,
‘menu_icon’ => ‘dashicons-clipboard’,
‘rewrite’ => array(
‘slug’ => $permalink_structure[‘task_rewrite_slug’],
‘with_front’ => true,
‘feeds’ => true,
‘pages’ => true
),
‘query_var’ => true,
‘supports’ => array(‘title’, ‘author’, ‘editor’, ‘excerpt’, ‘custom-fields’, ‘publicize’, ‘thumbnail’, ‘comments’),
‘has_archive’ => $permalink_structure[‘tasks_archive_rewrite_slug’],
‘show_in_nav_menus’ => true
))
);
register_post_status(‘preview’, array(
‘label’ => _x(‘Preview’, ‘post status’, ‘workscout-freelancer’),
‘public’ => false,
‘exclude_from_search’ => true,
‘show_in_admin_all_list’ => true,
‘show_in_admin_status_list’ => true,
‘label_count’ => _n_noop(‘Preview <span class=”count”>(%s)</span>’, ‘Preview <span class=”count”>(%s)</span>’, ‘workscout-freelancer’),
));
register_post_status(‘expired’, array(
‘label’ => _x(‘Expired’, ‘post status’, ‘workscout-freelancer’),
‘public’ => false,
‘protected’ => true,
‘exclude_from_search’ => true,
‘show_in_admin_all_list’ => true,
‘show_in_admin_status_list’ => true,
‘label_count’ => _n_noop(‘Expired <span class=”count”>(%s)</span>’, ‘Expired <span class=”count”>(%s)</span>’, ‘workscout-freelancer’),
));
register_post_status(‘pending_payment’, array(
‘label’ => _x(‘Pending Payment’, ‘post status’, ‘workscout-freelancer’),
‘public’ => false,
‘exclude_from_search’ => false,
‘show_in_admin_all_list’ => false,
‘show_in_admin_status_list’ => true,
‘label_count’ => _n_noop(‘Pending Payment <span class=”count”>(%s)</span>’, ‘Pending Payment <span class=”count”>(%s)</span>’, ‘workscout-freelancer’),
));
register_post_status(‘in_progress’, array(
‘label’ => _x(‘In progress’, ‘post status’, ‘workscout-freelancer’),
‘public’ => true,
‘exclude_from_search’ => true,
‘show_in_admin_all_list’ => true,
‘show_in_admin_status_list’ => true,
‘label_count’ => _n_noop(‘In progress <span class=”count”>(%s)</span>’, ‘In Progress <span class=”count”>(%s)</span>’, ‘workscout-freelancer’),
));
register_post_status(‘completed’, array(
‘label’ => _x(‘Completed’, ‘post status’, ‘workscout-freelancer’),
‘public’ => true,
‘exclude_from_search’ => true,
‘show_in_admin_all_list’ => true,
‘show_in_admin_status_list’ => true,
‘label_count’ => _n_noop(‘Completed <span class=”count”>(%s)</span>’, ‘Completed <span class=”count”>(%s)</span>’, ‘workscout-freelancer’),
));
// Register taxonomy “Job Listing Categry”
$singular = __(‘Task Category’, ‘workscout-freelancer’);
$plural = __(‘Task Categories’, ‘workscout-freelancer’);
$rewrite = array(
‘slug’ => $permalink_structure[‘task_category_rewrite_slug’],
‘with_front’ => false,
‘hierarchical’ => false
);
$public = true;
register_taxonomy(
“task_category”,
apply_filters(‘register_taxonomy_task_category_object_type’, array(‘task’)),
apply_filters(‘register_taxonomy_task_category_args’, array(
‘hierarchical’ => true,
/*’update_count_callback’ => ‘_update_post_term_count’,*/
‘label’ => $plural,
‘show_in_rest’ => true,
‘labels’ => array(
‘name’ => $plural,
‘singular_name’ => $singular,
‘menu_name’ => ucwords($plural),
‘search_items’ => sprintf(__(‘Search %s’, ‘workscout-freelancer’), $plural),
‘all_items’ => sprintf(__(‘All %s’, ‘workscout-freelancer’), $plural),
‘parent_item’ => sprintf(__(‘Parent %s’, ‘workscout-freelancer’), $singular),
‘parent_item_colon’ => sprintf(__(‘Parent %s:’, ‘workscout-freelancer’), $singular),
‘edit_item’ => sprintf(__(‘Edit %s’, ‘workscout-freelancer’), $singular),
‘update_item’ => sprintf(__(‘Update %s’, ‘workscout-freelancer’), $singular),
‘add_new_item’ => sprintf(__(‘Add New %s’, ‘workscout-freelancer’), $singular),
‘new_item_name’ => sprintf(__(‘New %s Name’, ‘workscout-freelancer’), $singular)
),
‘show_ui’ => true,
‘show_tagcloud’ => false,
‘public’ => $public,
/*’capabilities’ => array(
‘manage_terms’ => $admin_capability,
‘edit_terms’ => $admin_capability,
‘delete_terms’ => $admin_capability,
‘assign_terms’ => $admin_capability,
),*/
‘rewrite’ => $rewrite,
))
);
// Register taxonomy “Features”
$singular = __(‘Task Skill’, ‘workscout-freelancer’);
$plural = __(‘Task Skill’, ‘workscout-freelancer’);
$rewrite = array(
‘slug’ => _x(‘task-skill’, ‘Task Skills slug – resave permalinks after changing this’, ‘workscout-freelancer’),
‘with_front’ => false,
‘hierarchical’ => false
);
$public = true;
register_taxonomy(
“task_skill”,
apply_filters(‘register_taxonomy_task_types_object_type’, array(‘task’)),
apply_filters(‘register_taxonomy_task_types_args’, array(
‘hierarchical’ => true,
/*’update_count_callback’ => ‘_update_post_term_count’,*/
‘label’ => $plural,
‘labels’ => array(
‘name’ => $plural,
‘singular_name’ => $singular,
‘menu_name’ => ucwords($plural),
‘search_items’ => sprintf(__(‘Search %s’, ‘workscout-freelancer’), $plural),
‘all_items’ => sprintf(__(‘All %s’, ‘workscout-freelancer’), $plural),
‘parent_item’ => sprintf(__(‘Parent %s’, ‘workscout-freelancer’), $singular),
‘parent_item_colon’ => sprintf(__(‘Parent %s:’, ‘workscout-freelancer’), $singular),
‘edit_item’ => sprintf(__(‘Edit %s’, ‘workscout-freelancer’), $singular),
‘update_item’ => sprintf(__(‘Update %s’, ‘workscout-freelancer’), $singular),
‘add_new_item’ => sprintf(__(‘Add New %s’, ‘workscout-freelancer’), $singular),
‘new_item_name’ => sprintf(__(‘New %s Name’, ‘workscout-freelancer’), $singular)
),
‘show_ui’ => true,
‘show_in_rest’ => true,
‘show_tagcloud’ => false,
‘public’ => $public,
/*’capabilities’ => array(
‘manage_terms’ => $admin_capability,
‘edit_terms’ => $admin_capability,
‘delete_terms’ => $admin_capability,
‘assign_terms’ => $admin_capability,
),*/
‘rewrite’ => $rewrite,
))
);
// Register taxonomy “Features”
} /* eof register*/
public function register_project_post_types()
{
/*
if ( post_type_exists( “task” ) )
return;*/
// Custom admin capability
$admin_capability = ‘edit_listing’;
$permalink_structure = self::get_permalink_structure();
// Set labels and localize them
$project_name = apply_filters(‘wsf_cpt_project_name’, __(‘Projects’, ‘workscout-freelancer’));
$project_singular = apply_filters(‘wsf_cpt_project_singular’, __(‘Project’, ‘workscout-freelancer’));
register_post_type(
“project”,
apply_filters(“register_post_type_project”, array(
‘labels’ => array(
‘name’ => $project_name,
‘singular_name’ => $project_singular,
‘menu_name’ => esc_html__(‘Projects’, ‘workscout-freelancer’),
‘all_items’ => sprintf(esc_html__(‘All %s’, ‘workscout-freelancer’), $project_name),
‘add_new’ => esc_html__(‘Add New’, ‘workscout-freelancer’),
‘add_new_item’ => sprintf(esc_html__(‘Add %s’, ‘workscout-freelancer’), $project_singular),
‘edit’ => esc_html__(‘Edit’, ‘workscout-freelancer’),
‘edit_item’ => sprintf(esc_html__(‘Edit %s’, ‘workscout-freelancer’), $project_singular),
‘new_item’ => sprintf(esc_html__(‘New %s’, ‘workscout-freelancer’), $project_singular),
‘view’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $project_singular),
‘view_item’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $project_singular),
‘search_items’ => sprintf(esc_html__(‘Search %s’, ‘workscout-freelancer’), $project_name),
‘not_found’ => sprintf(esc_html__(‘No %s found’, ‘workscout-freelancer’), $project_name),
‘not_found_in_trash’ => sprintf(esc_html__(‘No %s found in trash’, ‘workscout-freelancer’), $project_name),
‘parent’ => sprintf(esc_html__(‘Parent %s’, ‘workscout-freelancer’), $project_singular),
),
‘description’ => sprintf(esc_html__(‘This is where you can create and manage %s.’, ‘workscout-freelancer’), $project_name),
‘public’ => false,
‘show_ui’ => true,
‘show_in_rest’ => true,
‘capability_type’ => array(‘job_listing’, ‘job_listings’),
‘map_meta_cap’ => true,
‘publicly_queryable’ => false,
‘exclude_from_search’ => false,
‘hierarchical’ => false,
‘menu_icon’ => ‘dashicons-clipboard’,
‘rewrite’ => array(
‘slug’ => ‘project’,
‘with_front’ => false,
‘feeds’ => true,
‘pages’ => true
),
‘query_var’ => true,
‘supports’ => array(‘title’, ‘author’, ‘editor’, ‘excerpt’, ‘custom-fields’, ‘publicize’, ‘thumbnail’, ‘comments’),
‘has_archive’ => false,
‘show_in_nav_menus’ => true
))
);
}
/**
* register_post_types function.
*
* @access public
* @return void
*/
public function register_bid_post_types()
{
/*
if ( post_type_exists( “task” ) )
return;*/
// Custom admin capability
$admin_capability = ‘edit_listing’;
$permalink_structure = self::get_permalink_structure();
// Set labels and localize them
$bid_name = apply_filters(‘wsf_cpt_bid_name’, __(‘Bids’, ‘workscout-freelancer’));
$bid_singular = apply_filters(‘wsf_cpt_bid_singular’, __(‘Bid’, ‘workscout-freelancer’));
register_post_type(
“bid”,
apply_filters(“register_post_type_task”, array(
‘labels’ => array(
‘name’ => $bid_name,
‘singular_name’ => $bid_singular,
‘menu_name’ => esc_html__(‘Bids’, ‘workscout-freelancer’),
‘all_items’ => sprintf(esc_html__(‘All %s’, ‘workscout-freelancer’), $bid_name),
‘add_new’ => esc_html__(‘Add New’, ‘workscout-freelancer’),
‘add_new_item’ => sprintf(esc_html__(‘Add %s’, ‘workscout-freelancer’), $bid_singular),
‘edit’ => esc_html__(‘Edit’, ‘workscout-freelancer’),
‘edit_item’ => sprintf(esc_html__(‘Edit %s’, ‘workscout-freelancer’), $bid_singular),
‘new_item’ => sprintf(esc_html__(‘New %s’, ‘workscout-freelancer’), $bid_singular),
‘view’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $bid_singular),
‘view_item’ => sprintf(esc_html__(‘View %s’, ‘workscout-freelancer’), $bid_singular),
‘search_items’ => sprintf(esc_html__(‘Search %s’, ‘workscout-freelancer’), $bid_name),
‘not_found’ => sprintf(esc_html__(‘No %s found’, ‘workscout-freelancer’), $bid_name),
‘not_found_in_trash’ => sprintf(esc_html__(‘No %s found in trash’, ‘workscout-freelancer’), $bid_name),
‘parent’ => sprintf(esc_html__(‘Parent %s’, ‘workscout-freelancer’), $bid_singular),
),
‘description’ => sprintf(esc_html__(‘This is where you can create and manage %s.’, ‘workscout-freelancer’), $bid_name),
‘public’ => true,
‘show_ui’ => true,
‘show_in_rest’ => true,
‘capability_type’ => array(‘job_listing’, ‘job_listings’),
‘map_meta_cap’ => true,
‘publicly_queryable’ => true,
‘exclude_from_search’ => true,
‘hierarchical’ => false,
‘menu_icon’ => ‘dashicons-clipboard’,
‘query_var’ => true,
‘supports’ => array(‘title’, ‘author’, ‘editor’, ‘custom-fields’, ‘publicize’, ‘thumbnail’, ‘comments’),
‘has_archive’ => false,
‘show_in_nav_menus’ => true
))
);
} /* eof register*/
/**
* Adds columns to admin task of task Job Listings.
*
* @param array $columns
* @return array
*/
public function columns($columns)
{
if (!is_array($columns)) {
$columns = array();
}
// unset the column for comments count
unset($columns[‘comments’]);
$columns[“task_type”] = __(“Type”, ‘workscout-freelancer’);
$columns[“task_posted”] = __(“Posted”, ‘workscout-freelancer’);
$columns[“expires”] = __(“Expires”, ‘workscout-freelancer’);
$columns[‘featured_task’] = ‘<span class=”tips” data-tip=”‘ . __(“Featured?”, ‘workscout-freelancer’) . ‘”>’ . __(“Featured?”, ‘workscout-freelancer’) . ‘</span>’;
$columns[‘task_actions’] = __(“Actions”, ‘workscout-freelancer’);
return $columns;
}
/**
* Displays the content for each custom column on the admin list for task Job Listings.
*
* @param mixed $column
*/
public function custom_columns($column)
{
global $post;
switch ($column) {
case “task_type”:
$type = get_post_meta($post->ID, ‘_task_type’, true);
echo $type;
break;
case “expires”:
$expires = get_post_meta($post->ID, ‘_task_expires’, true);
if ((is_numeric($expires) && (int)$expires == $expires && (int)$expires > 0)) {
echo date_i18n(get_option(‘date_format’), $expires);
} else {
echo $expires;
}
break;
case “featured_task”:
if (workscout_core_is_featured($post->ID)) echo ‘✔’;
else echo ‘–’;
break;
case “task_posted”:
echo ‘<strong>’ . date_i18n(__(‘M j, Y’, ‘workscout-freelancer’), strtotime($post->post_date)) . ‘</strong><span>’;
echo (empty($post->post_author) ? __(‘by a guest’, ‘workscout-freelancer’) : sprintf(__(‘by %s’, ‘workscout-freelancer’), ‘<a href=”‘ . esc_url(add_query_arg(‘author’, $post->post_author)) . ‘”>’ . get_the_author() . ‘</a>’)) . ‘</span>’;
break;
case “task_actions”:
echo ‘<div class=”actions”>’;
$admin_actions = apply_filters(‘wsf_post_row_actions’, array(), $post);
if (in_array($post->post_status, array(‘pending’, ‘preview’, ‘pending_payment’)) && current_user_can(‘publish_post’, $post->ID)) {
$admin_actions[‘approve’] = array(
‘action’ => ‘approve’,
‘name’ => __(‘Approve’, ‘workscout-freelancer’),
‘url’ => wp_nonce_url(add_query_arg(‘approve_task’, $post->ID), ‘approve_task’)
);
}
/* if ( $post->post_status !== ‘trash’ ) {
if ( current_user_can( ‘read_post’, $post->ID ) ) {
$admin_actions[‘view’] = array(
‘action’ => ‘view’,
‘name’ => __( ‘View’, ‘workscout-freelancer’),
‘url’ => get_permalink( $post->ID )
);
}
if ( current_user_can( ‘edit_post’, $post->ID ) ) {
$admin_actions[‘edit’] = array(
‘action’ => ‘edit’,
‘name’ => __( ‘Edit’, ‘workscout-freelancer’),
‘url’ => get_edit_post_link( $post->ID )
);
}
if ( current_user_can( ‘delete_post’, $post->ID ) ) {
$admin_actions[‘delete’] = array(
‘action’ => ‘delete’,
‘name’ => __( ‘Delete’, ‘workscout-freelancer’),
‘url’ => get_delete_post_link( $post->ID )
);
}
}*/
$admin_actions = apply_filters(‘task_manager_admin_actions’, $admin_actions, $post);
foreach ($admin_actions as $action) {
if (is_array($action)) {
printf(‘<a class=”button button-icon tips icon-%1$s” href=”%2$s” data-tip=”%3$s”>%4$s</a>’, $action[‘action’], esc_url($action[‘url’]), esc_attr($action[‘name’]), esc_html($action[‘name’]));
} else {
echo str_replace(‘class=”‘, ‘class=”button ‘, $action);
}
}
echo ‘</div>’;
break;
}
}
/**
* Sets expiry date when status changes.
*
* @param WP_Post $post
*/
public function set_expiry($post)
{
if ($post->post_type !== ‘task’) {
return;
}
// See if it is already set
if (get_post_meta($post->ID, ‘_task_expires’, true)) {
$expires = get_post_meta($post->ID, ‘_task_expires’, true);
if ((is_numeric($expires) && (int)$expires == $expires && (int)$expires > 0)) {
//
} else {
$expires = CMB2_Utils::get_timestamp_from_value($expires, ‘m/d/Y’);
}
if ($expires && $expires < current_time(‘timestamp’)) {
update_post_meta($post->ID, ‘_task_expires’, ”);
} else {
update_post_meta($post->ID, ‘_task_expires’, strtotime($expires));
}
}
// See if the user has set the expiry manually:
if (!empty($_POST[‘_task_expires’])) {
$expires = $_POST[‘_task_expires’];
if ((is_numeric($expires) && (int)$expires == $expires && (int)$expires > 0)) {
//
} else {
$expires = CMB2_Utils::get_timestamp_from_value($expires, ‘m/d/Y’);
}
update_post_meta($post->ID, ‘_task_expires’, $expires);
// No manual setting? Lets generate a date if there isn’t already one
} elseif (false == isset($expires)) {
$expires = calculate_task_expiry($post->ID);
update_post_meta($post->ID, ‘_task_expires’, $expires);
// In case we are saving a post, ensure post data is updated so the field is not overridden
if (isset($_POST[‘_task_expires’])) {
$expires = $_POST[‘_task_expires’];
// // if ((is_numeric($expires) && (int)$expires == $expires && (int)$expires > 0)) {
// // //
// // } else {
// // $expires = CMB2_Utils::get_timestamp_from_value($expires, ‘m/d/Y’);
// // }
// $_POST[‘_task_expires’] = $expires;
}
}
}
/**
* Maintenance task to expire tasks.
*/
public function workscout_freelancer_check_for_expired_tasks()
{
global $wpdb;
$date_format = get_option(‘date_format’);
// Change status to expired
$task_ids = $wpdb->get_col($wpdb->prepare(“
SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta
LEFT JOIN {$wpdb->posts} as posts ON postmeta.post_id = posts.ID
WHERE postmeta.meta_key = ‘_task_expires’
AND postmeta.meta_value > 0
AND postmeta.meta_value < %s
AND posts.post_status = ‘publish’
AND posts.post_type = ‘task’
“,
date(‘Y-m-d’, current_time(‘timestamp’))
)
);
if ($task_ids) {
foreach ($task_ids as $task_id) {
$task_data = array();
$task_data[‘ID’] = $task_id;
$task_data[‘post_status’] = ‘expired’;
wp_update_post($task_data);
do_action(‘wsf_expired_task’, $task_id);
}
}
// Notifie expiring in 5 days
$task_ids = $wpdb->get_col($wpdb->prepare(“
SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta
LEFT JOIN {$wpdb->posts} as posts ON postmeta.post_id = posts.ID
WHERE postmeta.meta_key = ‘_task_expires’
AND postmeta.meta_value > 0
AND postmeta.meta_value < %s
AND posts.post_status = ‘publish’
AND posts.post_type = ‘task’
“,
date(‘Y-m-d’, strtotime(‘+5 days’))
)
);
if ($task_ids) {
foreach ($task_ids as $task_id) {
$task_data[‘ID’] = $task_id;
do_action(‘wsf_expiring_soon_task’, $task_id);
}
}
// Delete old expired tasks
if (apply_filters(‘wsf_delete_expired_tasks’, false)) {
$task_ids = $wpdb->get_col($wpdb->prepare(“
SELECT posts.ID FROM {$wpdb->posts} as posts
WHERE posts.post_type = ‘task’
AND posts.post_modified < %s
AND posts.post_status = ‘expired’
“, strtotime(date($date_format, strtotime(‘-‘ . apply_filters(‘wsf_delete_expired_tasks_days’, 30) . ‘ days’, current_time(‘timestamp’))))));
if ($task_ids) {
foreach ($task_ids as $task_id) {
wp_trash_post($task_id);
}
}
}
}
/**
* Adds bulk actions to drop downs on Job Job Listing admin page.
*
* @param array $bulk_actions
* @return array
*/
public function add_bulk_actions($bulk_actions)
{
global $wp_post_types;
foreach ($this->get_bulk_actions() as $key => $bulk_action) {
if (isset($bulk_action[‘label’])) {
$bulk_actions[$key] = sprintf($bulk_action[‘label’], $wp_post_types[‘task’]->labels->name);
}
}
return $bulk_actions;
}
/**
* Performs bulk actions on Job Job Listing admin page.
*
* @since 1.27.0
*
* @param string $redirect_url The redirect URL.
* @param string $action The action being taken.
* @param array $post_ids The posts to take the action on.
*/
public function do_bulk_actions($redirect_url, $action, $post_ids)
{
$actions_handled = $this->get_bulk_actions();
if (isset($actions_handled[$action]) && isset($actions_handled[$action][‘handler’])) {
$handled_jobs = array();
if (!empty($post_ids)) {
foreach ($post_ids as $post_id) {
if (
‘task’ === get_post_type($post_id)
&& call_user_func($actions_handled[$action][‘handler’], $post_id)
) {
$handled_jobs[] = $post_id;
}
}
wp_redirect(add_query_arg(‘handled_jobs’, $handled_jobs, add_query_arg(‘action_performed’, $action, $redirect_url)));
exit;
}
}
}
/**
* Returns the list of bulk actions that can be performed on job tasks.
*
* @return array
*/
public function get_bulk_actions()
{
$actions_handled = array();
$actions_handled[‘approve_tasks’] = array(
‘label’ => __(‘Approve %s’, ‘workscout-freelancer’),
‘notice’ => __(‘%s approved’, ‘workscout-freelancer’),
‘handler’ => array($this, ‘bulk_action_handle_approve_task’),
);
$actions_handled[‘expire_tasks’] = array(
‘label’ => __(‘Expire %s’, ‘workscout-freelancer’),
‘notice’ => __(‘%s expired’, ‘workscout-freelancer’),
‘handler’ => array($this, ‘bulk_action_handle_expire_task’),
);
return apply_filters(‘wsf_bulk_actions’, $actions_handled);
}
/**
* Performs bulk action to approve a single job task.
*
* @param $post_id
*
* @return bool
*/
public function bulk_action_handle_approve_task($post_id)
{
$job_data = array(
‘ID’ => $post_id,
‘post_status’ => ‘publish’,
);
if (
in_array(get_post_status($post_id), array(‘pending’, ‘pending_payment’))
&& current_user_can(‘publish_post’, $post_id)
&& wp_update_post($job_data)
) {
return true;
}
return false;
}
/**
* Performs bulk action to expire a single job task.
*
* @param $post_id
*
* @return bool
*/
public function bulk_action_handle_expire_task($post_id)
{
$job_data = array(
‘ID’ => $post_id,
‘post_status’ => ‘expired’,
);
if (
current_user_can(‘manage_tasks’, $post_id)
&& wp_update_post($job_data)
) {
return true;
}
return false;
}
/**
* Approves a single task.
*/
public function approve_task()
{
if (!empty($_GET[‘approve_task’]) && wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘approve_task’) && current_user_can(‘publish_post’, $_GET[‘approve_task’])) {
$post_id = absint($_GET[‘approve_task’]);
$task_data = array(
‘ID’ => $post_id,
‘post_status’ => ‘publish’
);
wp_update_post($task_data);
wp_redirect(remove_query_arg(‘approve_task’, add_query_arg(‘handled_tasks’, $post_id, add_query_arg(‘action_performed’, ‘approve_tasks’, admin_url(‘edit.php?post_type=task’)))));
exit;
}
}
/**
* Shows a notice if we did a bulk action.
*/
public function action_notices()
{
global $post_type, $pagenow;
$handled_jobs = isset($_REQUEST[‘handled_tasks’]) ? $_REQUEST[‘handled_tasks’] : false;
$action = isset($_REQUEST[‘action_performed’]) ? $_REQUEST[‘action_performed’] : false;
$actions_handled = $this->get_bulk_actions();
if (
$pagenow == ‘edit.php’
&& $post_type == ‘task’
&& $action
&& !empty($handled_jobs)
&& isset($actions_handled[$action])
&& isset($actions_handled[$action][‘notice’])
) {
if (is_array($handled_jobs)) {
$handled_jobs = array_map(‘absint’, $handled_jobs);
$titles = array();
foreach ($handled_jobs as $job_id) {
$titles[] = get_the_title($job_id);
}
echo ‘<div class=”updated”><p>’ . sprintf($actions_handled[$action][‘notice’], ‘"’ . implode(‘", "’, $titles) . ‘"’) . ‘</p></div>’;
} else {
echo ‘<div class=”updated”><p>’ . sprintf($actions_handled[$action][‘notice’], ‘"’ . get_the_title(absint($handled_jobs)) . ‘"’) . ‘</p></div>’;
}
}
}
public function add_icon_column($columns)
{
$columns[‘icon’] = __(‘Icon’, ‘workscout-freelancer’);
return $columns;
}
/**
* Adds the Employment Type column content when task job type terms in WP Admin.
*
* @param string $content
* @param string $column_name
* @param int $term_id
* @return string
*/
public function add_icon_column_content($content, $column_name, $term_id)
{
if (‘icon’ !== $column_name) {
return $content;
}
$term_id = absint($term_id);
$icon = get_term_meta($term_id, ‘icon’, true);
if ($icon) {
$content .= ‘<i style=”font-size:30px;” class=”‘ . $icon . ‘”></i>’;
}
return $content;
}
public function add_assigned_features_column($columns)
{
$columns[‘features’] = __(‘Features’, ‘workscout-freelancer’);
return $columns;
}
public function add_assigned_features_content($content, $column_name, $term_id)
{
if (‘features’ !== $column_name) {
return $content;
}
$term_id = absint($term_id);
$term_meta = get_term_meta($term_id, ‘wsf_taxonomy_multicheck’, true);
if ($term_meta) {
foreach ($term_meta as $feature) {
$feature_obj = get_term_by(‘slug’, $feature, ‘task_feature’);
if ($feature_obj) {
$term_link = get_term_link($feature_obj);
$content .= ‘<a href=”‘ . esc_url($term_link) . ‘”>’ . $feature_obj->name . ‘</a>, ‘;
}
}
$content = substr($content, 0, -2);
}
return $content;
}
public function set_default_avg_rating_new_post($post_ID)
{
$current_field_value = get_post_meta($post_ID, ‘wsf-avg-rating’, true); //change YOUMETAKEY to a default
$default_meta = ‘0’; //set default value
if ($current_field_value == ” && !wp_is_post_revision($post_ID)) {
add_post_meta($post_ID, ‘wsf-avg-rating’, $default_meta, true);
}
return $post_ID;
}
function add_tasks_permastructure()
{
global $wp_rewrite;
$standard_slug = apply_filters(‘wsf_rewrite_task_slug’, ‘task’);
$permalinks = self::get_permalink_structure();
$slug = (isset($permalinks[‘task_base’]) && !empty($permalinks[‘task_base’])) ? $permalinks[‘task_base’] : $standard_slug;
//add_permastruct( ‘region’, $slug.’/%region%’, false );
//add_permastruct( ‘task_category’, $slug.’/%task_category%’, false );
add_permastruct(‘task’, $slug . ‘/%region%/%task_category%/%task%’, false);
}
function task_permalinks($permalink, $post)
{
if ($post->post_type !== ‘task’)
return $permalink;
$regions = get_the_terms($post->ID, ‘region’);
if (!$regions) {
$permalink = str_replace(‘%region%/’, ‘-/’, $permalink);
} else {
$post_regions = array();
foreach ($regions as $region)
$post_regions[] = $region->slug;
$permalink = str_replace(‘%region%’, implode(‘,’, $post_regions), $permalink);
}
$categories = get_the_terms($post->ID, ‘task_category’);
if (!$categories) {
$permalink = str_replace(‘%task_category%/’, ‘-/’, $permalink);
} else {
$post_categories = array();
foreach ($categories as $category)
$post_categories[] = $category->slug;
$permalink = str_replace(‘%task_category%’, implode(‘,’, $post_categories), $permalink);
}
return $permalink;
}
// Make sure that all term links include their parents in the permalinks
function add_term_parents_to_permalinks($permalink, $term)
{
$term_parents = $this->get_term_parents($term);
foreach ($term_parents as $term_parent)
$permlink = str_replace($term->slug, $term_parent->slug . ‘,’ . $term->slug, $permalink);
return $permalink;
}
function get_term_parents($term, &$parents = array())
{
$parent = get_term($term->parent, $term->taxonomy);
if (is_wp_error($parent))
return $parents;
$parents[] = $parent;
if ($parent->parent)
self::get_term_parents($parent, $parents);
return $parents;
}
public function default_comments_on($data)
{
if ($data[‘post_type’] == ‘task’) {
$data[‘comment_status’] = ‘open’;
}
return $data;
}
function save_as_product($post_ID, $post, $update)
{
if (!is_admin()) {
return;
}
if ($post->post_type == ‘task’) {
$product_id = get_post_meta($post_ID, ‘product_id’, true);
// basic task informations will be added to task
$product = array(
‘post_author’ => get_current_user_id(),
‘post_content’ => $post->post_content,
‘post_status’ => ‘publish’,
‘post_title’ => $post->post_title,
‘post_parent’ => ”,
‘post_type’ => ‘product’,
);
// add product if not exist
if (!$product_id || get_post_type($product_id) != ‘product’) {
// insert task as WooCommerce product
$product_id = wp_insert_post($product);
wp_set_object_terms($product_id, ‘task_booking’, ‘product_type’);
} else {
// update existing product
$product[‘ID’] = $product_id;
wp_update_post($product);
}
// set product category
$term = get_term_by(‘name’, apply_filters(‘wsf_default_product_category’, ‘Hireo booking’), ‘product_cat’, ARRAY_A);
if (!$term) $term = wp_insert_term(
apply_filters(‘wsf_default_product_category’, ‘Hireo booking’),
‘product_cat’,
array(
‘description’ => __(‘Task category’, ‘wsf-core’),
‘slug’ => str_replace(‘ ‘, ‘-‘, apply_filters(‘wsf_default_product_category’, ‘Hireo booking’))
)
);
wp_set_object_terms($product_id, $term[‘term_id’], ‘product_cat’);
update_post_meta($post_ID, ‘product_id’, $product_id);
}
}
}
class-workscout-freelancer-emails.php
<?php
// Exit if accessed directly
if (!defined(‘ABSPATH’)) {
exit;
}
/**
* WorkScout_Freelancer_Emails class
*/
class WorkScout_Freelancer_Emails
{
/**
* The single instance of the class.
*
* @var self
* @since 1.0
*/
private static $_instance = null;
private $project;
/**
* Allows for accessing single instance of class. Class should only be constructed once per call.
*
* @since 1.0
* @static
* @return self Main instance.
*/
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct()
{
// Hook into project/milestone events
$this->project = WorkScout_Freelancer_Project::instance();
//about new project
add_action(‘workscout_freelancer_new_project_created’, array($this, ‘new_project’));
//employer bout new milestone
add_action(‘workscout_freelancer_new_milestone_created’, array($this, ‘new_milestone’), 10, 2);
//employer milestone edited notifications
add_action(‘workscout_freelancer_milestone_edited’, array($this, ‘milestone_edited’), 10, 2);
//employer notifications about milestone for review
add_action(‘workscout_freelancer_milestone_for_approval’, array($this, ‘milestone_for_approval’), 10, 2);
//freelancer notifications about milestone completion
add_action(‘workscout_freelancer_milestone_approved’, array($this, ‘milestone_approved’), 10, 3);
//new milestone payment email notifications
add_action(‘workscout_freelancer_order_created’, array($this, ‘order_created’));
// add_action(‘workscout_freelancer_payment_complete’,array(‘$this’,’payment_complete_notification’));
}
//
/**
* New Order Notification
*/
function order_created($order_id)
{
// get option to check if notification is enabled
$notification_data = get_option(‘workscout_freelancer_new_order_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_freelancer_new_order_notification_enable’] != 1) {
return;
}
$order = wc_get_order($order_id);
$project_id = $order->get_meta(‘project_id’);
$milestone_id = $order->get_meta(‘milestone_id’);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$args = array(
‘milestone_id’ => $milestone_id,
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
‘order_id’ => $order_id,
‘order_amount’ => $order->get_total(),
‘project_title’ => get_the_title($project_id),
‘project_url’ => get_permalink($project_id),
);
$subject = $notification_data[‘workscout_freelancer_new_order_subject’];
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_freelancer_new_order_content’];
$body = $this->replace_shortcode($args, $body);
self::send($args[‘user_mail’], $subject, $body);
}
/**
* New Project Notification
*/
function new_project($project_id)
{
$notification_data = get_option(‘workscout_freelancer_new_project_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_freelancer_new_project_notification_enable’] != 1) {
return;
}
$project = get_post($project_id);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$employer_data = get_userdata($employer_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
’employer_name’ => $employer_data->display_name,
‘freelancer_name’ => $freelancer_data->display_name,
‘project_title’ => $project->post_title,
‘project_url’ => get_permalink($project_id),
‘project_budget’ => floatval(get_post_meta($project_id, ‘_budget’, true)),
‘project_description’ => get_post_field(‘post_content’, $project_id),
);
$subject = $notification_data[‘workscout_freelancer_new_project_subject’];
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_freelancer_new_project_content’];
$body = $this->replace_shortcode($args, $body);
self::send($args[‘user_mail’], $subject, $body);
}
/**
* New Milestone Notification
*/
function new_milestone($project_id,$milestone_data)
{
$notification_data = get_option(‘workscout_employer_new_milestone_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_employer_new_milestone_notification_enable’] != 1) {
return;
}
$project_id = $project_id;
$project = get_post($project_id);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$employer_data = get_userdata($employer_id);
$milestone_details = $this->project->get_milestone_details($milestone_data[‘id’], $project_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
’employer_name’ => $employer_data->display_name,
‘freelancer_name’ => $freelancer_data->display_name,
‘project_title’ => $project->post_title,
‘project_url’ => get_permalink($project_id),
‘milestone_title’ => $milestone_details[‘title’],
‘milestone_amount’ => $milestone_details[‘amount’],
);
$subject = $notification_data[‘workscout_employer_new_milestone_subject’];
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_employer_new_milestone_content’];
$body = $this->replace_shortcode($args, $body);
self::send($employer_data->user_email, $subject, $body);
}
function milestone_edited($project_id, $milestone_id)
{
$notification_data = get_option(‘workscout_employer_milestone_edited_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_employer_milestone_edited_notification_enable’] != 1) {
return;
}
$project_id = $project_id;
$project = get_post($project_id);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$employer_data = get_userdata($employer_id);
$milestone_details = $this->project->get_milestone_details($milestone_id, $project_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
’employer_name’ => $employer_data->display_name,
‘freelancer_name’ => $freelancer_data->display_name,
‘project_title’ => $project->post_title,
‘project_url’ => get_permalink($project_id),
‘milestone_title’ => $milestone_details[‘title’],
‘milestone_amount’ => $milestone_details[‘amount’],
);
$subject = $this->replace_shortcode($args, $notification_data[‘workscout_employer_milestone_edited_notification_subject’]);
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_employer_milestone_edited_notification_content’];
$body = $this->replace_shortcode($args, $body);
self::send($employer_data->user_email, $subject, $body);
}
/**
* Milestone Approved Notification
*/
function milestone_approved($project_id, $milestone_id, $order_id)
{
$notification_data = get_option(‘workscout_employer_milestone_approval_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_employer_milestone_approval_notification_enable’] != 1) {
return;
}
$milestone_details = $this->project->get_milestone_details($milestone_id, $project_id);
$freelancer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
// get payment link from order id
if(!$order_id){
return;
}
$order = wc_get_order($order_id);
if(!$order){
return;
}
$payment_link = $order->get_checkout_payment_url();
//$milestone_details = $this->project->get_milestone_details($milestone_id, $project_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
‘milestone_title’ => $milestone_details[‘title’],
‘milestone_amount’ => $milestone_details[‘amount’],
‘project_title’ => get_the_title($project_id),
‘project_url’ => get_permalink($project_id),
‘payment_link’ => $payment_link,
);
$subject = $this->replace_shortcode($args, $notification_data[‘workscout_employer_milestone_approval_subject’]);
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_employer_milestone_approval_content’];
$body = $this->replace_shortcode($args, $body);
self::send($args[‘user_mail’], $subject, $body);
}
/**
* Milestone Approved Notification
*/
function milestone_for_approval($project_id, $milestone_id)
{
$notification_data = get_option(‘workscout_employer_milestone_approval_notification’);
if (is_array($notification_data) && $notification_data[‘workscout_employer_milestone_approval_notification_enable’] != 1) {
return;
}
$project_id = $project_id;
$freelancer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$milestone_data = $this->project->get_milestone_details($milestone_id, $project_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
‘milestone_title’ => $milestone_data[‘title’],
‘milestone_amount’ => $milestone_data[‘amount’],
‘project_title’ => get_the_title($project_id),
‘project_url’ => get_permalink($project_id),
);
$subject = $this->replace_shortcode($args, $notification_data[‘workscout_employer_milestone_approval_subject’]);
$subject = $this->replace_shortcode($args, $subject);
$body = $notification_data[‘workscout_employer_milestone_approval_content’];
$body = $this->replace_shortcode($args, $body);
self::send($args[‘user_mail’], $subject, $body);
}
/**
* Payment Complete Notification
*/
function payment_complete_notification($payment_data)
{
$project_id = $payment_data[‘project_id’];
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$freelancer_data = get_userdata($freelancer_id);
$args = array(
‘user_mail’ => $freelancer_data->user_email,
‘user_name’ => $freelancer_data->display_name,
‘payment_amount’ => $payment_data[‘amount’],
‘project_title’ => get_the_title($project_id),
‘project_url’ => get_permalink($project_id),
);
$subject = get_option(‘workscout_freelancer_payment_complete_subject’, ‘Payment Received: {payment_amount}’);
$subject = $this->replace_shortcode($args, $subject);
$body = get_option(
‘workscout_freelancer_payment_complete_content’,
“Hi {user_name},<br><br>
A payment of {payment_amount} has been completed for your project {project_title}.<br>
View project: {project_url}<br><br>
Best regards,<br>
{site_name}”
);
$body = $this->replace_shortcode($args, $body);
self::send($args[‘user_mail’], $subject, $body);
}
/**
* Send email
*/
public static function send($emailto, $subject, $body)
{
$from_name = get_option(‘workscout_freelancer_emails_name’, get_bloginfo(‘name’));
$from_email = get_option(‘workscout_freelancer_emails_from_email’, get_bloginfo(‘admin_email’));
$headers = sprintf(“From: %s <%s>\r\n Content-type: text/html”, $from_name, $from_email);
if (empty($emailto) || empty($subject) || empty($body)) {
return;
}
$template_loader = new WorkScout_Freelancer_Template_Loader;
ob_start();
$template_loader->get_template_part(’emails/header’);
?>
<tr>
<td align=”left” valign=”top” style=”border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 25px; padding-right: 25px; padding-bottom: 28px; width: 87.5%; font-size: 16px; font-weight: 400; padding-top: 28px; color: #666; font-family: sans-serif;” class=”paragraph”>
<?php echo $body; ?>
</td>
</tr>
<?php
$template_loader->get_template_part(’emails/footer’);
$content = ob_get_clean();
wp_mail($emailto, $subject, $content, $headers);
}
/**
* Replace email template shortcodes
*/
public function replace_shortcode($args, $body)
{
$tags = array(
‘user_mail’ => “”,
‘user_name’ => “”,
‘project_title’ => “”,
‘project_url’ => “”,
‘milestone_title’ => “”,
‘milestone_amount’ => “”,
‘order_id’ => “”,
‘order_amount’ => “”,
‘payment_amount’ => “”,
’employer_name’ => “”,
‘site_name’ => get_bloginfo(‘name’),
‘site_url’ => get_home_url(),
);
$tags = array_merge($tags, $args);
extract($tags);
$search = array(
‘{user_mail}’,
‘{user_name}’,
‘{project_title}’,
‘{project_url}’,
‘{milestone_title}’,
‘{milestone_amount}’,
‘{order_id}’,
‘{order_amount}’,
‘{payment_amount}’,
‘{employer_name}’,
‘{site_name}’,
‘{site_url}’,
);
$replace = array(
$user_mail,
$user_name,
$project_title,
$project_url,
$milestone_title,
$milestone_amount,
$order_id,
$order_amount,
$payment_amount,
$employer_name,
get_bloginfo(‘name’),
get_home_url(),
);
$message = str_replace($search, $replace, $body);
$message = nl2br($message);
return $message;
}
}
class-workscout-freelancer-forms.php
<?php
/**
* WP_Resume_Manager_Forms class.
*/
class WorkScout_Freelancer_Forms
{
/**
* Constructor
*/
public function __construct()
{
add_action(‘init’, array($this, ‘load_posted_form’));
}
/**
* If a form was posted, load its class so that it can be processed before display.
*/
public function load_posted_form()
{
if (!empty($_POST[‘workscout_freelancer_form’])) {
$this->load_form_class(sanitize_title($_POST[‘workscout_freelancer_form’]));
}
}
/**
* Load a form’s class
*
* @param string $form_name
* @return string class name on success, false on failure
*/
private function load_form_class($form_name)
{
if (!class_exists(‘WP_Job_Manager_Form’)) {
include(JOB_MANAGER_PLUGIN_DIR . ‘/includes/abstracts/abstract-wp-job-manager-form.php’);
}
// Now try to load the form_name
$form_class = ‘WorkScout_Freelancer_Form_’ . str_replace(‘-‘, ‘_’, $form_name);
$form_file = WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/includes/forms/class-workscout-freelancer-form-‘ . $form_name . ‘.php’;
if (class_exists($form_class)) {
return call_user_func(array($form_class, ‘instance’));
}
if (!file_exists($form_file)) {
return false;
}
if (!class_exists($form_class)) {
include $form_file;
}
// Init the form
return call_user_func(array($form_class, ‘instance’));
}
/**
* get_form function.
*
* @param string $form_name
* @param array $atts Optional passed attributes
* @return string
*/
public function get_form($form_name, $atts = array())
{
if ($form = $this->load_form_class($form_name)) {
ob_start();
$form->output($atts);
return ob_get_clean();
}
}
}
class-workscout-freelancer-meta-boxes.php
<?php
// Exit if accessed directly
if ( ! defined( ‘ABSPATH’ ) )
exit;
/**
* WPSight_Meta_Boxes class
*/
class WorkScout_Freelancer_Meta_Boxes {
/**
* Constructor
*/
public function __construct() {
// Add custom meta boxes
add_action( ‘cmb2_admin_init’, array( $this, ‘add_meta_boxes’ ) );
add_filter(‘submit_company_form_fields’, array($this, ‘workscout_frontend_add_company_countries_fields’));
add_filter(‘company_manager_company_fields’, array($this, ‘workscout_backend_add_company_countries_fields’));
//add_action( ‘task_category_add_form_fields’, array( $this,’wcf_task_category_add_new_meta_field’), 10, 2 );
// add_action( ‘task_category_edit_form_fields’, array( $this,’wcf_task_category_edit_meta_field’), 10, 2 );
// add_action( ‘edited_task_category’, array( $this,’wcf_save_taxonomy_custom_meta’), 10, 2 );
// add_action( ‘created_task_category’, array( $this,’wcf_save_taxonomy_custom_meta’), 10, 2 );
add_filter(‘submit_resume_form_fields’, array($this, ‘workscout_freelancer_frontend_add_resume_field’));
add_filter(‘resume_manager_resume_fields’, array($this, ‘workscout_freelancer_admin_add_resume_field’));
add_filter(‘resume_manager_resume_links_fields’, array($this, ‘workscout_freelancer_admin_add_resume_links_field’));
//add_action( ‘cmb2_admin_init’, array( $this,’wcf_register_taxonomy_metabox’ ) );
add_filter( ‘cmb2_sanitize_checkbox’, array( $this, ‘sanitize_checkbox’), 10, 2 );
//resume metaboxes for qualifications
add_action(‘add_meta_boxes’, [$this, ‘add_resume_meta_boxes’]);
add_action(‘resume_manager_save_resume’, [$this, ‘save_resume_data’], 1, 2);
}
function workscout_backend_add_company_countries_fields($fields){
if(function_exists(‘workscoutGetCountries’)){
$fields[‘_country’] = array(
‘label’ => esc_html__(‘Country’, ‘workscout-freelancer’),
‘type’ => ‘select’,
‘required’ => false,
‘options’ => workscoutGetCountries(),
‘priority’ => 16
);
}
return $fields;
}
function workscout_frontend_add_company_countries_fields($fields)
{
if (function_exists(‘workscoutGetCountries’)) {
$fields[‘company_fields’][‘country’] = array(
‘label’ => esc_html__(‘Country’, ‘workscout-freelancer’),
‘type’ => ‘select’,
‘required’ => false,
‘options’ => workscoutGetCountries(),
‘priority’ => 16
);
}
return $fields;
}
function sanitize_checkbox( $override_value, $value ) {
// Return 0 instead of false if null value given. This hack for
// checkbox or checkbox-like can be setting true as default value.
return is_null( $value ) ? ‘0’ : $value;
}
public function add_meta_boxes( ) {
//TASK
$task_admin_options = array(
‘id’ => ‘wcf_core_task_admin_metaboxes’,
‘title’ => __( ‘Task data’, ‘workscout-freelancer’ ),
‘object_types’ => array( ‘task’ ),
‘show_names’ => true,
);
$cmb_task_admin = new_cmb2_box( $task_admin_options );
$cmb_task_admin->add_field( array(
‘name’ => __( ‘Expiration date’, ‘workscout-freelancer’ ),
‘desc’ => ”,
‘id’ => ‘_task_expires’,
‘type’ => ‘text_date’,
‘date_format’ => ‘Y-m-d’,
) );
$cmb_task_admin->add_field( array(
‘name’ => __( ‘Keywords’, ‘workscout-freelancer’ ),
‘id’ => ‘keywords’,
‘type’ => ‘text’,
‘desc’ => ‘Optional keywords used in search’,
));
if(function_exists(‘mas_wpjmc’)){
$cmb_task_admin->add_field(
array(
‘name’ => esc_html__(‘Company’, ‘workscout-freelancer’),
‘id’ => ‘_company_id’,
‘type’ => ‘select’,
‘options’ => mas_wpjmc()->company->job_manager_get_current_user_companies_select_options(),
‘priority’ => 2,
)
);
}
$cmb_task_admin->add_field(array(
‘name’ => __(‘Task deadline date’, ‘workscout-freelancer’),
‘desc’ => ”,
‘id’ => ‘_task_deadline’,
‘type’ => ‘text’,
));
// Verified
$verified_box_options = array(
‘id’ => ‘wcf_core_verified_metabox’,
‘title’ => __( ‘Verified Listing’, ‘workscout-freelancer’ ),
‘context’ => ‘side’,
‘priority’ => ‘core’,
‘object_types’ => array( ‘task’ ),
‘show_names’ => false,
);
// Setup meta box
$cmb_verified = new_cmb2_box( $verified_box_options );
$cmb_verified->add_field( array(
‘name’ => __( ‘Verified’, ‘workscout-freelancer’ ),
‘id’ => ‘_verified’,
‘type’ => ‘checkbox’,
‘desc’ => __( ‘Tick the checkbox to mark it as Verified’, ‘workscout-freelancer’ ),
));
// EOF Verified
$featured_box_options = array(
‘id’ => ‘wcf_core_featured_metabox’,
‘title’ => __( ‘Featured Listing’, ‘workscout-freelancer’ ),
‘context’ => ‘side’,
‘priority’ => ‘core’,
‘object_types’ => array( ‘task’ ),
‘show_names’ => false,
);
// Setup meta box
$cmb_featured = new_cmb2_box( $featured_box_options );
$cmb_featured->add_field( array(
‘name’ => __( ‘Featured’, ‘workscout-freelancer’ ),
‘id’ => ‘_featured’,
‘type’ => ‘checkbox’,
‘desc’ => __( ‘Tick the checkbox to make it Featured’, ‘workscout-freelancer’ ),
));
$advanced_box_options = array(
‘id’ => ‘wcf_core_advanced_metabox’,
‘title’ => __( ‘Advanced meta data Listing’, ‘workscout-freelancer’ ),
‘priority’ => ‘core’,
‘object_types’ => array( ‘task’ ),
‘show_names’ => true,
);
// Setup meta box
$cmb_advanced = new_cmb2_box( $advanced_box_options );
$cmb_advanced->add_field( array(
‘name’ => __( ‘WooCommerce Product ID’, ‘workscout-freelancer’ ),
‘id’ => ‘product_id’,
‘type’ => ‘text’,
‘desc’ => __( ‘WooCommerce Product ID. Don\’t change it unless you know what you are doing:)’, ‘workscout-freelancer’ ),
));
$tabs_box_options = array(
‘id’ => ‘wcf_tabbed_task_metaboxes’,
‘title’ => __( ‘Listing fields’, ‘workscout-freelancer’ ),
‘object_types’ => array( ‘task’ ),
‘show_names’ => true,
);
// Setup meta box
$cmb_tabs = new_cmb2_box( $tabs_box_options );
// setting tabs
$tabs_setting = array(
‘config’ => $tabs_box_options,
‘layout’ => ‘vertical’, // Default : horizontal
‘tabs’ => array()
);
$tabs_setting[‘tabs’] = array(
// $this->meta_boxes_main_details(),
$this->meta_boxes_prices(),
$this->meta_boxes_video(),
$this->meta_boxes_custom(),
);
// set tabs
$cmb_tabs->add_field( array(
‘id’ => ‘_task_tabs’,
‘type’ => ‘tabs’,
‘tabs’ => $tabs_setting
) );
//BIDS Custom Meta Box
$bid_admin_options = array(
‘id’ => ‘wcf_core_bid_admin_metaboxes’,
‘title’ => __(‘Bid data’, ‘workscout-freelancer’),
‘object_types’ => array(‘bid’),
‘show_names’ => true,
);
$cmb_bid_admin = new_cmb2_box($bid_admin_options);
$cmb_bid_admin->add_field(array(
‘name’ => __(‘Budget’, ‘workscout-freelancer’),
‘desc’ => ”,
‘id’ => ‘_budget’,
‘type’ => ‘text’,
));
$cmb_bid_admin->add_field(array(
‘name’ => __(‘Time’, ‘workscout-freelancer’),
‘id’ => ‘_time’,
‘type’ => ‘text’,
‘desc’ => ‘Time to do the task’,
));
$cmb_bid_admin->add_field(array(
‘name’ => __(‘Time Scale’, ‘workscout-freelancer’),
‘id’ => ‘_time_scale’,
‘type’ => ‘text’,
‘desc’ => ‘Time scale’,
));
$cmb_tasks = new_cmb2_box(array(
‘id’ => ‘workscout_tasks’,
‘title’ => esc_html__(‘Tasks attachments’, ‘workscout-freelancer’),
‘object_types’ => array(‘task’), // Post type
‘priority’ => ‘high’,
));
$cmb_tasks->add_field(array(
‘name’ => __(‘Task Attachments ‘, ‘workscout-freelancer’),
‘desc’ => ”,
‘id’ => ‘_task_file’,
‘type’ => ‘file_list’,
// ‘preview_size’ => array( 100, 100 ), // Default: array( 50, 50 )
// ‘query_args’ => array(‘type’ => ‘image’), // Only images attachment
// Optional, override default text strings
‘text’ => array(
‘add_upload_files_text’ => __(‘Add or Upload Files’, ‘workscout-freelancer’),
),
));
}
public static function meta_boxes_prices() {
$fields = array(
‘id’ => ‘prices_tab’,
‘title’ => __( ‘Prices fields’, ‘workscout-freelancer’ ),
‘fields’ => array(
array(
‘name’ => __( ‘Type:’, ‘workscout-freelancer’ ),
‘id’ => ‘_task_type’,
‘default’ => ‘fixed’,
‘options’ => array(
‘fixed’ => __( ‘Fixed’, ‘workscout-freelancer’ ),
‘hourly’ => __( ‘Hourly’, ‘workscout-freelancer’ ),
),
‘type’ => ‘radio’,
),
array(
‘name’ => __( ‘Minimum Budget Range:’, ‘workscout-freelancer’ ),
‘id’ => ‘_budget_min’,
‘type’ => ‘text’,
),
array(
‘name’ => __( ‘Maximum Budget Range:’, ‘workscout-freelancer’ ),
‘id’ => ‘_budget_max’,
‘type’ => ‘text’,
),
array(
‘name’ => __( ‘Min rate per hour:’, ‘workscout-freelancer’ ),
‘id’ => ‘_hourly_min’,
‘type’ => ‘text’,
),
array(
‘name’ => __( ‘Max rate per hour:’, ‘workscout-freelancer’ ),
‘id’ => ‘_hourly_max’,
‘type’ => ‘text’,
),
)
);
// Set meta box
return apply_filters( ‘wcf_prices_fields’, $fields );
}
public static function meta_boxes_video() {
$fields = array(
‘id’ => ‘video_tab’,
‘title’ => __( ‘Video’, ‘workscout-freelancer’ ),
‘fields’ => array(
‘video’ => array(
‘name’ => __( ‘Video’, ‘workscout-freelancer’ ),
‘id’ => ‘_video’,
‘type’ => ‘textarea’,
‘desc’ => __( ‘URL to oEmbed supported service’,’workscout-freelancer’ ),
),
)
);
$fields = apply_filters( ‘wcf_video_fields’, $fields );
// Set meta box
return $fields;
}
public static function meta_boxes_custom() {
$fields = array(
‘id’ => ‘custom_tab’,
‘title’ => __( ‘Custom fields’, ‘workscout-freelancer’ ),
‘fields’ => array(
‘video’ => array(
‘name’ => __( ‘Example field’, ‘workscout-freelancer’ ),
‘id’ => ‘_example’,
‘type’ => ‘text’,
‘desc’ => __( ‘Example field description’,’workscout-freelancer’ ),
),
)
);
$fields = apply_filters( ‘wcf_custom_fields’, $fields );
// Set meta box
return $fields;
}
function cmb2_render_opening_hours_wcf_field_callback( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
//var_dump($escaped_value);
if(is_array($escaped_value)){
foreach ($escaped_value as $key => $time) {
echo $field_type_object->input(
array(
‘type’ => ‘text_time’,
‘value’ => $time,
‘name’ => $field_type_object->_name( ‘[]’ ),
‘time_format’ => ‘H:i’,
) );
echo “<br>”;
}
} else {
echo $field_type_object->input(
array(
‘type’ => ‘text’,
‘class’ => ‘input’,
‘name’ => $field_type_object->_name( ‘[]’ ),
) );
}
}
function wcf_register_taxonomy_metabox() {
$prefix = ‘wcf_’;
/**
* Metabox to add fields to categories and tags
*/
$cmb_term = new_cmb2_box( array(
‘id’ => $prefix . ‘edit’,
‘title’ => esc_html__( ‘Listing Taxonomy Meta’, ‘workscout-freelancer’ ), // Doesn’t output for term boxes
‘object_types’ => array( ‘term’ ), // Tells CMB2 to use term_meta vs post_meta
‘taxonomies’ => array( ‘task_category’ ), // Tells CMB2 which taxonomies should have these fields
// ‘new_term_section’ => true, // Will display in the “Add New Category” section
) );
$cmb_term->add_field( array(
‘name’ => ‘Assign Features for this Category’,
‘desc’ => ‘Features can be created in Listings -> Features’,
‘id’ => $prefix . ‘taxonomy_multicheck’,
‘taxonomy’ => ‘task_feature’, //Enter Taxonomy Slug
‘type’ => ‘taxonomy_multicheck’,
// Optional :
‘text’ => array(
‘no_terms_text’ => ‘Sorry, no terms could be found.’ // Change default text. Default: “No terms”
),
‘remove_default’ => ‘true’ // Removes the default metabox provided by WP core. Pending release as of Aug-10-1
) );
$cmb_term->add_field( array(
‘name’ => ‘Category description’,
‘id’ => $prefix . ‘taxonomy_content_description’,
‘type’ => ‘textarea’,
) );
}
/*
* Custom Icon field for Job Categories taxonomy
**/
// Add term page
function wcf_task_category_add_new_meta_field() {
?>
<div class=”form-field”>
<label for=”icon”><?php esc_html_e( ‘Category Icon’, ‘workscout-freelancer’ ); ?></label>
<select class=”wcf-icon-select” name=”icon” id=”icon”>
<?php
// $faicons = wcf_fa_icons_list();
// foreach ($faicons as $key => $value) {
// echo ‘<option value=”fa fa-‘.$key.'” ‘;
// echo ‘>’.$value.'</option>’;
// }
$faicons = wcf_fa_icons_list();
foreach ($faicons as $key => $value) {
if($key){
echo ‘<option value=”fa fa-‘.$key.'” ‘;
if ($icon == ‘fa fa-‘.$key) { echo ‘ selected=”selected”‘;}
echo ‘>’.$value.'</option>’;
}
}
if(!get_option(‘wcf_iconsmind’)==’hide’){
$imicons = vc_iconpicker_type_iconsmind(array());
foreach ($imicons as $key => $icon_array ) {
$key = key($icon_array);
$value = $icon_array[$key];
echo ‘<option value=”‘.$key.'” ‘;
if(isset($icon) && $icon == $key) { echo ‘ selected=”selected”‘;}
echo ‘>’.$value.'</option>’;
}
}
?>
</select>
<p class=”description”><?php esc_html_e( ‘Icon will be displayed in categories grid view’,’workscout-freelancer’ ); ?></p>
</div>
<?php //wp_enqueue_media(); ?>
<div class=”form-field”>
<label for=”_cover”><?php esc_html_e( ‘Custom Icon (SVG files only)’, ‘workscout-freelancer’ ); ?></label>
<input style=”width:100px” type=”text” name=”_icon_svg” id=”_icon_svg” value=””>
<input type=’button’ class=”wcf-custom-image-upload button-primary” value=”<?php _e( ‘Upload SVG Icon’, ‘workscout-freelancer’ ); ?>” id=”uploadimage”/><br />
</div>
<div class=”form-field”>
<label for=”_cover”><?php esc_html_e( ‘Category Cover’, ‘workscout-freelancer’ ); ?></label>
<input style=”width:100px” type=”text” name=”_cover” id=”_cover” value=””>
<input type=’button’ class=”wcf-custom-image-upload button-primary” value=”<?php _e( ‘Upload Image’, ‘workscout-freelancer’ ); ?>” id=”uploadimage”/><br />
<p class=”description”><?php esc_html_e( ‘Similar to the single jobs you can add image to the category header. It should be 1920px wide’,’workscout-freelancer’ ); ?></p>
</div>
<?php
}
// Edit term page
function wcf_task_category_edit_meta_field($term) {
// put the term ID into a variable
$t_id = $term->term_id;
// retrieve the existing value(s) for this meta field. This returns an array
?>
<tr class=”form-field”>
<th scope=”row” valign=”top”>
<label for=”icon”><?php esc_html_e( ‘Category Icon’, ‘workscout-freelancer’ ); ?></label>
<td>
<select class=”wcf-icon-select” name=”icon” id=”icon”>
<option value=”empty”>Empty</option>
<?php
$icon = get_term_meta( $t_id, ‘icon’, true );
$faicons = wcf_fa_icons_list();
foreach ($faicons as $key => $value) {
if($key){
echo ‘<option value=”fa fa-‘.$key.'” ‘;
if ($icon == ‘fa fa-‘.$key) { echo ‘ selected=”selected”‘;}
echo ‘>’.$value.'</option>’;
}
}
if(!get_option(‘wcf_iconsmind’)==’hide’){
$imicons = vc_iconpicker_type_iconsmind(array());
foreach ($imicons as $key => $icon_array ) {
$key = key($icon_array);
$value = $icon_array[$key];
echo ‘<option value=”‘.$key.'” ‘;
if(isset($icon) && $icon == $key) { echo ‘ selected=”selected”‘;}
echo ‘>’.$value.'</option>’;
}
}
?>
</select>
<p class=”description”><?php esc_html_e( ‘Icon will be displayed in categories grid view’,’workscout-freelancer’ ); ?></p>
</td>
</tr>
<?php wp_enqueue_media(); ?>
<tr class=”form-field”>
<th scope=”row” valign=”top”><label for=”_cover”><?php esc_html_e( ‘Custom Icon (SVG files only)’, ‘workscout-freelancer’ ); ?></label></th>
<td>
<?php
$_icon_svg = get_term_meta( $t_id, ‘_icon_svg’, true );
if($_icon_svg) :
$_icon_svg_image = wp_get_attachment_image_src($_icon_svg,’medium’);
if ($_icon_svg_image) {
echo ‘<img src=”‘.$_icon_svg_image[0].'” style=”width:300px;height: auto;”/><br>’;
}
endif;
?>
<input style=”width:100px” type=”text” name=”_icon_svg” id=”_icon_svg” value=”<?php echo $_icon_svg; ?>”>
<input type=’button’ class=”wcf-custom-image-upload button-primary” value=”<?php _e( ‘Upload SVG Icon’, ‘workscout-freelancer’ ); ?>” id=”uploadimage”/><br />
<p>We recommend using outline icons from <a href=”https://www.iconfinder.com/search/?price=free&style=outline”>iconfinder.com</a></p>
</td>
</tr>
<tr class=”form-field”>
<th scope=”row” valign=”top”><label for=”_cover”><?php esc_html_e( ‘Category Cover’, ‘workscout-freelancer’ ); ?></label></th>
<td>
<?php
$cover = get_term_meta( $t_id, ‘_cover’, true );
if($cover) :
$cover_image = wp_get_attachment_image_src($cover,’medium’);
if ($cover_image) {
echo ‘<img src=”‘.$cover_image[0].'” style=”width:300px;height: auto;”/><br>’;
}
endif;
?>
<input style=”width:100px” type=”text” name=”_cover” id=”_cover” value=”<?php echo $cover; ?>”>
<input type=’button’ class=”wcf-custom-image-upload button-primary” value=”<?php _e( ‘Upload Image’, ‘workscout-freelancer’ ); ?>” id=”uploadimage”/><br />
</td>
</tr>
<?php
}
// Save extra taxonomy fields callback function.
function wcf_save_taxonomy_custom_meta( $term_id, $tt_id ) {
if( isset( $_POST[‘icon’] ) && ” !== $_POST[‘icon’] ){
$icon = $_POST[‘icon’];
update_term_meta( $term_id, ‘icon’, $icon );
}
if( isset( $_POST[‘_cover’] ) && ” !== $_POST[‘_cover’] ){
$cover = sanitize_title( $_POST[‘_cover’] );
update_term_meta( $term_id, ‘_cover’, $cover );
}
if( isset( $_POST[‘_icon_svg’] ) && ” !== $_POST[‘_icon_svg’] ){
$_icon_svg = sanitize_title( $_POST[‘_icon_svg’] );
update_term_meta( $term_id, ‘_icon_svg’, $_icon_svg );
}
}
function cmb2_render_callback_for_datetime( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
echo $field_type_object->input( array( ‘type’ => ‘text’, ‘class’ => ‘input-datetime’ ) );
}
public static function meta_boxes_user_owner(){
$fields = array(
‘phone’ => array(
‘id’ => ‘phone’,
‘name’ => __( ‘Phone’, ‘workscout-freelancer’ ),
‘label’ => __( ‘Phone’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘header_social’ => array(
‘label’ => __( ‘Social’, ‘workscout-freelancer’ ),
‘type’ => ‘header’,
‘id’ => ‘header_social’,
‘name’ => __( ‘Social’, ‘workscout-freelancer’ ),
),
‘twitter’ => array(
‘id’ => ‘twitter’,
‘name’ => __( ‘<i class=”fa fa-twitter”></i> Twitter’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-twitter”></i> Twitter’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘facebook’ => array(
‘id’ => ‘facebook’,
‘name’ => __( ‘<i class=”fa fa-facebook-square”></i> Facebook’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-facebook-square”></i> Facebook’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘linkedin’ => array(
‘id’ => ‘linkedin’,
‘name’ => __( ‘<i class=”fa fa-linkedin”></i> Linkedin’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-linkedin”></i> Linkedin’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘instagram’ => array(
‘id’ => ‘instagram’,
‘name’ => __( ‘<i class=”fa fa-instagram”></i> Instagram’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-instagram”></i> Instagram’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘youtube’ => array(
‘id’ => ‘youtube’,
‘name’ => __( ‘<i class=”fa fa-youtube”></i> YouTube’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-youtube”></i> YouTube’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘skype’ => array(
‘id’ => ‘skype’,
‘name’ => __( ‘<i class=”fa fa-skype”></i> Skype’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-skype”></i> Skype’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘whatsapp’ => array(
‘id’ => ‘whatsapp’,
‘name’ => __( ‘<i class=”fa fa-skype”></i> Whatsapp’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-skype”></i> Whatsapp’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
);
$fields = apply_filters( ‘wcf_user_owner_fields’, $fields );
// Set meta box
return $fields;
}
public static function meta_boxes_user_guest(){
$fields = array(
‘phone’ => array(
‘id’ => ‘phone’,
‘name’ => __( ‘Phone’, ‘workscout-freelancer’ ),
‘label’ => __( ‘Phone’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘header_social’ => array(
‘label’ => __( ‘Social’, ‘workscout-freelancer’ ),
‘type’ => ‘header’,
‘id’ => ‘header_social’,
‘name’ => __( ‘Social’, ‘workscout-freelancer’ ),
),
‘twitter’ => array(
‘id’ => ‘twitter’,
‘name’ => __( ‘<i class=”fa fa-twitter”></i> Twitter’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-twitter”></i> Twitter’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘facebook’ => array(
‘id’ => ‘facebook’,
‘name’ => __( ‘<i class=”fa fa-facebook-square”></i> Facebook’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-facebook-square”></i> Facebook’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘linkedin’ => array(
‘id’ => ‘linkedin’,
‘name’ => __( ‘<i class=”fa fa-linkedin”></i> Linkedin’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-linkedin”></i> Linkedin’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘instagram’ => array(
‘id’ => ‘instagram’,
‘name’ => __( ‘<i class=”fa fa-instagram”></i> Instagram’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-instagram”></i> Instagram’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘youtube’ => array(
‘id’ => ‘youtube’,
‘name’ => __( ‘<i class=”fa fa-youtube”></i> YouTube’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-youtube”></i> YouTube’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘skype’ => array(
‘id’ => ‘skype’,
‘name’ => __( ‘<i class=”fa fa-skype”></i> Skype’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-skype”></i> Skype’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
‘whatsapp’ => array(
‘id’ => ‘whatsapp’,
‘name’ => __( ‘<i class=”fa fa-skype”></i> Whatsapp’, ‘workscout-freelancer’ ),
‘label’ => __( ‘<i class=”fa fa-skype”></i> Whatsapp’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
),
);
$fields = apply_filters( ‘wcf_user_guest_fields’, $fields );
// Set meta box
return $fields;
}
function workscout_freelancer_frontend_add_resume_field($fields){
$fields[‘resume_fields’][‘candidate_photo’][‘priority’] = 13 ;
$fields[‘resume_fields’][‘competencies’] = [
‘label’ => __(‘Competency Bars’, ‘workscout-freelancer’ ),
‘add_row’ => __(‘Add competency’, ‘workscout-freelancer’ ),
‘type’ => ‘repeated’, // Repeated field.
‘required’ => false,
‘placeholder’ => ”,
‘priority’ => 11,
‘fields’ => [
‘skill’ => [
‘label’ => __( ‘Skill’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
‘required’ => true,
‘placeholder’ => ”,
],
‘qualification’ => [
‘label’ => __( ‘Level (0-100%)’, ‘workscout-freelancer’ ),
// ‘type’ => ‘select’,
//array from 0 to 100 every 5 )
// ‘options’ => array_combine(range(0,100,5), range(0,100,5)),
‘type’ => ‘number’,
‘min’ =>0,
‘max’ =>100,
‘required’ => true,
‘placeholder’ => ”,
],
],
‘personal_data’ => true,
];
if (function_exists(‘workscoutGetCountries’)) {
$fields[‘resume_fields’][‘country’] = array(
‘label’ => esc_html__(‘Country’, ‘workscout-freelancer’),
‘type’ => ‘select’,
‘required’ => false,
‘options’ => workscoutGetCountries(),
‘priority’ => 4
);
}
// $fields[‘resume_fields’][‘set_as_profile’] = array(
// ‘label’ => esc_html__(‘Set this resume as your profile’, ‘workscout-freelancer’),
// ‘type’ => ‘checkbox’,
// ‘required’ => false,
// ‘priority’ => 16
// );
$fields[‘resume_fields’][‘gallery’] = array(
‘label’ => esc_html__(‘Gallery’, ‘workscout-freelancer’),
‘type’ => ‘gallery’,
‘required’ => false,
‘priority’ => 5
);
$fields[‘resume_fields’][‘header_image’] = array(
‘label’ => __(‘Header Image’, ‘workscout-freelancer’),
‘type’ => ‘file’,
‘required’ => false,
‘priority’ => 13,
‘ajax’ => true,
‘multiple’ => false,
‘allowed_mime_types’ => array(
‘jpg’ => ‘image/jpeg’,
‘jpeg’ => ‘image/jpeg’,
‘gif’ => ‘image/gif’,
‘png’ => ‘image/png’
)
);
$fields[‘resume_fields’][‘links’][‘label’] = __( ‘Social Sites’, ‘workscout-freelancer’ );
$fields[‘resume_fields’][‘links’][‘add_row’] = __( ‘Add Site’, ‘workscout-freelancer’ );
$fields[‘resume_fields’][‘links’][‘fields’] = [
‘name’ => [
‘label’ => __( ‘Service’, ‘workscout-freelancer’ ),
‘type’ => ‘select’,
‘options’ => workscoutBrandIcons(),
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 1,
],
‘url’ => [
‘label’ => __( ‘URL’, ‘workscout-freelancer’ ),
‘type’ => ‘text’,
‘sanitizer’ => ‘esc_url_raw’,
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 2,
],
];
// ‘links’ => [
// ‘label’ => __( ‘URL(s)’, ‘workscout-freelancer’ ),
// ‘add_row’ => __( ‘Add URL’, ‘workscout-freelancer’ ),
// ‘type’ => ‘links’, // Repeated field.
// ‘required’ => false,
// ‘placeholder’ => ”,
// ‘description’ => __( ‘Optionally provide links to any of your websites or social network profiles.’, ‘workscout-freelancer’ ),
// ‘priority’ => 10,
// ‘fields’ => [
// ‘name’ => [
// ‘label’ => __( ‘Name’, ‘workscout-freelancer’ ),
// ‘type’ => ‘text’,
// ‘required’ => true,
// ‘placeholder’ => ”,
// ‘priority’ => 1,
// ],
// ‘url’ => [
// ‘label’ => __( ‘URL’, ‘workscout-freelancer’ ),
// ‘type’ => ‘text’,
// ‘sanitizer’ => ‘esc_url_raw’,
// ‘required’ => true,
// ‘placeholder’ => ”,
// ‘priority’ => 2,
// ],
// ],
// ‘personal_data’ => true,
// ],
return $fields;
}
function workscout_freelancer_admin_add_resume_field($fields){
if (function_exists(‘workscoutGetCountries’)) {
$fields[‘_country’] = array(
‘label’ => esc_html__(‘Country’, ‘workscout-freelancer’),
‘type’ => ‘select’,
‘required’ => false,
‘options’ => workscoutGetCountries(),
‘priority’ => 16
);
}
$fields[‘_header_image’] = array(
‘label’ => __(‘Header Image’, ‘workscout-freelancer’),
‘type’ => ‘file’,
‘required’ => false,
‘priority’ => 13,
‘ajax’ => true,
‘multiple’ => false,
‘allowed_mime_types’ => array(
‘jpg’ => ‘image/jpeg’,
‘jpeg’ => ‘image/jpeg’,
‘gif’ => ‘image/gif’,
‘png’ => ‘image/png’
)
);
// $fields[‘_gallery’] = array(
// ‘label’ => esc_html__(‘Gallery’, ‘workscout-freelancer’),
// ‘type’ => ‘text’,
// ‘required’ => false,
// ‘priority’ => 5
// );
return $fields;
}
function workscout_freelancer_admin_add_resume_links_field($fields)
{
$fields = [
‘name’ => [
‘label’ => __(‘Service’, ‘workscout-freelancer’),
‘type’ => ‘select’,
‘name’ => ‘resume_url_name[]’,
‘options’ => workscoutBrandIcons(),
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 1,
],
‘url’ => [
‘label’ => __(‘URL’, ‘workscout-freelancer’),
‘type’ => ‘text’,
‘name’ => ‘resume_url[]’,
‘required’ => true,
‘placeholder’ => ”,
‘priority’ => 2,
],
];
return $fields;
}
//resume_manager_resume_links_fields
/**
* Resume fields
*
* @return array
*/
public static function resume_competencies_fields()
{
return apply_filters(
‘resume_manager_resume_competencies_fields’,
[
‘skill’ => [
‘label’ => __(‘Skill’, ‘workscout-freelancer’),
‘name’ => ‘competencies_skill[]’,
‘placeholder’ => ”,
‘description’ => ”,
‘required’ => true,
],
‘qualification’ => [
‘label’ => __(‘Level ( 0-100%)’, ‘workscout-freelancer’),
‘name’ => ‘competencies_qualification[]’,
‘placeholder’ => ”,
// ‘type’ =>’select’,
// ‘options’ => array_combine(range(0,100,5), range(0,100,5)),
‘type’ => ‘text’,
‘min’ => 0,
‘max’ => 100,
‘description’ => ”,
],
]
);
}
function add_resume_meta_boxes(){
add_meta_box(‘resume_competencies_data’, __(‘Competency Bars’, ‘workscout-freelancer’), [$this, ‘competencies_data’], ‘resume’, ‘normal’, ‘high’);
}
/**
* Resume Education data
*
* @param mixed $post
*/
public function competencies_data($post)
{
$fields = $this->resume_competencies_fields();
WP_Resume_Manager_Writepanels::repeated_rows_html(__(‘Competency’, ‘workscout-freelancer’), $fields, get_post_meta($post->ID, ‘_competencies’, true));
}
public function save_resume_data($post_id, $post)
{
global $wpdb;
$save_repeated_fields = [
‘_competencies’ => $this->resume_competencies_fields(),
];
foreach ($save_repeated_fields as $meta_key => $fields) {
WP_Resume_Manager_Writepanels::save_repeated_row($post_id, $meta_key, $fields);
}
}
}
class-workscout-freelancer-project.php
<?php
// Exit if accessed directly
if (!defined(‘ABSPATH’))
exit;
/**
* WorkScout_Freelancer_Task class
*/
class WorkScout_Freelancer_Project
{
private static $_instance = null;
private $meta_key = ‘project_milestones’;
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct()
{
add_action(‘init’, array($this, ‘workscout_handle_project_comment’));
add_action(‘wp_ajax_save_milestone’, array($this, ‘ajax_save_milestone’));
add_action(‘wp_ajax_ws_delete_milestone’, array($this, ‘ajax_delete_milestone’));
add_action(‘wp_ajax_approve_milestone’, array($this, ‘ajax_approve_milestone’));
add_action(‘wp_ajax_complete_milestone’, array($this, ‘ajax_complete_milestone’));
add_action( ‘woocommerce_order_status_changed’, array($this, ‘handle_order_status_change’), 10, 3);
add_action(‘wp_ajax_get_milestone_for_edit’, array($this, ‘ajax_get_milestone_for_edit’));
add_action(‘wp_ajax_update_milestone’, array($this, ‘ajax_update_milestone’));
}
/**
* Get detailed milestone data by ID
*
* @param string $milestone_id The unique identifier of the milestone
* @param int $project_id Optional project ID if known (improves performance)
* @return array|false Returns milestone data array or false if not found
*/
public function get_milestone_details($milestone_id, $project_id = null)
{
global $wpdb;
// If project_id is not provided, find it by querying post meta
if (!$project_id) {
$project_id = $this->find_project_by_milestone($milestone_id);
if (!$project_id) {
return false;
}
}
// Get all milestones for the project
$milestones = $this->get_milestones($project_id);
if (empty($milestones)) {
return false;
}
// Find the specific milestone
$milestone_data = null;
foreach ($milestones as $milestone) {
if ($milestone[‘id’] === $milestone_id) {
$milestone_data = $milestone;
break;
}
}
if (!$milestone_data) {
return false;
}
// Get project details
$project = get_post($project_id);
if (!$project) {
return false;
}
// Get employer and freelancer details
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
// Get payment status if order exists
$payment_status = ”;
$order_id = isset($milestone_data[‘order_id’]) ? $milestone_data[‘order_id’] : null;
if ($order_id) {
$order = wc_get_order($order_id);
if ($order) {
$payment_status = $order->get_status();
}
}
// Build comprehensive milestone data array
$complete_milestone_data = array_merge($milestone_data, array(
‘project_id’ => $project_id,
‘project_title’ => $project->post_title,
‘project_status’ => $project->post_status,
’employer_id’ => $employer_id,
‘freelancer_id’ => $freelancer_id,
’employer_name’ => get_userdata($employer_id) ? get_userdata($employer_id)->display_name : ”,
‘freelancer_name’ => get_userdata($freelancer_id) ? get_userdata($freelancer_id)->display_name : ”,
‘payment_status’ => $payment_status,
‘order_id’ => $order_id,
‘creation_date’ => isset($milestone_data[‘creation_date’]) ? $milestone_data[‘creation_date’] : ”,
‘last_modified’ => isset($milestone_data[‘last_modified’]) ? $milestone_data[‘last_modified’] : ”,
‘completion_percentage’ => $this->calculate_milestone_completion_percentage($project_id, $milestone_id),
));
return apply_filters(‘workscout_freelancer_milestone_details’, $complete_milestone_data, $milestone_id, $project_id);
}
/**
* Helper function to find project ID by milestone ID
*
* @param string $milestone_id The milestone ID to search for
* @return int|false Project ID if found, false otherwise
*/
private function find_project_by_milestone($milestone_id)
{
$args = array(
‘post_type’ => ‘project’,
‘posts_per_page’ => 1,
‘meta_query’ => array(
array(
‘key’ => $this->meta_key,
‘value’ => $milestone_id,
‘compare’ => ‘LIKE’
)
)
);
$query = new WP_Query($args);
if ($query->have_posts()) {
return $query->posts[0]->ID;
}
return false;
}
/**
* Calculate the completion percentage of a milestone
*
* @param int $project_id The project ID
* @param string $milestone_id The milestone ID
* @return float The completion percentage
*/
private function calculate_milestone_completion_percentage($project_id, $milestone_id)
{
$milestone = $this->get_milestone($project_id, $milestone_id);
if (!$milestone) {
return 0;
}
$total = 0;
// Calculate based on approval status
if ($milestone[‘client_approval’]) {
$total += 50;
}
if ($milestone[‘freelancer_approval’]) {
$total += 50;
}
return $total;
}
function workscout_handle_project_comment()
{
if (!isset($_POST[‘submit_project_comment’])) {
return;
}
if (!is_user_logged_in()) {
return;
}
// Verify nonce
if (!isset($_POST[‘project_comment_nonce’]) || !wp_verify_nonce($_POST[‘project_comment_nonce’], ‘project_comment_action’)) {
return;
}
$project_id = absint($_POST[‘project_id’]);
$comment_content = wp_kses_post($_POST[‘comment_content’]);
$is_milestone = isset($_POST[‘is_milestone’]) ? 1 : 0;
// Check if user is allowed to comment (project owner or assigned freelancer)
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$current_user_id = get_current_user_id();
if ($current_user_id != $freelancer_id && $current_user_id != $employer_id) {
return;
}
// Prepare comment data
$comment_data = array(
‘comment_post_ID’ => $project_id,
‘comment_content’ => $comment_content,
‘user_id’ => $current_user_id,
‘comment_type’ => ‘project_comment’,
‘comment_approved’ => 1
);
// Insert comment
$comment_id = wp_insert_comment($comment_data);
if ($comment_id) {
// Handle milestone
if ($is_milestone) {
add_comment_meta($comment_id, ‘_is_milestone’, ‘1’);
// Add milestone status
add_comment_meta($comment_id, ‘_milestone_status’, ‘pending’);
}
// Handle file attachments
if (!empty($_FILES[‘comment_files’])) {
require_once(ABSPATH . ‘wp-admin/includes/image.php’);
require_once(ABSPATH . ‘wp-admin/includes/file.php’);
require_once(ABSPATH . ‘wp-admin/includes/media.php’);
$files = $_FILES[‘comment_files’];
$files_array = array();
foreach ($files[‘name’] as $key => $value) {
if ($files[‘name’][$key]) {
$file = array(
‘name’ => $files[‘name’][$key],
‘type’ => $files[‘type’][$key],
‘tmp_name’ => $files[‘tmp_name’][$key],
‘error’ => $files[‘error’][$key],
‘size’ => $files[‘size’][$key]
);
$_FILES = array(‘upload_file’ => $file);
$attachment_id = media_handle_upload(‘upload_file’, $project_id);
if (!is_wp_error($attachment_id)) {
$files_array[] = $attachment_id;
}
}
}
if (!empty($files_array)) {
add_comment_meta($comment_id, ‘_comment_files’, $files_array);
}
}
wp_redirect(add_query_arg(‘comment_posted’, ‘true’, wp_get_referer()));
exit;
}
exit;
}
/**
* Get all files attached to project comments
*
* @param int $project_id The ID of the project
* @return array Array of attachment objects with file details
*/
public function get_project_files($project_id)
{
// Get all comments for this project
$comments = get_comments(array(
‘post_id’ => $project_id,
‘type’ => ‘project_comment’,
‘status’ => ‘approve’
));
$files = array();
foreach ($comments as $comment) {
// Get files attached to this comment
$comment_files = get_comment_meta($comment->comment_ID, ‘_comment_files’, true);
if (!empty($comment_files) && is_array($comment_files)) {
foreach ($comment_files as $attachment_id) {
$attachment = get_post($attachment_id);
if ($attachment) {
$file_url = wp_get_attachment_url($attachment_id);
$file_type = wp_check_filetype(get_attached_file($attachment_id));
$file_size = filesize(get_attached_file($attachment_id));
$files[] = array(
‘id’ => $attachment_id,
‘name’ => $attachment->post_title,
‘url’ => $file_url,
‘type’ => $file_type[‘ext’],
‘size’ => size_format($file_size),
‘date’ => $attachment->post_date,
‘comment_id’ => $comment->comment_ID,
‘comment_author’ => $comment->comment_author,
‘comment_date’ => $comment->comment_date
);
}
}
}
}
return $files;
}
public function display_project_files($project_id)
{
$files = $this->get_project_files($project_id);
if (empty($files)) {
echo ‘<p>No files attached to this project.</p>’;
return;
}
foreach ($files as $file) {
?>
<li class=”project-file”>
<div class=”file-info”>
<a href=”<?php echo esc_url($file[‘url’]); ?>” target=”_blank” class=”file-name”>
<?php echo esc_html($file[‘name’]); ?>
</a>
<span class=”file-meta”>
<?php
echo esc_html($file[‘type’]) . ‘ | ‘ .
esc_html($file[‘size’]) . ‘ | ‘ .
‘Uploaded by ‘ . esc_html($file[‘comment_author’]) . ‘ on ‘ .
date(‘M j, Y’, strtotime($file[‘comment_date’]));
?>
</span>
</div>
</li>
<?php
}
}
// Get milestones for a project
public function get_milestones($project_id)
{
$milestones = get_post_meta($project_id, $this->meta_key, true);
return !empty($milestones) ? $milestones : array();
}
// I need a function that calculates project completion based on done milestones:
/**
* Calculate the overall project completion percentage based on completed milestones
*
* @param int $project_id The ID of the project
* @return float Completion percentage between 0 and 100
*/
public function calculate_project_completion($project_id) {
$milestones = $this->get_milestones($project_id);
if (empty($milestones)) {
return 0;
}
$total_percentage = 0;
$completed_percentage = 0;
foreach ($milestones as $milestone) {
$milestone_percentage = floatval($milestone[‘percentage’]);
$total_percentage += $milestone_percentage;
if ($milestone[‘status’] === ‘approved’) {
$completed_percentage += $milestone_percentage;
}
}
return $completed_percentage;
// Normalize to ensure we don’t exceed 100%
if ($total_percentage > 0) {
return min(100, ($completed_percentage / $total_percentage) * 100);
}
return 0;
}
// Save a new milestone or update existing one
public function save_milestone($project_id, $milestone_data)
{
$milestones = $this->get_milestones($project_id);
if (isset($milestone_data[‘id’])) {
// Update existing milestone
foreach ($milestones as $key => $milestone) {
if ($milestone[‘id’] === $milestone_data[‘id’]) {
$milestones[$key] = array_merge($milestone, $milestone_data);
do_action(‘workscout_freelancer_milestone_edited’, $project_id, $milestone_data);
break;
}
}
} else {
// Add new milestone
$milestone_data[‘id’] = uniqid();
$milestone_data[‘status’] = ‘pending’;
$milestone_data[‘client_approval’] = false;
$milestone_data[‘freelancer_approval’] = false;
$milestones[] = $milestone_data;
// Trigger email notification
do_action(‘workscout_freelancer_new_milestone_created’, $project_id, $milestone_data);
}
return update_post_meta($project_id, $this->meta_key, $milestones);
}
// Handle milestone approval
public function approve_milestone($project_id, $milestone_id, $user_type)
{
$milestones = $this->get_milestones($project_id);
$completion = 0;
foreach ($milestones as &$milestone) {
$completion = $milestone[‘percentage’];
if ($milestone[‘id’] === $milestone_id) {
if ($user_type === ‘client’) {
$milestone[‘client_approval’] = true;
} else {
$milestone[‘freelancer_approval’] = true;
do_action(‘workscout_freelancer_milestone_for_approval’, $project_id, $milestone_id);
}
// Check if both parties approved
if ($milestone[‘client_approval’] && $milestone[‘freelancer_approval’]) {
$milestone[‘status’] = ‘approved’;
// Create WooCommerce order
$order_id = $this->create_milestone_order($project_id, $milestone);
if ($order_id) {
$milestone[‘order_id’] = $order_id;
}
// Trigger milestone approved notification
do_action(‘workscout_freelancer_milestone_approved’, $project_id, $milestone_id,$order_id);
}
break;
}
}
update_post_meta($project_id, $this->meta_key, $milestones);
$data = array(
‘remaining_percentage’ => 100-$completion
);
return $data;
}
// In the WorkScout_Project_Milestones class
public function ajax_approve_milestone()
{
// Verify nonce
check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$milestone_id = sanitize_text_field($_POST[‘milestone_id’]);
// Check if user has permission
if (!$this->can_approve_milestone($project_id)) {
wp_send_json_error(‘Permission denied’);
return;
}
// Determine if current user is client or freelancer
$user_type = $this->get_user_type($project_id);
$result = $this->approve_milestone($project_id, $milestone_id, $user_type);
if ($result) {
wp_send_json_success( array(
‘remaining_percentage’ => $result[‘remaining_percentage’]
)
);
} else {
wp_send_json_error();
}
}
/**
* AJAX handler for getting milestone data for editing
*/
public function ajax_get_milestone_for_edit()
{
// check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$milestone_id = sanitize_text_field($_POST[‘milestone_id’]);
// if (!$this->can_edit_milestone($project_id, $milestone_id)) {
// wp_send_json_error([‘message’ => __(‘Permission denied’, ‘workscout-freelancer’)]);
// return;
// }
$milestone = $this->get_milestone($project_id, $milestone_id);
if ($milestone) {
// Get project value for percentage calculations
$project_value = $this->get_project_value($project_id);
// Calculate remaining percentage excluding current milestone
$remaining_percentage = 100 – $this->get_total_milestone_percentage($project_id, $milestone_id);
$remaining_percentage += floatval($milestone[‘percentage’]); // Add back current milestone percentage
wp_send_json_success([
‘milestone’ => $milestone,
‘project_value’ => $project_value,
‘remaining_percentage’ => $remaining_percentage
]);
} else {
wp_send_json_error([‘message’ => __(‘Milestone not found’, ‘workscout-freelancer’)]);
}
}
/**
* AJAX handler for updating milestone
*/
public function ajax_update_milestone()
{
// check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$milestone_id = sanitize_text_field($_POST[‘milestone_id’]);
$percentage = floatval($_POST[‘percentage’]);
if (!$this->can_edit_milestone($project_id, $milestone_id)) {
wp_send_json_error([‘message’ => __(‘Permission denied’, ‘workscout-freelancer’)]);
return;
}
// Validate percentage
if (!$this->validate_milestone_percentage($project_id, $percentage, $milestone_id)) {
wp_send_json_error([
‘message’ => __(‘Total milestone percentages cannot exceed 100%’, ‘workscout-freelancer’),
‘current_total’ => $this->get_total_milestone_percentage($project_id, $milestone_id)
]);
return;
}
$amount = $this->calculate_amount_from_percentage($project_id, $percentage);
$milestone_data = [
‘id’ => $milestone_id,
‘title’ => sanitize_text_field($_POST[‘title’]),
‘description’ => wp_kses_post($_POST[‘description’]),
‘percentage’ => $percentage,
‘amount’ => $amount,
];
$result = $this->update_milestone($project_id, $milestone_data);
if ($result) {
wp_send_json_success([
‘milestone’ => $milestone_data,
‘remaining_percentage’ => 100 – $this->get_total_milestone_percentage($project_id)
]);
} else {
wp_send_json_error([‘message’ => __(‘Failed to update milestone’, ‘workscout-freelancer’)]);
}
}
private function create_milestone_order($project_id, $milestone)
{
WC()->cart->empty_cart();
// Get project details
$project = get_post($project_id);
$client_id = $project->post_author;
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
try {
// Create the order
// Create or get the product
$product_id = $this->get_or_create_milestone_product();
if (!$product_id) {
error_log(‘Failed to create milestone product’);
return false;
}
$product = wc_get_product($product_id);
if (!$product) {
error_log(‘Failed to get milestone product’);
return false;
}
// Set the price
$product->set_price($milestone[‘amount’]);
$product->set_regular_price($milestone[‘amount’]);
$product->save();
// Create the order
$order = wc_create_order(array(
‘status’ => ‘pending’,
‘customer_id’ => get_current_user_id()
));
// Add the product to the cart first
$cart_item_key = WC()->cart->add_to_cart($product_id, 1, 0, array(), array(
‘milestone_id’ => $milestone[‘id’],
‘project_id’ => $project_id
));
if (!$cart_item_key) {
error_log(‘Failed to add product to cart’);
return false;
}
$item_id = $order->add_product($product, 1, array(
‘subtotal’ => $milestone[‘amount’],
‘total’ => $milestone[‘amount’]
));
if (!$item_id) {
error_log(‘Failed to add product to order’);
return false;
}
// Add meta data
$order->update_meta_data(‘project_id’, $project_id);
$order->update_meta_data(‘project_title’, get_the_title($project_id));
$order->update_meta_data(‘milestone_id’, $milestone[‘id’]);
$order->update_meta_data(‘milestone_title’, $milestone[‘title’]);
$order->update_meta_data(‘freelancer_id’, get_post_meta($project_id, ‘_freelancer_id’, true));
$order->update_meta_data(’employer_id’, get_post_meta($project_id, ‘_employer_id’, true));
// Set address
$this->set_order_address($order, get_current_user_id());
// Calculate totals
$order->calculate_totals();
// Add note
$order->add_order_note(sprintf(
‘Order created for project milestone: %s (Project: %s)’,
$milestone[‘title’],
get_the_title($project_id)
));
$order->save();
// Fire the actions
do_action(‘workscout_milestone_order_created’, $order->get_id(), $project_id,
$milestone
);
do_action(‘workscout_freelancer_order_created’, $order->get_id());
return $order->get_id();
} catch (Exception $e) {
error_log(‘Failed to create milestone order: ‘ . $e->getMessage());
return false;
}
}
// Helper function to set order address
private function set_order_address($order, $client_id)
{
$client = get_userdata($client_id);
if ($client) {
$address = array(
‘first_name’ => $client->first_name,
‘last_name’ => $client->last_name,
’email’ => $client->user_email,
‘phone’ => get_user_meta($client_id, ‘billing_phone’, true),
‘address_1’ => get_user_meta($client_id, ‘billing_address_1’, true),
‘address_2’ => get_user_meta($client_id, ‘billing_address_2’, true),
‘city’ => get_user_meta($client_id, ‘billing_city’, true),
‘state’ => get_user_meta($client_id, ‘billing_state’, true),
‘postcode’ => get_user_meta($client_id, ‘billing_postcode’, true),
‘country’ => get_user_meta($client_id, ‘billing_country’, true),
);
// Set both billing and shipping address
$order->set_address($address, ‘billing’);
$order->set_address($address, ‘shipping’);
}
}
private function get_or_create_milestone_product()
{
try {
// Try to get existing milestone product
$product_id = get_option(‘workscout_milestone_product_id’);
if ($product_id) {
$product = wc_get_product($product_id);
if ($product) {
// Update existing product settings
$product->set_status(‘publish’);
$product->set_catalog_visibility(‘hidden’);
$product->set_virtual(true);
$product->set_downloadable(false);
$product->set_sold_individually(true);
$product->set_stock_status(‘instock’);
$product->save();
return $product_id;
}
}
// Create new product
$product = new WC_Product_Simple();
$product->set_name(‘Project Milestone Payment’);
$product->set_status(‘publish’);
$product->set_catalog_visibility(‘hidden’);
$product->set_virtual(true);
$product->set_downloadable(false);
$product->set_sold_individually(true);
$product->set_stock_status(‘instock’);
$product->set_manage_stock(false);
$product->set_reviews_allowed(false);
// Set initial prices
$product->set_regular_price(‘0’);
$product->set_price(‘0’);
// Set the SKU
$product->set_sku(‘milestone-payment-‘ . wp_generate_password(6, false));
// Save the product
$product->save();
// Save product ID for future use
update_option(‘workscout_milestone_product_id’, $product->get_id());
return $product->get_id();
} catch (Exception $e) {
error_log(‘Error creating milestone product: ‘ . $e->getMessage());
return false;
}
}
// Hook for order status changes
public function handle_order_status_change($order_id, $old_status, $new_status)
{
$order = wc_get_order($order_id);
if (!$order) return;
// Get milestone info from order
$project_id = $order->get_meta(‘project_id’);
$milestone_id = $order->get_meta(‘milestone_id’);
if (!$project_id || !$milestone_id) return;
// Update milestone status based on order status
$milestones = $this->get_milestones($project_id);
foreach ($milestones as &$milestone) {
if ($milestone[‘id’] === $milestone_id) {
switch ($new_status) {
case ‘completed’:
case ‘processing’:
$milestone[‘payment_status’] = ‘paid’;
break;
case ‘refunded’:
$milestone[‘payment_status’] = ‘refunded’;
break;
case ‘failed’:
$milestone[‘payment_status’] = ‘failed’;
break;
}
break;
}
}
if ($new_status === ‘completed’) {
do_action(‘workscout_freelancer_payment_complete’,$order_id, $project_id, $milestone_id);
// Check if all milestones are paid
$total_progress = 0;
$all_paid = true;
foreach ($milestones as $milestone) {
$total_progress += floatval($milestone[‘percentage’]);
if ($milestone[‘payment_status’] !== ‘paid’) {
$all_paid = false;
break;
}
}
// If all milestones are paid and total progress is 100%, mark project as completed
if ($all_paid && abs($total_progress – 100) < 0.01) {
wp_update_post(array(
‘ID’ => $project_id,
‘post_status’ => ‘completed’
));
// update post meta _project_status to completed
update_post_meta($project_id, ‘_project_status’, ‘completed’);
}
}
update_post_meta($project_id, $this->meta_key, $milestones);
}
// Get total project value from custom field
private function get_project_value($project_id)
{
return floatval(get_post_meta($project_id, ‘_budget’, true));
}
// Calculate total percentage of existing milestones
public function get_total_milestone_percentage($project_id, $exclude_milestone_id = null)
{
$milestones = $this->get_milestones($project_id);
$total = 0;
foreach ($milestones as $milestone) {
// Skip the milestone we’re updating if provided
// check if milestone has percentage
if (!isset($milestone[‘percentage’])) {
continue;
// check if milestone has amount
}
if ($exclude_milestone_id && $milestone[‘id’] === $exclude_milestone_id) {
continue;
}
$total += floatval($milestone[‘percentage’]);
}
return $total;
}
// Validate milestone percentage
private function validate_milestone_percentage($project_id, $new_percentage, $milestone_id = null)
{
$current_total = $this->get_total_milestone_percentage($project_id, $milestone_id);
$total_with_new = $current_total + floatval($new_percentage);
return $total_with_new <= 100;
}
// Calculate amount based on percentage
private function calculate_amount_from_percentage($project_id, $percentage)
{
$project_value = $this->get_project_value($project_id);
return ($project_value * floatval($percentage)) / 100;
}
public function get_milestone_payment_link($milestone)
{
if (!isset($milestone[‘order_id’])) {
return ”;
}
$order = wc_get_order($milestone[‘order_id’]);
if (!$order) {
return ”;
}
// Check if current user is the client
if (get_current_user_id() !== $order->get_customer_id()) {
return ”;
}
switch ($order->get_status()) {
case ‘pending’:
return sprintf(
‘<a href=”%s” class=”button pay-milestone”>Pay Now</a>’,
esc_url($order->get_checkout_payment_url())
);
case ‘processing’:
case ‘completed’:
return ‘<span class=”milestone-paid”>Payment Complete</span>’;
default:
return sprintf(
‘<span class=”milestone-status”>Order Status: %s</span>’,
esc_html($order->get_status())
);
}
}
// Helper function to determine user type
public function get_user_type($project_id)
{
$current_user_id = get_current_user_id();
$project = get_post($project_id);
$freelancer = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer = get_post_meta($project_id, ‘_employer_id’, true);
if ($current_user_id === intval($employer)) {
return ‘client’;
} elseif ($current_user_id === intval($freelancer)) {
return ‘freelancer’;
}
return false;
}
// Check if user can approve milestone
private function can_approve_milestone($project_id)
{
$user_type = $this->get_user_type($project_id);
return $user_type !== false;
}
/**
* Check if user can edit milestone
*
* @param int $project_id Project ID
* @param string $milestone_id Milestone ID
* @param int $user_id User ID (optional)
* @return bool
*/
public function can_edit_milestone($project_id, $milestone_id, $user_id = null)
{
if (!$user_id) {
$user_id = get_current_user_id();
}
$milestone = $this->get_milestone($project_id, $milestone_id);
if (!$milestone) {
return false;
}
// Get project owner and freelancer
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
// Check if milestone is already approved
if (isset($milestone[‘status’]) && $milestone[‘status’] === ‘approved’) {
return false;
}
if ($user_id == $employer_id) {
return false;
}
if ($user_id == $freelancer_id) {
return true;
}
// Only employer can edit milestones
return ($user_id == $employer_id);
}
/**
* Check if user can edit milestones for a project
*
* @param int $project_id Project ID
* @param int $user_id Optional user ID, defaults to current user
* @return bool
*/
private function can_edit_milestones($project_id, $user_id = null)
{
if (!$user_id) {
$user_id = get_current_user_id();
}
// Get project owner and freelancer
$employer_id = get_post_meta($project_id, ‘_employer_id’, true);
$freelancer_id = get_post_meta($project_id, ‘_freelancer_id’, true);
// Only freelancers can add/edit milestones
return ($user_id == $freelancer_id);
}
// AJAX handler for saving milestone
public function ajax_save_milestone()
{
check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$percentage = floatval($_POST[‘percentage’]);
$milestone_id = isset($_POST[‘milestone_id’]) ? sanitize_text_field($_POST[‘milestone_id’]) : null;
// Check if user has permission
if (!$this->can_edit_milestones($project_id)) {
wp_send_json_error(‘Permission denied’);
return;
}
// Validate percentage
if (!$this->validate_milestone_percentage($project_id, $percentage, $milestone_id)) {
wp_send_json_error([
‘message’ => ‘Total milestone percentages cannot exceed 100%’,
‘current_total’ => $this->get_total_milestone_percentage($project_id, $milestone_id)
]);
return;
}
$amount = $this->calculate_amount_from_percentage($project_id, $percentage);
$milestone_data = [
‘title’ => sanitize_text_field($_POST[‘title’]),
‘description’ => wp_kses_post($_POST[‘description’]),
‘percentage’ => $percentage,
‘amount’ => $amount,
];
if (isset($_POST[‘milestone_id’])) {
$milestone_data[‘id’] = sanitize_text_field($_POST[‘milestone_id’]);
}
$result = $this->save_milestone($project_id, $milestone_data);
if ($result) {
wp_send_json_success([
‘milestone’ => $milestone_data,
‘remaining_percentage’ => 100 – $this->get_total_milestone_percentage($project_id)
]);
} else {
wp_send_json_error([‘message’ => ‘Failed to save milestone’]);
}
}
// AJAX handler to get remaining percentage
public function ajax_get_remaining_percentage()
{
check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$milestone_id = isset($_POST[‘milestone_id’]) ? sanitize_text_field($_POST[‘milestone_id’]) : null;
$remaining = 100 – $this->get_total_milestone_percentage($project_id, $milestone_id);
wp_send_json_success([‘remaining’ => $remaining]);
}
/**
* Delete a milestone
*
* @param int $project_id Project ID
* @param string $milestone_id Milestone ID
* @return bool Success status
*/
public function delete_milestone($project_id, $milestone_id)
{
$milestones = $this->get_milestones($project_id);
$updated_milestones = array();
foreach ($milestones as $milestone) {
if ($milestone[‘id’] !== $milestone_id) {
$updated_milestones[] = $milestone;
} else {
// Check if milestone can be deleted
if (isset($milestone[‘status’]) && $milestone[‘status’] === ‘approved’) {
return false; // Cannot delete approved milestone
}
}
}
return update_post_meta($project_id, $this->meta_key, $updated_milestones);
}
/**
* Update existing milestone
*
* @param int $project_id Project ID
* @param array $milestone_data Updated milestone data
* @return bool Success status
*/
public function update_milestone($project_id, $milestone_data)
{
if (!isset($milestone_data[‘id’])) {
return false;
}
$milestones = $this->get_milestones($project_id);
$milestone_updated = false;
foreach ($milestones as $key => $milestone) {
if ($milestone[‘id’] === $milestone_data[‘id’]) {
// Check if milestone can be edited
if (isset($milestone[‘status’]) && $milestone[‘status’] === ‘approved’) {
return false; // Cannot edit approved milestone
}
// Update milestone data while preserving status and approval flags
$milestones[$key] = array_merge($milestone, $milestone_data);
// unset freelancer_approval flag
$milestones[$key][‘freelancer_approval’] = false;
$milestones[$key][‘client_approval’] = false;
$milestone_updated = true;
break;
}
}
if ($milestone_updated) {
return update_post_meta($project_id, $this->meta_key, $milestones);
}
return false;
}
/**
* Get single milestone by ID
*
* @param int $project_id Project ID
* @param string $milestone_id Milestone ID
* @return array|bool Milestone data or false if not found
*/
public function get_milestone($project_id, $milestone_id)
{
$milestones = $this->get_milestones($project_id);
foreach ($milestones as $milestone) {
if ($milestone[‘id’] === $milestone_id) {
return $milestone;
}
}
return false;
}
/**
* AJAX handler for deleting milestone
*/
public function ajax_delete_milestone()
{
//check_ajax_referer(‘workscout_milestone_nonce’, ‘nonce’);
$project_id = intval($_POST[‘project_id’]);
$milestone_id = sanitize_text_field($_POST[‘milestone_id’]);
// if (!$this->can_edit_milestone($project_id, $milestone_id)) {
// wp_send_json_error([‘message’ => ‘Permission denied’]);
// return;
// }
$result = $this->delete_milestone($project_id, $milestone_id);
if ($result) {
wp_send_json_success([
‘message’ => ‘Milestone deleted successfully’,
‘remaining_percentage’ => 100 – $this->get_total_milestone_percentage($project_id)
]);
} else {
wp_send_json_error([‘message’ => ‘Failed to delete milestone’]);
}
}
// Get milestone status badge HTML
public function get_status_badge($status)
{
$badges = array(
‘pending’ => ‘<span class=”badge badge-warning”>Pending Approval</span>’,
‘approved’ => ‘<span class=”badge badge-success”>Approved</span>’,
‘completed’ => ‘<span class=”badge badge-primary”>Completed</span>’
);
return isset($badges[$status]) ? $badges[$status] : ”;
}
}
class-workscout-freelancer-reviews.php
<?php
// Exit if accessed directly
if (!defined(‘ABSPATH’))
exit;
/**
* WP_listing_Manager_Content class.
*/
class WorkScout_Freelancer_Reviews
{
/**
* The single instance of the class.
*
* @var self
* @since 1.26
*/
private static $_instance = null;
private $dashboard_message = ”;
/**
* Allows for accessing single instance of class. Class should only be constructed once per call.
*
* @since 1.26
* @static
* @return self Main instance.
*/
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Constructor
*/
public function __construct()
{
add_filter(‘comment_form_fields’, array($this, ‘comments_fields’)); // add new fields
add_filter(‘comment_form_defaults’, array($this, ‘comment_form_submit_button_label’)); // add new fields
add_action(‘comment_post’, array($this, ‘save_comment_meta_data’)); // save new fields
add_action(‘comment_form_logged_in_after’, array($this, ‘comments_logged_in_fields’));
//add_action( ‘comment_form_after_fields’, array( $this,’comments_logged_in_fields’) );
add_action(‘transition_comment_status’, array($this, ‘transition_comment_callbacks’), 10, 3);
add_action(‘comment_post’, array($this, ‘add_comment_rating’), 10, 2);
add_action(‘add_meta_boxes_comment’, array($this, ‘add_custom_comment_field_meta_boxes’));
add_action(‘edit_comment’, array($this, ‘update_edit_comment’));
add_action(‘load-edit-comments.php’, array($this, ‘add_custom_fields_to_edit_comment_screen’));
add_action(‘manage_comments_custom_column’, array($this, ‘custom_rating_column’), 10, 2);
//add_filter(‘preprocess_comment’, array($this, ‘check_if_attachment_is_image’), 10, 1);
// if(get_option(‘workscout_recaptcha_reviews’)) :
// add_filter(‘preprocess_comment’, array($this, ‘validate_captcha_comment_field’), 10, 1);
// add_filter(‘comment_post_redirect’, array($this, ‘redirect_fail_captcha_comment’), 10, 2 );
// endif;
add_action(‘comment_post’, array($this, ‘save_comment_attachment’));
add_action(‘delete_comment’, array($this, ‘delete_comment_attachment’));
add_action(‘delete_comment’, array($this, ‘delete_comment_meta’));
add_shortcode(‘workscout_freelancer_reviews’, array($this, ‘workscout_freelancer_reviews’));
add_action(‘wp_ajax_workscout_review_freelancer’, array($this, ‘send_review’));
add_action(‘wp_ajax_reload_reviews’, array($this, ‘reload_reviews’));
add_action(‘wp_ajax_reply_to_review’, array($this, ‘reply_to_review’));
add_action(‘wp_ajax_edit_reply_to_review’, array($this, ‘edit_reply_to_review’));
add_action(‘wp_ajax_edit_review’, array($this, ‘edit_review’));
add_action(‘wp_ajax_workscout_get_review_form’, array($this, ‘get_review_form’));
add_action(‘wp’, array($this, ‘reviews_action_handler’));
add_action(‘wp_ajax_workscout_core_rate_review’, array($this, ‘rate_review’));
add_action(‘wp_ajax_nopriv_workscout_core_rate_review’, array($this, ‘rate_review’));
add_action(‘wp_ajax_get_comment_review_details’, array($this, ‘get_comment_review_details’));
}
public function comment_form_submit_button_label($args)
{
global $post;
if ($post && $post->post_type == ‘resume’) {
$args[‘label_submit’] = esc_html__(‘Submit Review’, ‘workscout-freelancer’);
}
return $args;
}
function reviews_action_handler()
{
global $post;
if (is_page(get_option(‘workscout_reviews_page’))) {
if (!empty($_REQUEST[‘action’]) && !empty($_REQUEST[‘_wpnonce’]) && wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘workscout_core_reviews_actions’)) {
$action = sanitize_title($_REQUEST[‘action’]);
$comment_id = absint($_REQUEST[‘comment_id’]);
$current_user = wp_get_current_user();
try {
// Get Job
$comment = get_comment($comment_id);
switch ($action) {
case ‘delete-comment’:
// Trash it
if ($current_user->ID == $comment->user_id) {
wp_trash_comment($comment_id);
// Message
$this->dashboard_message = ‘<div class=”notification closeable success”><p>’ . __(‘Review has been deleted’, ‘workscout-freelancer’) . ‘</p><a class=”close” href=”#”></a></div>’;
} else {
$this->dashboard_message = ‘<div class=”notification closeable error”><p>’ . __(‘You are trying to remove not your listing’, ‘workscout-freelancer’) . ‘</p><a class=”close” href=”#”></a></div>’;
}
break;
default:
do_action(‘workscout_core_dashboard_do_action_’ . $action);
break;
}
do_action(‘workscout_core_my_listing_do_action’, $action, $comment_id);
} catch (Exception $e) {
$this->dashboard_message = ‘<div class=”notification closeable error”>’ . $e->getMessage() . ‘</div>’;
}
}
}
}
function comments_fields($fields)
{
$type = get_post_type(get_the_ID());
$commenter = wp_get_current_commenter();
$req = get_option(‘require_name_email’);
$aria_req = ($req ? ” aria-required=’true'” : ”);
$consent = empty($commenter[‘comment_author_email’]) ? ” : ‘ checked=”checked”‘;
unset($fields[‘author’]);
unset($fields[’email’]);
unset($fields[‘url’]);
unset($fields[‘cookies’]);
$comment_field = $fields[‘comment’];
unset($fields[‘comment’]);
if ($type == ‘resume’) {
$criteria_fields = workscout_get_reviews_criteria();
ob_start();
?>
<!– Subratings Container –>
<div class=”sub-ratings-container”>
<?php foreach ($criteria_fields as $key => $value) { ?>
<!– Subrating #1 –>
<div class=”add-sub-rating”>
<div data-tippy-placement=”top” title=”<?php echo esc_html($value[‘tooltip’]); ?>” class=”sub-rating-title”><?php echo stripslashes(esc_html($value[‘label’])) ?>
<?php if (isset($value[‘tooltip’]) && !empty($value[‘tooltip’])) : ?><i class=”tip”></i> <?php endif; ?>
</div>
<div class=”sub-rating-stars”>
<!– Leave Rating –>
<div class=”clearfix”></div>
<div class=”leave-rating”>
<?php for ($i = 5; $i > 0; $i–) { ?>
<input type=”radio” name=”<?php echo $key; ?>” id=”rating-<?php echo $key . ‘-‘ . $i; ?>” value=”<?php echo $i; ?>” />
<label for=”rating-<?php echo $key . ‘-‘ . $i; ?>” class=”fa fa-star”></label>
<?php } ?>
</div>
</div>
</div>
</div>
<?php }
$rating_output = ob_get_clean();
$fields[‘rating’] = $rating_output;
}
$fields[‘author’] = ‘
<div class=”row”>
<div class=”col-md-6 comment-form-author”>’ . ‘<label for=”author”>’ . __(‘Name’, ‘workscout-freelancer’) . ($req ? ‘ <span class=”required”>*</span>’ : ”) . ‘</label> ‘ .
‘<input id=”author” name=”author” type=”text” ‘ . ($req ? ‘ required’ : ”) . ‘ value=”‘ . esc_attr($commenter[‘comment_author’]) . ‘” size=”30″‘ . $aria_req . ‘ />
</div>’;
$fields[’email’] = ‘
<div class=”col-md-6 comment-form-email”>’ . ‘<label for=”email”>’ . __(‘Email’, ‘workscout-freelancer’) . ($req ? ‘ <span class=”required”>*</span>’ : ”) . ‘</label> ‘ .
‘<input id=”email” name=”email” type=”email” ‘ . ($req ? ‘ required’ : ”) . ‘ value=”‘ . esc_attr($commenter[‘comment_author_email’]) . ‘” size=”30″‘ . $aria_req . ‘ />
</div>
</div>’;
$fields[‘comment’] = $comment_field;
if (get_option(‘workscout_recaptcha_reviews’)) :
$recaptcha_status = get_option(‘workscout_recaptcha’);
$recaptcha_version = get_option(‘workscout_recaptcha_version’);
if ($recaptcha_status && $recaptcha_version == ‘v2’) {
$fields[‘recaptcha’] =
‘<div class=”row”>
<div class=”form-row col-md-12 captcha_wrapper”>
<div class=”g-recaptcha” data-sitekey=”‘ . get_option(‘workscout_recaptcha_sitekey’) . ‘”></div>
</div>
</div>’;
}
if ($recaptcha_status && $recaptcha_version == ‘v3’) {
$fields[‘recaptcha’] = ‘
<input type=”hidden” id=”rc_action” name=”rc_action” value=”ws_review”>
<input type=”hidden” id=”token” name=”token”>’;
}
endif;
$fields[‘cookies’] = ‘<p class=”comment-form-cookies-consent”><input id=”wp-comment-cookies-consent” name=”wp-comment-cookies-consent” type=”checkbox” value=”yes”‘ . $consent . ‘ />’ .
‘<label for=”wp-comment-cookies-consent”>’ . __(‘Save my name, email, and website in this browser for the next time I comment.’, ‘workscout-freelancer’) . ‘</label></p>’;
return $fields;
}
function comments_logged_in_fields()
{
$type = get_post_type(get_the_ID());
if ($type != ‘resume’) {
return;
}
$criteria_fields = workscout_get_reviews_criteria();
?>
<!– Subratings Container –>
<div class=”sub-ratings-container”>
<?php foreach ($criteria_fields as $key => $value) { ?>
<!– Subrating #1 –>
<div class=”add-sub-rating”>
<div class=”sub-rating-title” data-tippy-placement=”top” title=”<?php echo esc_html($value[‘tooltip’]); ?>”><?php echo stripslashes(esc_html($value[‘label’])) ?>
<?php if (isset($value[‘tooltip’]) && !empty($value[‘tooltip’])) : ?><i class=”tip”></i> <?php endif; ?>
</div>
<div class=”sub-rating-stars”>
<!– Leave Rating –>
<div class=”clearfix”></div>
<div class=”leave-rating”>
<?php for ($i = 5; $i > 0; $i–) { ?>
<input type=”radio” name=”<?php echo $key; ?>” id=”rating-<?php echo $key . ‘-‘ . $i; ?>” value=”<?php echo $i; ?>” />
<label for=”rating-<?php echo $key . ‘-‘ . $i; ?>” class=”fa fa-star”></label>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
</div>
<!– Subratings Container / End –>
<?php
}
function save_comment_meta_data($comment_id)
{
$criteria_fields = workscout_get_reviews_criteria();
$count_criteria = 0;
$total_criteria = 0;
foreach ($criteria_fields as $key => $value) {
if ((isset($_POST[$key])) && ($_POST[$key] != ”)) {
$count_criteria++;
$rating = wp_filter_nohtml_kses($_POST[$key]);
$total_criteria = $total_criteria + (int) $rating;
add_comment_meta($comment_id, $key, $rating);
}
}
if ($total_criteria > 0) {
$workscout_rating = (float) $total_criteria / $count_criteria;
add_comment_meta($comment_id, ‘workscout-rating’, $workscout_rating);
}
}
function transition_comment_callbacks($new_status, $old_status, $comment)
{
if ($old_status != $new_status) {
$commentdata = get_comment($comment->comment_ID, ARRAY_A);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
if ($parent_post) {
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
$criteria_fields = workscout_get_reviews_criteria();
foreach ($criteria_fields as $key => $value) {
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
if ($reviews) {
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
}
}
}
function add_comment_rating($comment_ID, $comment_approved)
{
if (1 === $comment_approved) {
$commentdata = get_comment($comment_ID, ARRAY_A);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
$criteria_fields = workscout_get_reviews_criteria();
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
foreach ($criteria_fields as $key => $value) {
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
if (isset($reviews[‘rating’]) && !empty($reviews[‘rating’]))
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
}
public function get_average_post_rating($id, $field)
{
global $post;
$overall_ratings = 0;
$count_ratings = 0;
if (empty($id)) {
$args = array(
‘post_id’ => $post->ID,
‘status’ => ‘approve’,
‘meta_key’ => $field
);
} else {
$args = array(
‘post_id’ => $id,
‘status’ => ‘approve’,
‘meta_key’ => $field
);
}
$ratings = get_comments($args);
$count_ratings = 0;
foreach ($ratings as $rating) {
$rating_value = get_comment_meta($rating->comment_ID, $field, true);
if ($rating_value > 0) {
$overall_ratings += $rating_value;
$count_ratings++;
}
}
if ($overall_ratings == 0 || $count_ratings == 0) {
return 0;
} else {
$average_count = $overall_ratings / $count_ratings;
//$average_count = round($average_count, 0, PHP_ROUND_HALF_UP);
$reviews = array(
‘reviews’ => $count_ratings,
‘rating’ => $average_count
);
return $reviews;
}
}
function add_custom_comment_field_meta_boxes()
{
add_meta_box(‘workscout-rating’, __(‘Rating’, ‘workscout-freelancer’), array($this, ‘workscout_comment_rating_field_meta_box’), ‘comment’, ‘normal’, ‘high’);
}
function workscout_comment_rating_field_meta_box($comment)
{
$rating = get_comment_meta($comment->comment_ID, ‘workscout-rating’, true);
wp_nonce_field(‘update_comment_rating’, ‘update_comment_rating’, false);
?>
<p>
<label for=”rating”><?php esc_html_e(‘General Rating’, ‘workscout-freelancer’); ?></label>
<input type=”text” name=”workscout-rating” disabled value=”<?php echo esc_attr($rating); ?>” class=”form-table editcomment” />
</p>
<?php
$criteria_fields = workscout_get_reviews_criteria();
foreach ($criteria_fields as $key => $value) {
$key_rating = get_comment_meta($comment->comment_ID, $key, true);
?>
<p>
<label for=”rating”><?php echo esc_html($value[‘label’]); ?></label>
<input type=”text” name=”<?php echo esc_attr($key); ?>” value=”<?php echo esc_attr($key_rating); ?>” class=”form-table editcomment” />
</p>
<?php }
}
function update_edit_comment($comment_id)
{
if (!isset($_POST[‘update_comment_rating’]) || !wp_verify_nonce($_POST[‘update_comment_rating’], ‘update_comment_rating’)) return;
// if( isset( $_POST[‘workscout-rating’] ) )
// update_comment_meta( $comment_id, ‘workscout-rating’, esc_attr( $_POST[‘workscout-rating’] ) );
$criteria_fields = workscout_get_reviews_criteria();
$count_criteria = 0;
$total_criteria = 0;
foreach ($criteria_fields as $key => $value) {
if ((isset($_POST[$key])) && ($_POST[$key] != ”)) {
$count_criteria++;
$rating = wp_filter_nohtml_kses($_POST[$key]);
$total_criteria = $total_criteria + (int) $rating;
update_comment_meta($comment_id, $key, $rating);
}
}
if ($total_criteria > 0) {
$workscout_rating = (float) $total_criteria / $count_criteria;
update_comment_meta($comment_id, ‘workscout-rating’, $workscout_rating);
$commentdata = get_comment($comment_id, ARRAY_A);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
$criteria_fields = workscout_get_reviews_criteria();
foreach ($criteria_fields as $key => $value) {
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
// $criteria_fields = workscout_get_reviews_criteria();
// foreach ($criteria_fields as $key => $value) {
// if( isset( $_POST[$key] ) ){
// update_comment_meta( $comment_id, $key, esc_attr( $_POST[$key] ) );
// }
// }
}
function add_custom_fields_to_edit_comment_screen()
{
$screen = get_current_screen();
add_filter(“manage_{$screen->id}_columns”, array($this, ‘add_custom_comment_columns’));
}
function add_custom_comment_columns($cols)
{
$cols[‘rating’] = __(‘Rating’, ‘workscout-core’);
return $cols;
}
function custom_rating_column($col, $comment_id)
{
switch ($col) {
case ‘rating’:
if ($ind = get_comment_meta($comment_id, ‘workscout-rating’, true)) {
echo esc_html($ind);
} else {
esc_html_e(‘No Rating Submitted’, ‘workscout-freelancer’);
}
}
}
/**
* User bookmarks shortcode
*/
public function workscout_reviews($atts)
{
if (!is_user_logged_in()) {
return __(‘You need to be signed in to manage your reviews.’, ‘workscout-freelancer’);
}
extract(shortcode_atts(array(
‘posts_per_page’ => ’25’,
), $atts));
ob_start();
$template_loader = new workscout_Core_Template_Loader;
$template_loader->set_template_data(
array(
‘message’ => $this->dashboard_message,
‘posts_per_page’ => $posts_per_page,
//’user_reviews’ => $this->get_reviews(),
)
)->get_template_part(‘account/reviews’);
return ob_get_clean();
}
// Comments attachments
public function make_form_multipart()
{
$action = site_url(‘/wp-comments-post.php’);
//echo ‘</form><form action=”‘ . $action . ‘” method=”POST” enctype=”multipart/form-data” id=”commentform” class=”comment-form” >’;
}
public function save_comment_attachment($comment_id)
{
$id = $_POST[‘comment_post_ID’];
if ($_FILES) {
$files = $_FILES[“attachments”];
foreach ($files[‘name’] as $key => $value) {
if ($files[‘name’][$key]) {
$file = array(
‘name’ => $files[‘name’][$key],
‘type’ => $files[‘type’][$key],
‘tmp_name’ => $files[‘tmp_name’][$key],
‘error’ => $files[‘error’][$key],
‘size’ => $files[‘size’][$key]
);
$_FILES = array(“attachments” => $file);
foreach ($_FILES as $file => $array) {
$attachId = $this->insert_attachment($file, $id);
add_comment_meta($comment_id, ‘workscout-attachment-id’, $attachId);
}
}
}
unset($_FILES);
}
}
public function insert_attachment($fileHandler, $post_id)
{
require_once(ABSPATH . “wp-admin” . ‘/includes/image.php’);
require_once(ABSPATH . “wp-admin” . ‘/includes/file.php’);
require_once(ABSPATH . “wp-admin” . ‘/includes/media.php’);
return media_handle_upload($fileHandler, $post_id);
}
public function delete_comment_attachment($comment_id)
{
$attachments = get_comment_meta($comment_id, ‘workscout-attachment-id’, false);
foreach ($attachments as $key => $attachment_id) {
if (is_numeric($attachment_id) && !empty($attachment_id)) {
wp_delete_attachment($attachment_id, TRUE);
}
}
}
public function delete_comment_meta($comment_id)
{
delete_comment_meta($comment_id, ‘workscout-rating’);
$commentdata = get_comment($comment_id, ARRAY_A);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
$criteria_fields = workscout_get_reviews_criteria();
foreach ($criteria_fields as $key => $value) {
delete_comment_meta($comment_id, $key);
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
public function captcha_verification()
{
$recaptcha_version = get_option(‘workscout_recaptcha_version’);
if ($recaptcha_version == ‘v2’) {
$response = isset($_POST[‘g-recaptcha-response’]) ? esc_attr($_POST[‘g-recaptcha-response’]) : ”;
$remote_ip = $_SERVER[“REMOTE_ADDR”];
// make a GET request to the Google reCAPTCHA Server
$request = wp_remote_get(
‘https://www.google.com/recaptcha/api/siteverify?secret=’ . get_option(‘workscout_recaptcha_secretkey’) . ‘&response=’ . $response
);
// get the request response body
$response_body = wp_remote_retrieve_body($request);
$result = json_decode($response_body, true);
return $result[‘success’];
}
if ($recaptcha_version == ‘v3’) {
if (isset($_POST[‘token’]) && !empty($_POST[‘token’])) :
//your site secret key
$secret = get_option(‘workscout_recaptcha_secretkey3’);
//get verify response data
$verifyResponse = wp_remote_get(‘https://www.google.com/recaptcha/api/siteverify?secret=’ . $secret . ‘&response=’ . $_POST[‘token’]);
$responseData_w = wp_remote_retrieve_body($verifyResponse);
$responseData = json_decode($responseData_w);
if ($responseData->success == ‘1’ && $responseData->action == ‘login’ && $responseData->score >= 0.5) :
$result[‘success’];
else :
$result[‘success’] = false;
endif;
endif;
}
}
public function validate_captcha_comment_field($commentdata)
{
global $captcha_error;
if (get_option(‘workscout_recaptcha_reviews’)) :
$recaptcha_status = get_option(‘workscout_recaptcha’);
$recaptcha_version = get_option(‘workscout_recaptcha_version’);
if ($recaptcha_version = ‘v2’ && $recaptcha_status) {
if (isset($_POST[‘g-recaptcha-response’]) && !($this->captcha_verification())) {
$captcha_error = ‘failed’;
}
}
if ($recaptcha_version = ‘v3’ && $recaptcha_status) {
if (isset($_POST[‘token’]) && !empty($_POST[‘token’]) && !($this->captcha_verification())) {
$captcha_error = ‘failed’;
}
}
endif;
return $commentdata;
}
public function redirect_fail_captcha_comment($location, $comment)
{
global $captcha_error;
if (!empty($captcha_error)) {
// delete the failed captcha comment
wp_delete_comment(absint($comment->comment_ID));
// add failed query string for @parent::display_captcha to display error message
$location = add_query_arg(‘captcha’, ‘failed’, $location);
}
return $location;
}
/**
* Checks attachment, size, and type and throws error if something goes wrong.
*
* @param $data
* @return mixed
*/
public function check_if_attachment_is_image($data)
{
$image_mime_types = array(
‘image/jpeg’,
‘image/jpg’,
‘image/jp_’,
‘application/jpg’,
‘application/x-jpg’,
‘image/pjpeg’,
‘image/pipeg’,
‘image/vnd.swiftview-jpeg’,
‘image/x-xbitmap’,
‘image/gif’,
‘image/x-xbitmap’,
‘image/gi_’,
‘image/png’,
‘application/png’,
‘application/x-png’
);
$image_file_types = array(
‘jpg’,
‘jpeg’,
‘gif’,
‘png’,
);
$orginal_files = $_FILES;
if ($_FILES) {
$files = $_FILES[“attachments”];
foreach ($files[‘name’] as $key => $value) {
if ($files[‘name’][$key]) {
$file = array(
‘name’ => $files[‘name’][$key],
‘type’ => $files[‘type’][$key],
‘tmp_name’ => $files[‘tmp_name’][$key],
‘error’ => $files[‘error’][$key],
‘size’ => $files[‘size’][$key]
);
$_FILES = array(“attachments” => $file);
foreach ($_FILES as $file => $array) {
if ($array[‘size’] > 0 && $array[‘error’] == 0) {
$fileInfo = pathinfo($array[‘name’]);
$fileExtension = strtolower($fileInfo[‘extension’]);
if (function_exists(‘finfo_file’)) {
$fileType = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $array[‘tmp_name’]);
} elseif (function_exists(‘mime_content_type’)) {
$fileType = mime_content_type($array[‘tmp_name’]);
} else {
$fileType = $array[‘type’];
}
// Is: allowed mime type / file extension, and size? extension making lowercase, just to make sure
if (!in_array($fileType, $image_mime_types) || !in_array(strtolower($fileExtension), $image_file_types)) { // file size from admin
wp_die(__(‘<strong>ERROR:</strong> File you upload must be valid file type,’, ‘workscout-core’));
}
} elseif ($array[‘error’] == 1) {
wp_die(__(‘<strong>ERROR:</strong> The uploaded file exceeds the upload_max_filesize directive in php.ini.’, ‘workscout-freelancer’));
} elseif ($array[‘error’] == 2) {
wp_die(__(‘<strong>ERROR:</strong> The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.’, ‘workscout-freelancer’));
} elseif ($array[‘error’] == 3) {
wp_die(__(‘<strong>ERROR:</strong> The uploaded file was only partially uploaded. Please try again later.’, ‘workscout-freelancer’));
} elseif ($array[‘error’] == 6) {
wp_die(__(‘<strong>ERROR:</strong> Missing a temporary folder.’, ‘workscout-freelancer’));
} elseif ($array[‘error’] == 7) {
wp_die(__(‘<strong>ERROR:</strong> Failed to write file to disk.’, ‘workscout-freelancer’));
} elseif ($array[‘error’] == 7) {
wp_die(__(‘<strong>ERROR:</strong> A PHP extension stopped the file upload.’, ‘workscout-freelancer’));
}
}
}
}
}
$_FILES = $orginal_files;
return $data;
}
function reload_reviews()
{
$id = sanitize_text_field(trim($_POST[‘id’]));
$current_user = wp_get_current_user();
$limit = 2;
$visitor_reviews_page = (isset($_POST[‘page’])) ? $_POST[‘page’] : 1;
add_filter(‘comments_clauses’, ‘workscout_top_comments_only’);
$visitor_reviews_offset = ($visitor_reviews_page * $limit) – $limit;
$total_visitor_reviews = get_comments(
array(
‘orderby’ => ‘post_date’,
‘order’ => ‘DESC’,
‘status’ => ‘approve’,
‘post_author’ => $current_user->ID,
‘parent’ => 0,
‘post_id’ => $id,
‘post_type’ => ‘resume’,
)
);
$visitor_reviews_args = array(
‘post_author’ => $current_user->ID,
‘parent’ => 0,
‘status’ => ‘approve’,
‘post_type’ => ‘resume’,
‘post_id’ => $id,
‘number’ => $limit,
‘offset’ => $visitor_reviews_offset,
);
$visitor_reviews_pages = ceil(count($total_visitor_reviews) / $limit);
$visitor_reviews = get_comments($visitor_reviews_args);
remove_filter(‘comments_clauses’, ‘workscout_top_comments_only’);
ob_start();
if (empty($visitor_reviews)) : ?>
<li>
<p><?php esc_html_e(‘You don\’t have any reviews for ‘, ‘workscout-freelancer’);
echo get_the_title($id); ?></p>
</li>
<?php else :
foreach ($visitor_reviews as $review) :
?>
<li class=”review-li” data-review=”<?php echo esc_attr($review->comment_ID); ?>” id=”review-<?php echo esc_attr($review->comment_ID); ?>”>
<div class=”comments listing-reviews”>
<ul>
<li>
<div class=”avatar”><?php echo get_avatar($review, 70); ?></div>
<div class=”comment-content”>
<div class=”arrow-comment”></div>
<div class=”comment-by”><?php echo esc_html($review->comment_author); ?>
<div class=”comment-by-listing”><?php esc_html_e(‘on’, ‘workscout-freelancer’); ?>
<a href=”<?php echo esc_url(get_permalink($review->comment_post_ID)); ?>”><?php echo get_the_title(
$review->comment_post_ID
) ?></a>
</div>
<span class=”date”><?php echo date_i18n(get_option(‘date_format’), strtotime($review->comment_date), false); ?></span>
<?php
$star_rating = get_comment_meta($review->comment_ID, ‘workscout-rating’, true);
if ($star_rating) : ?>
<div class=”star-rating” data-rating=”<?php echo get_comment_meta($review->comment_ID, ‘workscout-rating’, true); ?>”></div>
<?php endif; ?>
</div>
<?php echo wpautop($review->comment_content); ?>
<?php
if (workscout_check_if_review_replied($review->comment_ID, $current_user->ID)) {
$reply = workscout_get_review_reply($review->comment_ID, $current_user->ID);
?>
<a href=”#small-dialog-edit” class=”rate-review edit-reply popup-with-zoom-anim” <?php if (!empty($reply)) : ?> data-comment-id=”<?php echo $reply[0]->comment_ID; ?>” data-comment-content=”<?php echo $reply[0]->comment_content; ?>” <?php endif; ?>><i class=”sl sl-icon-pencil”></i> <?php esc_html_e(‘Edit your reply’, ‘workscout-freelancer’) ?></a>
<?php } else { ?>
<a data-replyid=”<?php echo esc_attr($review->comment_ID); ?>” data-postid=”<?php echo esc_attr($review->comment_post_ID); ?>” href=”#small-dialog” class=”reply-to-review-link rate-review popup-with-zoom-anim”><i class=”sl sl-icon-action-undo”></i> <?php esc_html_e(‘Reply to this review’, ‘workscout-freelancer’) ?></a>
<?php } ?>
</div>
</li>
</ul>
</div>
</li>
<?php endforeach; ?>
<?php endif;
$output = ob_get_clean();
$pagination = workscout_core_ajax_pagination($visitor_reviews_pages, $visitor_reviews_page);
echo json_encode(array(‘success’ => true, ‘comments’ => $output, ‘pagination’ => $pagination));
die();
}
function get_review_form()
{
$id = sanitize_text_field(trim($_POST[‘task_id’]));
$bid_id = get_post_meta($id, ‘_selected_bid_id’, true);
$current_user = wp_get_current_user();
//get bud author
$bid_author = get_post_field(‘post_author’, $bid_id);
//get his profile
$reviewed_id = get_the_author_meta(‘freelancer_profile’, $bid_author);
if (empty($reviewed_id)) {
// get ID of last post by user
$reviewed_id = get_posts(array(
‘author’ => $bid_author,
‘posts_per_page’ => 1,
‘post_type’ => ‘resume’,
‘fields’ => ‘ids’,
‘orderby’ => ‘date’,
‘order’ => ‘DESC’
));
$reviewed_id = $reviewed_id[0];
}
// check if comment exists
$comment = get_comments(array(
‘author__in’ => array($current_user->ID),
‘post_id’ => $reviewed_id,
‘parent’ => 0,
‘fields’ => ‘ids’
));
//if comment exists, set default value for form
if (!empty($comment)) {
$comment_data = get_comment($comment[0]);
$comment_content = $comment_data->comment_content;
} else {
$comment_content = ”;
}
ob_start();
$criteria_fields = workscout_get_reviews_criteria();
?>
<form action=”” method=”POST” id=”popup-commentform” class=”comment-form”>
<!– Subratings Container –>
<div class=”sub-ratings-container”>
<?php foreach ($criteria_fields as $key => $value) {
if (isset($comment[0]) && !empty($comment[0])) {
$this_rating = get_comment_meta($comment[0], $key, true);
} else {
$this_rating = ”;
} ?>
<!– Subrating #1 –>
<div class=”add-sub-rating”>
<div data-tippy-placement=”top” title=”<?php echo esc_html($value[‘tooltip’]); ?>” class=”sub-rating-title”><?php echo stripslashes(esc_html($value[‘label’])) ?>
<?php if (isset($value[‘tooltip’]) && !empty($value[‘tooltip’])) : ?><i class=”tip”></i> <?php endif; ?>
</div>
<div class=”sub-rating-stars”>
<!– Leave Rating –>
<div class=”clearfix”></div>
<div class=”leave-rating”>
<?php for ($i = 5; $i > 0; $i–) { ?>
<input <?php checked($this_rating, $i) ?> type=”radio” name=”<?php echo $key; ?>” id=”rating-<?php echo $key . ‘-‘ . $i; ?>” value=”<?php echo $i; ?>” />
<label for=”rating-<?php echo $key . ‘-‘ . $i; ?>” class=”fa fa-star”></label>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
</div>
<p class=”comment-form-comment”><label for=”comment”>Review <span class=”required”>*</span></label>
<textarea id=”comment” name=”comment” cols=”45″ rows=”8″ maxlength=”65525″ required=””><?php echo $comment_content; ?></textarea>
</p>
<p class=”form-submit”>
<?php if (!empty($comment)) { ?>
<input name=”submit” type=”submit” id=”submit” class=”submit” value=”Update Review”>
<input type=”hidden” name=”comment_id” value=”<?php echo $comment[0]; ?>” id=”comment_id”>
<?php } else { ?>
<input name=”submit” type=”submit” id=”submit” class=”submit” value=”Submit Review”>
<?php } ?>
<input type=”hidden” name=”comment_post_ID” value=”<?php echo $reviewed_id; ?>” id=”comment_post_ID”>
<input type=”hidden” name=”task_id” value=”<?php echo $id; ?>” id=”task_id”>
<input type=”hidden” name=”comment_parent” id=”comment_parent” value=”0″>
</p>
</form>
<?php
$message = ob_get_clean();
$return = array(
‘message’ => $message,
);
wp_send_json($return);
}
function reply_to_review()
{
global $post; //for this example only 🙂
$current_user = wp_get_current_user();
$post_id = sanitize_text_field(trim($_POST[‘post_id’]));
$review_id = sanitize_text_field(trim($_POST[‘review_id’]));
$content = sanitize_text_field(trim($_POST[‘content’]));
$commentdata = array(
‘comment_post_ID’ => $post_id, // to which post the comment will show up
‘comment_author’ => $current_user->display_name, //fixed value – can be dynamic
‘comment_author_email’ => $current_user->user_email, //fixed value – can be dynamic
‘comment_content’ => $content, //fixed value – can be dynamic
‘comment_type’ => ”, //empty for regular comments, ‘pingback’ for pingbacks, ‘trackback’ for trackbacks
‘comment_parent’ => $review_id, //0 if it’s not a reply to another comment; if it’s a reply, mention the parent comment ID here
‘comment_date’ => date(‘Y-m-d H:i:s’),
‘comment_date_gmt’ => date(‘Y-m-d H:i:s’),
‘comment_approved’ => 1,
‘user_id’ => $current_user->ID, //passing current user ID or any predefined as per the demand
);
//Insert new comment and get the comment ID
$comment_id = wp_new_comment($commentdata);
if ($comment_id !== 0) {
echo json_encode(array(‘success’ => true));
} else {
echo json_encode(array(‘success’ => false));
}
die();
}
public function edit_reply_to_review()
{
global $post; //for this example only 🙂
$current_user = wp_get_current_user();
$reply_id = sanitize_text_field(trim($_POST[‘reply_id’]));
$content = sanitize_text_field(trim($_POST[‘content’]));
$commentdata = array(
‘comment_ID’ => $reply_id,
‘comment_content’ => $content, //fixed value – can be dynamic
‘comment_date’ => date(‘Y-m-d H:i:s’),
‘comment_date_gmt’ => date(‘Y-m-d H:i:s’),
‘comment_approved’ => !get_option(‘comment_moderation’),
‘user_id’ => $current_user->ID, //passing current user ID or any predefined as per the demand
);
//Insert new comment and get the comment ID
$result = wp_update_comment($commentdata);
if ($result == 1) {
echo json_encode(array(‘success’ => true));
} else {
echo json_encode(array(‘success’ => false));
}
die();
}
public function send_review()
{
parse_str($_REQUEST[‘data’], $commentdata);
$time = current_time(‘mysql’);
$author = get_current_user_id();
$user_email = get_the_author_meta(‘user_email’, $author);
// review for profile page of
// Set the arguments
$data = array(
‘comment_post_ID’ => $commentdata[‘comment_post_ID’],
‘comment_author’ => workscout_get_users_name($author),
‘comment_author_email’ => $user_email,
‘comment_author_url’ => ”,
‘comment_content’ => $commentdata[‘comment’],
‘comment_type’ => ”,
‘comment_parent’ => 0,
‘user_id’ => $author,
‘comment_author_IP’ => ”,
‘comment_agent’ => ”,
‘comment_date’ => $time,
‘comment_approved’ => 1,
);
// Store the ID in a variable
if(isset($commentdata[‘comment_id’])){
$reply_id = wp_update_comment($data);
} else {
$reply_id = wp_insert_comment($data);
}
if (is_wp_error($reply_id)) {
wp_send_json_error($reply_id->get_error_message());
}
update_comment_meta($reply_id, ‘review_for_task_id’, $commentdata[‘task_id’]);
$criteria_fields = workscout_get_reviews_criteria();
$count_criteria = 0;
$total_criteria = 0;
foreach ($criteria_fields as $key => $value) {
if ((isset($commentdata[$key])) && ($commentdata[$key] != ”)) {
$count_criteria++;
$rating = wp_filter_nohtml_kses($commentdata[$key]);
$total_criteria = $total_criteria + (int) $rating;
update_comment_meta($reply_id, $key, $rating);
}
}
if ($total_criteria > 0) {
$workscout_rating = (float) $total_criteria / $count_criteria;
update_comment_meta($reply_id, ‘workscout-rating’, $workscout_rating);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
if (!empty($reviews)) {
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
}
foreach ($criteria_fields as $key => $value) {
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
if (!empty($reviews)) {
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
}
if ($data) {
echo json_encode(array(
‘success’ => true,
‘message’ => esc_html__(‘Thank you for your review!’, ‘workscout-freelancer’)
));
} else {
echo json_encode(array(‘success’ => false));
}
die();
}
public function edit_review()
{
global $post; //for this example only 🙂
$current_user = wp_get_current_user();
$reply_id = sanitize_text_field(trim($_POST[‘reply_id’]));
$content = sanitize_textarea_field(trim($_POST[‘content’]));
$commentdata = array(
‘comment_ID’ => $reply_id,
‘comment_content’ => $content, //fixed value – can be dynamic
‘comment_date’ => date(‘Y-m-d H:i:s’),
‘comment_date_gmt’ => date(‘Y-m-d H:i:s’),
‘comment_approved’ => 0,
‘user_id’ => $current_user->ID, //passing current user ID or any predefined as per the demand
);
//Insert new comment and get the comment ID
$result = wp_update_comment($commentdata);
if ($result == 1) {
$criteria_fields = workscout_get_reviews_criteria();
$count_criteria = 0;
$total_criteria = 0;
foreach ($criteria_fields as $key => $value) {
if ((isset($_POST[‘rating_’ . $key])) && ($_POST[‘rating_’ . $key] != ”)) {
$count_criteria++;
$rating = wp_filter_nohtml_kses($_POST[‘rating_’ . $key]);
$total_criteria = $total_criteria + (int) $rating;
update_comment_meta($reply_id, $key, $rating);
}
}
if ($total_criteria > 0) {
$workscout_rating = (float) $total_criteria / $count_criteria;
update_comment_meta($reply_id, ‘workscout-rating’, $workscout_rating);
$commentdata = get_comment($reply_id, ARRAY_A);
$parent_post = get_post($commentdata[‘comment_post_ID’]);
$reviews = $this->get_average_post_rating($parent_post->ID, ‘workscout-rating’);
if (!empty($reviews)) {
update_post_meta($parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
}
foreach ($criteria_fields as $key => $value) {
$reviews = $this->get_average_post_rating($parent_post->ID, $key);
if (!empty($reviews)) {
update_post_meta($parent_post->ID, $key . ‘-avg’, $reviews[‘rating’]);
}
}
}
// if ( ( isset( $_POST[‘rating’] ) ) && ( $_POST[‘rating’] != ”) ) {
// $rating = wp_filter_nohtml_kses($_POST[‘rating’]);
// update_comment_meta( $reply_id, ‘workscout-rating’, $rating );
// $commentdata = get_comment($reply_id, ARRAY_A);
// $parent_post = get_post($commentdata[‘comment_post_ID’]);
// $reviews = $this->get_average_post_rating($parent_post->ID);
// update_post_meta( $parent_post->ID, ‘workscout-avg-rating’, $reviews[‘rating’]);
echo json_encode(array(‘success’ => true));
} else {
echo json_encode(array(‘success’ => false));
}
die();
}
function rate_review()
{
$comment_id = $_POST[‘comment’];
if (isset($_COOKIE[‘workscout_rate_review_’ . $comment_id])) {
$result[‘type’] = ‘error’;
$result[‘output’] = ‘<i class=”sl sl-icon-like”></i> ‘ . esc_html__(‘You already voted ‘, ‘workscout-freelancer’);
} else {
$rating = (int) get_comment_meta($comment_id, ‘workscout-review-rating’, true);
$new_rating = $rating + 1;
$update = update_comment_meta($comment_id, ‘workscout-review-rating’, $new_rating);
$new_rating = (int) get_comment_meta($comment_id, ‘workscout-review-rating’, true);
if ($update) {
$result[‘type’] = ‘success’;
$result[‘output’] = ‘<i class=”sl sl-icon-like”></i> ‘ . esc_html__(‘Helpful Review ‘, ‘workscout-freelancer’) . ‘<span>’ . $new_rating . ‘</span>’;
// Set a cookie. Change “August 15, 2016” to the date you want the cookie to expire.
setcookie(‘workscout_rate_review_’ . $comment_id, $comment_id, 0, COOKIEPATH, COOKIE_DOMAIN, false, false);
} else {
$result[‘type’] = ‘error’;
$result[‘output’] = ‘<i class=”sl sl-icon-like”></i> ‘ . esc_html__(‘Helpful Review ‘, ‘workscout-freelancer’) . ‘<span>’ . $new_rating . ‘</span>’;
}
}
wp_send_json($result);
die();
}
function get_comment_review_details()
{
$comment_id = $_POST[‘comment’];
$commentdata = get_comment($comment_id);
$result = array();
$result[‘comment_content’] = $commentdata->comment_content;
$result[‘rating’] = get_comment_meta($comment_id, ‘workscout-rating’, true);
$criteria_fields = workscout_get_reviews_criteria();
ob_start();
foreach ($criteria_fields as $key => $value) {
$this_rating = get_comment_meta($comment_id, $key, true); ?>
<!– Subrating #1 –>
<div class=”add-sub-rating”>
<div data-tippy-placement=”top” title=”<?php echo esc_html($value[‘tooltip’]); ?>” class=”sub-rating-title”><?php echo esc_html($value[‘label’]) ?>
<?php if (isset($value[‘tooltip’]) && !empty($value[‘tooltip’])) : ?><i class=”tip”></i> <?php endif; ?>
</div>
<div class=”sub-rating-stars”>
<!– Leave Rating –>
<div class=”clearfix”></div>
<div class=”leave-rating”>
<?php for ($i = 5; $i > 0; $i–) { ?>
<input <?php checked($this_rating, $i) ?> type=”radio” name=”<?php echo $key; ?>” id=”rating-<?php echo $key . ‘-‘ . $i; ?>” value=”<?php echo $i; ?>” />
<label for=”rating-<?php echo $key . ‘-‘ . $i; ?>” class=”fa fa-star”></label>
<?php } ?>
</div>
</div>
</div>
<?php }
$result[‘ratings’] = ob_get_clean();
// foreach ($criteria_fields as $key => $value) {
// $this_rating = get_comment_meta( $comment_id, $key, true );
// workscout_write_log($this_rating);
// $result[$key] = $this_rating;
// }
wp_send_json($result);
die();
}
}
class-workscout-freelancer-shortcodes.php
<?php
/**
* File containing the class WorkScout_Freelancer_Shortcodes.
*
* @package wp-job-manager-tasks
*/
if (!defined(‘ABSPATH’)) {
exit; // Exit if accessed directly.
}
/**
* WorkScout_Freelancer_Shortcodes class.
*/
class WorkScout_Freelancer_Shortcodes
{
private $task_dashboard_message = ”;
/**
* Constructor
*/
public function __construct()
{
add_action(‘wp’, [$this, ‘handle_redirects’]);
add_action(‘wp’, [$this, ‘shortcode_action_handler’]);
add_shortcode(‘workscout_submit_task’, [$this, ‘submit_task_form’]);
add_shortcode(‘workscout_task_dashboard’, [$this, ‘task_dashboard’]);
add_shortcode(‘workscout_project_dashboard’, [$this, ‘project_dashboard’]);
add_shortcode(‘workscout_my_bids’, [$this, ‘task_my_bids’]);
add_action(‘workscout_freelancer_task_dashboard_content_view-project’, [$this, ‘load_project_view’]);
add_shortcode(‘workscout_freelancer_project_view’, [$this, ‘freelancer_project_view’]);
add_shortcode(‘tasks’, [$this, ‘output_tasks’]);
// add_action( ‘workscout_freelancer_output_tasks_no_results’, [ $this, ‘output_no_results’ ] );
}
/**
* Handle redirects
*/
public function handle_redirects()
{
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
if (!get_current_user_id() || (!empty($_REQUEST[‘task_id’]) && workscout_freelancer_user_can_edit_task(intval($_REQUEST[‘task_id’])))) {
return;
}
$submit_task_form_page_id = get_option(‘workscout_freelancer_submit_task_form_page_id’);
$submission_limit = get_option(‘workscout_freelancer_submission_limit’);
//$task_count = workscout_freelancer_count_user_tasks();
$task_count = 0;
if (
$submit_task_form_page_id
&& $submission_limit
&& $task_count >= $submission_limit
&& is_page($submit_task_form_page_id)
) {
$task_dashboard_page_id = get_option(‘workscout_freelancer_task_dashboard_page_id’);
if ($task_dashboard_page_id) {
$redirect_url = get_permalink($task_dashboard_page_id);
} else {
$redirect_url = home_url(‘/’);
}
/**
* Filter on the URL visitors will be redirected upon exceeding submission limit.
*
* @since 1.18.0
*
* @param string $redirect_url URL to redirect when user has exceeded submission limit.
* @param int $submission_limit Maximum number of listings a user can submit.
* @param int $task_count Number of tasks the user has submitted.
*/
$redirect_url = apply_filters(
‘workscout_freelancer_redirect_url_exceeded_listing_limit’,
$redirect_url,
$submission_limit,
$task_count
);
if ($redirect_url) {
wp_safe_redirect(esc_url($redirect_url));
exit;
}
}
}
/**
* Handle actions which need to be run before the shortcode e.g. post actions
*/
public function shortcode_action_handler()
{
global $post;
/**
* Force the shortcode handler to run.
*
* @param bool $force_shortcode_action_handler Whether it should be forced to run.
*/
$force_shortcode_action_handler = apply_filters(‘workscout_freelancer_force_shortcode_action_handler’, false);
if (is_page() && strstr($post->post_content, ‘[workscout_task_dashboard’) || $force_shortcode_action_handler) {
$this->task_dashboard_handler();
}
if (is_page() && strstr($post->post_content, ‘[candidate_dashboard’) || $force_shortcode_action_handler) {
$this->candidate_dashboard_handler();
}
}
/**
* Show the task submission form
*/
public function submit_task_form($atts = [])
{
return $GLOBALS[‘workscout_freelancer’]->forms->get_form(‘submit-task’, $atts);
}
/**
* Handles actions on candidate dashboard
*/
public function candidate_dashboard_handler() {
if (!empty($_REQUEST[‘action’]) && !empty($_REQUEST[‘_wpnonce’]) && wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘resume_manager_my_resume_actions’)) {
$action = sanitize_title($_REQUEST[‘action’]);
$resume_id = absint($_REQUEST[‘resume_id’]);
try {
// Get resume
$resume = get_post($resume_id);
// Check ownership
if (!$resume || $resume->post_author != get_current_user_id()) {
throw new Exception(__(‘Invalid Resume ID’, ‘wp-job-manager-resumes’));
}
$user_id = get_current_user_id();
switch ($action) {
case ‘set_as_profile’:
// Trash it
//get current user id
//save resume id as user meta ‘freelancer_profile’
update_user_meta($user_id, ‘freelancer_profile’, $resume_id);
// Message
//$this->resume_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been set as your Freelancer profile’, ‘wp-job-manager-resumes’), $resume->post_title) . ‘</div>’;
break;
case ‘unset_as_profile’:
// Trash it
//remove user meta ‘freelancer_profile’
delete_user_meta($user_id, ‘freelancer_profile’);
// Message
//$this->resume_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been set as your Freelancer profile’, ‘wp-job-manager-resumes’), $resume->post_title) . ‘</div>’;
break;
}
do_action(‘resume_manager_my_resume_do_action’, $action, $resume_id);
} catch (Exception $e) {
//$this->resume_dashboard_message = ‘<div class=”job-manager-error”>’ . $e->getMessage() . ‘</div>’;
}
}
}
/**
* Handles actions on candidate dashboard
*/
public function task_dashboard_handler()
{
if (!empty($_REQUEST[‘action’]) && !empty($_REQUEST[‘_wpnonce’]) && wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘workscout_freelancer_my_task_actions’)) {
$action = sanitize_title($_REQUEST[‘action’]);
$task_id = absint($_REQUEST[‘task_id’]);
try {
// Get task
$task = get_post($task_id);
// Check ownership
if (!$task || $task->post_author != get_current_user_id()) {
throw new Exception(__(‘Invalid Task ID’, ‘workscout-freelancer’));
}
switch ($action) {
case ‘delete’:
// Trash it
wp_trash_post($task_id);
// Message
$this->task_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been deleted’, ‘workscout-freelancer’), $task->post_title) . ‘</div>’;
break;
case ‘hide’:
if ($task->post_status === ‘publish’) {
$update_task = [
‘ID’ => $task_id,
‘post_status’ => ‘hidden’,
];
wp_update_post($update_task);
$this->task_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been hidden’, ‘workscout-freelancer’), $task->post_title) . ‘</div>’;
}
break;
case ‘completed’:
if ($task->post_status === ‘in_progress’) {
$update_task = [
‘ID’ => $task_id,
‘post_status’ => ‘completed’,
];
wp_update_post($update_task);
// get the bid
$bid_id = get_post_meta($task_id, ‘_selected_bid_id’, true);
//set bid post status as closed
if($bid_id){
$update_bid = [
‘ID’ => $bid_id,
‘post_status’ => ‘closed’,
];
wp_update_post($update_bid);
}
$this->task_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been completed’, ‘workscout-freelancer’), $task->post_title) . ‘</div>’;
}
break;
case ‘publish’:
if ($task->post_status === ‘hidden’) {
$update_task = [
‘ID’ => $task_id,
‘post_status’ => ‘publish’,
];
wp_update_post($update_task);
$this->task_dashboard_message = ‘<div class=”job-manager-message”>’ . sprintf(__(‘%s has been published’, ‘workscout-freelancer’), $task->post_title) . ‘</div>’;
}
break;
case ‘relist’:
// redirect to post page
wp_redirect(add_query_arg([‘task_id’ => absint($task_id)], get_permalink(get_option(‘workscout_freelancer_submit_task_form_page_id’))));
break;
}
do_action(‘workscout_freelancer_my_task_do_action’, $action, $task_id);
} catch (Exception $e) {
$this->task_dashboard_message = ‘<div class=”job-manager-error”>’ . $e->getMessage() . ‘</div>’;
}
}
}
/**
* Add a flash message to display on a candidate dashboard.
*
* @param string $message Flash message to show on candidate dashboard.
* @param bool $is_error True this message is an error.
*
* @return bool
*/
public static function add_task_dashboard_message($message, $is_error = false)
{
$task_dashboard_page_id = get_option(‘workscout_freelancer_task_dashboard_page_id’);
if (!wp_get_session_token() || !$task_dashboard_page_id) {
// We only handle flash messages when the candidate dashboard page ID is set and user has valid session token.
return false;
}
$messages_key = self::get_task_dashboard_message_key();
$messages = self::get_task_dashboard_messages(false);
$messages[] = [
‘message’ => $message,
‘is_error’ => $is_error,
];
set_transient($messages_key, wp_json_encode($messages), HOUR_IN_SECONDS);
return true;
}
/**
* Gets the current flash messages for the candidate dashboard.
*
* @param bool $clear Flush messages after retrieval.
* @return array
*/
private static function get_task_dashboard_messages($clear)
{
$messages_key = self::get_task_dashboard_message_key();
$messages = get_transient($messages_key);
if (empty($messages)) {
$messages = [];
} else {
$messages = json_decode($messages, true);
}
if ($clear) {
delete_transient($messages_key);
}
return $messages;
}
/**
* Get the transient key to use to store candidate dashboard messages.
*
* @return string
*/
private static function get_task_dashboard_message_key()
{
return ‘task_dashboard_messages_’ . md5(wp_get_session_token());
}
function freelancer_project_view($atts){
global $workscout_freelancer;
if (!is_user_logged_in()) {
ob_start();
get_job_manager_template(‘task-dashboard-login.php’, [], ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’);
return ob_get_clean();
}
$posts_per_page = isset($atts[‘posts_per_page’]) ? intval($atts[‘posts_per_page’]) : 25;
ob_start();
// If doing an action, show conditional content if needed….
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
$action = isset($_REQUEST[‘action’]) ? sanitize_title(wp_unslash($_REQUEST[‘action’])) : false;
if (!empty($action)) {
// Show alternative content if a plugin wants to.
if (has_action(‘workscout_freelancer_task_dashboard_content_’ . $action)) {
do_action(‘workscout_freelancer_task_dashboard_content_’ . $action, $atts);
return ob_get_clean();
}
}
// ….If not show the candidate dashboard
$args = apply_filters(
‘workscout_freelancer_get_dashboard_projects_args’,
[
‘post_type’ => ‘project’,
‘post_status’ => [‘publish’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’],
‘ignore_sticky_posts’ => 1,
‘posts_per_page’ => $posts_per_page,
‘offset’ => (max(1, get_query_var(‘paged’)) – 1) * $posts_per_page,
‘orderby’ => ‘date’,
‘order’ => ‘desc’,
]
);
// query only posts that have meta field “_freelancer_id” with value of current user id
// check current user role
$current_user = wp_get_current_user();
$roles = $current_user->roles;
//_employer_id
if (array_intersect($roles, array(‘administrator’, ‘admin’, ’employer’))) {
$args[‘meta_query’] = [
[
‘key’ => ‘_employer_id’,
‘value’ => get_current_user_id(),
‘compare’ => ‘=’,
],
];
} else {
$args[‘meta_query’] = [
[
‘key’ => ‘_freelancer_id’,
‘value’ => get_current_user_id(),
‘compare’ => ‘=’,
],
];
}
if (isset($_REQUEST[‘sort-by’]) && $_REQUEST[‘sort-by’] != ”) {
if ($_REQUEST[‘sort-by’] == ‘active’) {
$statuses = [‘publish’];
} else {
$statuses = [‘closed’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’];
}
$args[‘post_status’] = $statuses;
}
$projects = new WP_Query();
get_job_manager_template(
‘my-projects.php’,
[
‘projects’ => $projects->query($args),
‘max_num_pages’ => $projects->max_num_pages,
//’task_dashboard_columns’ => $task_dashboard_columns,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
return ob_get_clean();
}
function load_project_view(){
// get_job_manager_template(
// ‘project-view.php’,
// [
// ‘project’ => get_post($_REQUEST[‘project_id’])
// ],
// ‘workscout-freelancer’,
// WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
// );
$project_id = absint($_REQUEST[‘project_id’]);
$project = get_post($project_id);
// Permissions
//AD LATER
// if (! job_manager_user_can_edit_job($job_id)) {
// _e(‘You do not have permission to view this job.’, ‘wp-job-manager-applications’);
// return;
// }
//wp_enqueue_script(‘wp-job-manager-applications-dashboard’);
get_job_manager_template(
‘project-view.php’,
[
‘project’ => get_post($_REQUEST[‘project_id’])
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
}
//comment
function add_comment() {
$post_id =123; // Your project post ID:
if ($_SERVER[‘REQUEST_METHOD’] == ‘POST’ && isset($_POST[‘submit_comment’])) {
$comment_author = wp_get_current_user();
$time = current_time(‘mysql’);
$data = array(
‘comment_post_ID’ => $post_id,
‘comment_author’ => $comment_author->display_name,
‘comment_author_email’ => $comment_author->user_email,
‘comment_author_url’ => $comment_author->user_url,
‘comment_content’ => $_POST[‘comment_content’],
‘comment_type’ => ”,
‘comment_parent’ => 0,
‘user_id’ => $comment_author->ID,
‘comment_date’ => $time,
‘comment_approved’ => 1,
);
wp_new_comment($data);
}
}
/**
* Shortcode which lists the logged in user’s tasks
*/
public function task_dashboard($atts)
{
global $workscout_freelancer;
if (!is_user_logged_in()) {
ob_start();
get_job_manager_template(‘task-dashboard-login.php’, [], ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’);
return ob_get_clean();
}
$posts_per_page = isset($atts[‘posts_per_page’]) ? intval($atts[‘posts_per_page’]) : 25;
wp_enqueue_script(‘wp-task-manager-candidate-dashboard’);
// If doing an action, show conditional content if needed….
if (!empty($_REQUEST[‘action’])) {
$action = sanitize_title($_REQUEST[‘action’]);
switch ($action) {
case ‘edit’:
return $workscout_freelancer->forms->get_form(‘edit-task’);
break;
}
}
ob_start();
// If doing an action, show conditional content if needed….
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
$action = isset($_REQUEST[‘action’]) ? sanitize_title(wp_unslash($_REQUEST[‘action’])) : false;
if (!empty($action)) {
// Show alternative content if a plugin wants to.
if (has_action(‘workscout_freelancer_task_dashboard_content_’ . $action)) {
do_action(‘workscout_freelancer_task_dashboard_content_’ . $action, $atts);
return ob_get_clean();
}
}
// ….If not show the candidate dashboard
$args = apply_filters(
‘workscout_freelancer_get_dashboard_tasks_args’,
[
‘post_type’ => ‘task’,
‘post_status’ => [‘in_progress’, ‘publish’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’, ‘completed’],
//’ignore_sticky_posts’ => 1,
‘posts_per_page’ => $posts_per_page,
‘offset’ => (max(1, get_query_var(‘paged’)) – 1) * $posts_per_page,
‘orderby’ => ‘date’,
‘order’ => ‘desc’,
‘author’ => get_current_user_id(),
]
);
if(isset($_REQUEST[‘sort-by’]) && $_REQUEST[‘sort-by’] != ”){
$args[‘post_status’] = $_REQUEST[‘sort-by’];
}
$tasks = new WP_Query();
echo wp_kses_post($this->task_dashboard_message);
// Get the flash messages sent by external handlers.
$messages = self::get_task_dashboard_messages(true);
foreach ($messages as $message) {
$div_class = ‘job-manager-message’;
if (!empty($message[‘is_error’])) {
$div_class = ‘job-manager-error’;
}
echo ‘<div class=”‘ . esc_attr($div_class) . ‘”>’ . wp_kses_post($message[‘message’]) . ‘</div>’;
}
$task_dashboard_columns = apply_filters(
‘workscout_freelancer_task_dashboard_columns’,
[
‘task-title’ => __(‘Name’, ‘workscout-freelancer’),
‘task-bidders’ => __(‘Bids’, ‘workscout-freelancer’),
‘task-bid-info’ => __(‘Info’, ‘workscout-freelancer’),
‘task-category’ => __(‘Title’, ‘workscout-freelancer’),
// ‘date’ => __(‘Date Posted’, ‘workscout-freelancer’),
]
);
if (!get_option(‘workscout_freelancer_enable_categories’)) {
unset($task_dashboard_columns[‘task-category’]);
}
get_job_manager_template(
‘task-dashboard.php’,
[
‘tasks’ => $tasks->query($args),
‘max_num_pages’ => $tasks->max_num_pages,
‘task_dashboard_columns’ => $task_dashboard_columns,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
return ob_get_clean();
}
/**
* output_tasks function.
*
* @access public
* @param mixed $args
* @return void
*/
public function output_tasks($atts)
{
ob_start();
extract($atts = shortcode_atts(apply_filters(‘workscout_freelancer_tasks_output_defaults’, array(
‘style’ => ‘list’, //compact, grid
‘layout_switch’ => ‘off’,
‘list_top_buttons’ => ‘filters|order|layout|radius’, //filters|order|layout
‘per_page’ => Kirki::get_option(‘workscout’, ‘tasks_per_page’),
‘orderby’ => ”,
‘order’ => ”,
‘keyword’ => ”,
‘location’ => ”,
‘search_radius’ => ”,
‘radius_type’ => ”,
‘featured’ => null, // True to show only featured, false to hide featured, leave null to show both.
‘custom_class’ => ”,
‘grid_columns’ => ‘2’,
‘in_rows’ => ”,
‘ajax_browsing’ => get_option(‘task_ajax_browsing’),
‘from_vs’ => ”,
)),
$atts
));
$template_loader = new WorkScout_Freelancer_Template_Loader;
$ordering_args = WorkScout_Freelancer_Task::get_task_ordering_args ($orderby, $order);
wp_enqueue_script(“workscout-freelancer-ajaxsearch”);
$get_tasks = array_merge($atts, array(
‘posts_per_page’ => $per_page,
‘orderby’ => $ordering_args[‘orderby’],
‘order’ => $ordering_args[‘order’],
‘keyword_search’ => $keyword,
‘search_keywords’ => $keyword,
‘location_search’ => $location,
‘search_radius’ => $search_radius,
‘radius_type’ => $radius_type,
‘listeo_orderby’ => $orderby,
));
switch ($style) {
case ‘list’:
$template_style = ”;
$list_class = ”;
break;
case ‘compact’:
$template_style = ”;
$list_class = ‘compact-list’;
break;
case ‘grid’:
$template_style = ‘grid’;
$list_class = ‘tasks-grid-layout’;
break;
default:
$template_style = ”;
$list_class = ”;
break;
}
$get_tasks[‘featured’] = $featured;
$tasks_query = WorkScout_Freelancer_Task::get_tasks(apply_filters(‘workscout_freelancer_output_defaults_args’, $get_tasks));
if ($tasks_query->have_posts()) {
$style_data = array(
‘style’ => $style,
‘class’ => $custom_class,
‘in_rows’ => $in_rows,
‘grid_columns’ => $grid_columns,
‘per_page’ => $per_page,
‘max_num_pages’ => $tasks_query->max_num_pages,
‘counter’ => $tasks_query->found_posts,
‘ajax_browsing’ => $ajax_browsing,
);
$search_data = array_merge($style_data, $get_tasks);
$template_loader->set_template_data( $search_data )->get_template_part( ‘tasks-start’ );
while ($tasks_query->have_posts()) {
// Loop through listings
// Setup listing data
$tasks_query->the_post();
$template_loader->set_template_data( $style_data )->get_template_part( ‘content-task’, $template_style );
}
if($style_data[‘ajax_browsing’]){?>
</div>
<div class=”pagination-container ajax-search”>
<?php
echo workscout_core_ajax_pagination($tasks_query->max_num_pages, 1 ); ?>
</div>
<?php } else {
$template_loader->set_template_data( $style_data )->get_template_part( ‘tasks-end’ );
}
} else {
$template_loader->get_template_part( ‘archive/no-found’ );
}
wp_reset_query();
return ob_get_clean();
}
/**
* Output some content when no results were found
*/
public function output_no_results()
{
get_job_manager_template(‘content-no-tasks-found.php’, [], ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’);
}
/**
* Get string as a bool
*
* @param string $value
* @return bool
*/
public function string_to_bool($value)
{
return (is_bool($value) && $value) || in_array($value, [‘1’, ‘true’, ‘yes’]) ? true : false;
}
function task_my_bids(){
global $workscout_freelancer;
if (!is_user_logged_in()) {
ob_start();
get_job_manager_template(‘task-dashboard-login.php’, [], ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’);
return ob_get_clean();
}
$posts_per_page = isset($atts[‘posts_per_page’]) ? intval($atts[‘posts_per_page’]) : 25;
// // If doing an action, show conditional content if needed….
// if (!empty($_REQUEST[‘action’])) {
// $action = sanitize_title($_REQUEST[‘action’]);
// switch ($action) {
// case ‘edit’:
// return $workscout_freelancer->forms->get_form(‘edit-task’);
// }
// }
ob_start();
// If doing an action, show conditional content if needed….
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
// $action = isset($_REQUEST[‘action’]) ? sanitize_title(wp_unslash($_REQUEST[‘action’])) : false;
// if (!empty($action)) {
// // Show alternative content if a plugin wants to.
// if (has_action(‘workscout_freelancer_task_dashboard_content_’ . $action)) {
// do_action(‘workscout_freelancer_task_dashboard_content_’ . $action, $atts);
// return ob_get_clean();
// }
// }
// ….If not show the candidate dashboard
$args = apply_filters(
‘workscout_freelancer_get_dashboard_tasks_args’,
[
‘post_type’ => ‘bid’,
‘post_status’ => [‘publish’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’],
‘ignore_sticky_posts’ => 1,
‘posts_per_page’ => $posts_per_page,
‘offset’ => (max(1, get_query_var(‘paged’)) – 1) * $posts_per_page,
‘orderby’ => ‘date’,
‘order’ => ‘desc’,
‘author’ => get_current_user_id(),
]
);
if (isset($_REQUEST[‘sort-by’]) && $_REQUEST[‘sort-by’] != ”) {
if($_REQUEST[‘sort-by’] == ‘active’) {
$statuses = [‘publish’];
} else {
$statuses = [ ‘closed’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’];
}
$args[‘post_status’] = $statuses;
}
$bids = new WP_Query();
get_job_manager_template(
‘my-bids.php’,
[
‘bids’ => $bids->query($args),
‘max_num_pages’ => $bids->max_num_pages,
//’task_dashboard_columns’ => $task_dashboard_columns,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
}
/**
* Show the project dashboard
*/
public function project_dashboard($atts){
global $workscout_freelancer;
if (!is_user_logged_in()) {
ob_start();
get_job_manager_template(‘task-dashboard-login.php’, [], ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’);
return ob_get_clean();
}
$posts_per_page = isset($atts[‘posts_per_page’]) ? intval($atts[‘posts_per_page’]) : 25;
wp_enqueue_script(‘wp-task-manager-candidate-dashboard’);
// If doing an action, show conditional content if needed….
if (!empty($_REQUEST[‘action’])) {
$action = sanitize_title($_REQUEST[‘action’]);
// switch ($action) {
// case ‘edit’:
// return $workscout_freelancer->forms->get_form(‘edit-task’);
// }
}
ob_start();
// If doing an action, show conditional content if needed….
// phpcs:ignore WordPress.Security.NonceVerification.Recommended — Input is used safely.
$action = isset($_REQUEST[‘action’]) ? sanitize_title(wp_unslash($_REQUEST[‘action’])) : false;
if (!empty($action)) {
// Show alternative content if a plugin wants to.
if (has_action(‘workscout_freelancer_project_dashboard_content_’ . $action)) {
do_action(‘workscout_freelancer_project_dashboard_content_’ . $action, $atts);
return ob_get_clean();
}
}
// ….If not show the candidate dashboard
$args = apply_filters(
‘workscout_freelancer_get_dashboard_project_args’,
[
‘post_type’ => ‘project’,
‘post_status’ => [‘in_progress’, ‘publish’, ‘expired’, ‘pending’, ‘hidden’, ‘preview’, ‘completed’],
//’ignore_sticky_posts’ => 1,
‘posts_per_page’ => $posts_per_page,
‘offset’ => (max(1, get_query_var(‘paged’)) – 1) * $posts_per_page,
‘orderby’ => ‘date’,
‘order’ => ‘desc’,
‘author’ => get_current_user_id(),
]
);
if (isset($_REQUEST[‘sort-by’]) && $_REQUEST[‘sort-by’] != ”) {
$args[‘post_status’] = $_REQUEST[‘sort-by’];
}
$projects = new WP_Query();
echo wp_kses_post($this->task_dashboard_message);
// Get the flash messages sent by external handlers.
$messages = self::get_task_dashboard_messages(true);
foreach ($messages as $message) {
$div_class = ‘job-manager-message’;
if (!empty($message[‘is_error’])) {
$div_class = ‘job-manager-error’;
}
echo ‘<div class=”‘ . esc_attr($div_class) . ‘”>’ . wp_kses_post($message[‘message’]) . ‘</div>’;
}
$project_dashboard_columns = apply_filters(
‘workscout_freelancer_task_dashboard_columns’,
[
‘task-title’ => __(‘Name’, ‘workscout-freelancer’),
‘task-bidders’ => __(‘Bids’, ‘workscout-freelancer’),
‘task-bid-info’ => __(‘Info’, ‘workscout-freelancer’),
‘task-category’ => __(‘Title’, ‘workscout-freelancer’),
// ‘date’ => __(‘Date Posted’, ‘workscout-freelancer’),
]
);
if (!get_option(‘workscout_freelancer_enable_categories’)) {
unset($projects_dashboard_columns[‘project-category’]);
}
get_job_manager_template(
‘project-dashboard.php’,
[
‘projects’ => $projects->query($args),
‘max_num_pages’ => $projects->max_num_pages,
‘project_dashboard_columns’ => $project_dashboard_columns,
],
‘workscout-freelancer’,
WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’
);
return ob_get_clean();
}
}
new WorkScout_Freelancer_Shortcodes();
class-workscout-freelancer-task.php
<?php
// Exit if accessed directly
if (!defined(‘ABSPATH’))
exit;
/**
* WorkScout_Freelancer_Task class
*/
class WorkScout_Freelancer_Task
{
private static $_instance = null;
public function __construct()
{
add_filter(‘query_vars’, array($this, ‘add_query_vars’));
add_action(‘pre_get_posts’, array($this, ‘pre_get_posts_tasks’), 0);
add_action(‘wp_ajax_nopriv_workscout_get_tasks’, array($this, ‘ajax_get_tasks’));
add_action(‘wp_ajax_workscout_get_tasks’, array($this, ‘ajax_get_tasks’));
add_action(‘wp_ajax_workscout_incremental_skills_suggest’, array($this, ‘wp_ajax_workscout_incremental_skills_suggest’));
add_action(‘wp_ajax_nopriv_workscout_incremental_skills_suggest’, array($this, ‘wp_ajax_workscout_incremental_skills_suggest’));
add_action(‘wp’, array($this, ‘bookmark_handler’));
}
function wp_ajax_workscout_incremental_skills_suggest(){
$suggestions = array();
$terms = get_terms(array(
‘taxonomy’ => array(‘task_skill’), // taxonomy name
‘orderby’ => ‘id’,
‘order’ => ‘ASC’,
‘hide_empty’ => false,
‘fields’ => ‘all’,
‘name__like’ => $_REQUEST[‘term’]
));
$count = count($terms);
if ($count > 0) {
foreach ($terms as $term) {
$suggestion = array();
$suggestion[‘label’] = html_entity_decode($term->name, ENT_QUOTES, ‘UTF-8’);
$suggestion[‘link’] = get_term_link($term);
$suggestions[] = $suggestion;
}
}
// JSON encode and echo
$response = $_GET[“callback”] . “(” . json_encode($suggestions) . “)”;
echo $response;
// Don’t forget to exit!
exit;
}
function bookmark_handler(){
global $wpdb;
if (!is_user_logged_in()) {
return;
}
//$wpjm_bookmark = WP_Job_Manager_Bookmarks();
$action_data = null;
if (!empty($_POST[‘submit_bookmark’])) {
$post_id = absint($_POST[‘bookmark_post_id’]);
if (!wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘update_bookmark’)) {
$action_data = array(
‘error_code’ => 400,
‘error’ => __(‘Bad request’, ‘wp-job-manager-bookmarks’),
);
} else {
$note = wp_kses_post(stripslashes($_POST[‘bookmark_notes’]));
if (
$post_id && in_array(get_post_type($post_id), array(‘task’))
) {
if (!$this->is_bookmarked($post_id)) {
$wpdb->insert(
“{$wpdb->prefix}job_manager_bookmarks”,
array(
‘user_id’ => get_current_user_id(),
‘post_id’ => $post_id,
‘bookmark_note’ => $note,
‘date_created’ => current_time(‘mysql’)
)
);
} else {
$wpdb->update(
“{$wpdb->prefix}job_manager_bookmarks”,
array(
‘bookmark_note’ => $note
),
array(
‘post_id’ => $post_id,
‘user_id’ => get_current_user_id()
)
);
}
delete_transient(‘bookmark_count_’ . $post_id);
$action_data = array(‘success’ => true, ‘note’ => $note);
}
}
}
if (null === $action_data) {
return;
}
if (!empty($_REQUEST[‘wpjm-ajax’]) && !defined(‘DOING_AJAX’)) {
define(‘DOING_AJAX’, true);
}
if (wp_doing_ajax()) {
wp_send_json($action_data, !empty($action_data[‘error_code’]) ? $action_data[‘error_code’] : 200);
} else {
wp_redirect(remove_query_arg(array(‘submit_bookmark’, ‘remove_bookmark’, ‘_wpnonce’, ‘wpjm-ajax’)));
}
}
/**
* See if a post is bookmarked by ID
* @param int post ID
* @return boolean
*/
public function is_bookmarked($post_id)
{
global $wpdb;
return $wpdb->get_var($wpdb->prepare(“SELECT id FROM {$wpdb->prefix}job_manager_bookmarks WHERE post_id = %d AND user_id = %d;”, $post_id, get_current_user_id())) ? true : false;
}
public function add_query_vars($vars)
{
$new_vars = array();
$taxonomy_objects = get_object_taxonomies(‘task’, ‘objects’);
foreach ($taxonomy_objects as $tax) {
array_push($new_vars, ‘tax-‘ . $tax->name);
}
array_push($new_vars, ‘search_keywords’, ‘location_search’, ‘workscout_freelancer_order’);
$vars = array_merge($new_vars, $vars);
return $vars;
}
public static function build_available_query_vars()
{
$query_vars = array();
$taxonomy_objects = get_object_taxonomies(‘task’, ‘objects’);
foreach ($taxonomy_objects as $tax) {
array_push($query_vars, ‘tax-‘ . $tax->name);
}
// $custom = Workscout_Freelancer_Meta_Boxes::meta_boxes_custom();
// foreach ($custom[‘fields’] as $key => $field) {
// array_push($query_vars, $field[‘id’]);
// }
// array_push($query_vars, ‘_hourl’);
return $query_vars;
}
public function pre_get_posts_tasks($query)
{
if (is_admin() || !$query->is_main_query()) {
return $query;
}
if(class_exists(‘Kirki’)){
$per_page = Kirki::get_option(‘workscout’, ‘tasks_per_page’);
} else {
$per_page = get_option(‘workscout_tasks_per_page’, 10);
}
if (!is_admin() && $query->is_main_query() && is_post_type_archive(‘task’)) {
$query->set(‘posts_per_page’, $per_page);
$query->set(‘post_type’, ‘task’);
$query->set(‘post_status’, ‘publish’);
}
if (is_tax(‘task_category’) || is_tax(‘task_skill’)) {
$query->set(‘posts_per_page’, $per_page);
}
if (is_post_type_archive(‘task’) || is_author() || is_tax(‘task_category’) || is_tax(‘task_skill’)) {
$ordering_args = WorkScout_Freelancer_Task::get_task_ordering_args();
if (isset($ordering_args[‘meta_key’]) && $ordering_args[‘meta_key’] != ‘_featured’) {
$query->set(‘meta_key’, $ordering_args[‘meta_key’]);
}
$query->set(‘orderby’, $ordering_args[‘orderby’]);
$query->set(‘order’, $ordering_args[‘order’]);
$keyword = get_query_var(‘search_keywords’);
$keyword_search = get_option(‘workscout_freelancer_keyword_search’, ‘search_title’);
$search_mode = get_option(‘workscout_freelancer_search_mode’, ‘exact’);
$keywords_post_ids = array();
$location_post_ids = array();
if ($keyword) {
global $wpdb;
// Trim and explode keywords
if ($search_mode == ‘exact’) {
$keywords = array_map(‘trim’, explode(‘+’, $keyword));
} else {
$keywords = array_map(‘trim’, explode(‘ ‘, $keyword));
}
// Setup SQL
$posts_keywords_sql = array();
$postmeta_keywords_sql = array();
// Loop through keywords and create SQL snippets
foreach ($keywords as $keyword) {
# code…
if (strlen($keyword) > 2) {
// Create post meta SQL
if ($keyword_search == ‘search_title’) {
$postmeta_keywords_sql[] = ” meta_value LIKE ‘%” . esc_sql($keyword) . “%’ AND meta_key IN (‘task_subtitle’,’task_title’,’task_description’,’keywords’) “;
} else {
$postmeta_keywords_sql[] = ” meta_value LIKE ‘%” . esc_sql($keyword) . “%'”;
}
// Create post title and content SQL
$posts_keywords_sql[] = ” post_title LIKE ‘%” . esc_sql($keyword) . “%’ OR post_content LIKE ‘%” . esc_sql($keyword) . “%’ “;
}
}
if (!empty($postmeta_keywords_sql)) {
// Get post IDs from post meta search
$post_ids = $wpdb->get_col(“
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE ” . implode(‘ OR ‘, $postmeta_keywords_sql) . “
“);
} else {
$post_ids = array();
}
// Merge with post IDs from post title and content search
$keywords_post_ids = array_merge($post_ids, $wpdb->get_col(“
SELECT ID FROM {$wpdb->posts}
WHERE ( ” . implode(‘ OR ‘, $posts_keywords_sql) . ” )
AND post_type = ‘task’
“), array(0));
}
$location = get_query_var(‘location_search’);
if ($location) {
$radius = get_query_var(‘search_radius’);
if (empty($radius) && get_option(‘workscout_radius_state’) == ‘enabled’) {
$radius = get_option(‘workscout_maps_default_radius’);
}
$radius_type = get_option(‘workscout_radius_unit’, ‘km’);
$geocoding_provider = get_option(‘workscout_geocoding_provider’, ‘google’);
if ($geocoding_provider == ‘google’) {
$radius_api_key = get_option(‘workscout_maps_api_server’);
} else {
$radius_api_key = get_option(‘workscout_geoapify_maps_api_server’);
}
if (!empty($location) && !empty($radius) && !empty($radius_api_key)) {
//search by google
$latlng = workscout_geocode($address);
$nearbyposts = workscout_get_nearby_jobs($latlng[0], $latlng[1], $radius, $radius_type);
workscout_array_sort_by_column($nearbyposts, ‘distance’);
$location_post_ids = array_unique(array_column($nearbyposts, ‘post_id’));
if (empty($location_post_ids)) {
$location_post_ids = array(0);
}
} else {
//search by text
global $wpdb;
// Trim and explode keywords
$locations = array_map(‘trim’, explode(‘,’, $location));
// Setup SQL
$posts_locations_sql = array();
$postmeta_locations_sql = array();
// Loop through keywords and create SQL snippets
if (get_option(‘workscout_search_only_address’, ‘off’) == ‘on’) {
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ AND meta_key = ‘_address'”;
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ AND meta_key = ‘_friendly_address'”;
} else {
// Create post meta SQL
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ “;
// Create post title and content SQL
$posts_locations_sql[] = ” post_title LIKE ‘%” . esc_sql($locations[0]) . “%’ OR post_content LIKE ‘%” . esc_sql($locations[0]) . “%’ “;
}
// Get post IDs from post meta search
$post_ids = $wpdb->get_col(“
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE ” . implode(‘ OR ‘, $postmeta_locations_sql) . “
“);
// Merge with post IDs from post title and content search
if (get_option(‘workscout_search_only_address’, ‘off’) == ‘on’) {
$location_post_ids = array_merge($post_ids, array(0));
} else {
$location_post_ids = array_merge($post_ids, $wpdb->get_col(“
SELECT ID FROM {$wpdb->posts}
WHERE ( ” . implode(‘ OR ‘, $posts_locations_sql) . ” )
AND post_type = ‘task’
AND post_status = ‘publish’
“), array(0));
}
}
}
if (sizeof($keywords_post_ids) != 0 && sizeof($location_post_ids) != 0) {
$post_ids = array_intersect($keywords_post_ids, $location_post_ids);
$query->set(‘post__in’, $post_ids);
} else if (sizeof($keywords_post_ids) != 0 && sizeof($location_post_ids) == 0) {
$query->set(‘post__in’, $keywords_post_ids);
} else if (sizeof($keywords_post_ids) == 0 && sizeof($location_post_ids) != 0) {
$query->set(‘post__in’, $location_post_ids);
}
// if ( ! empty( $post_ids ) ) {
// $query->set( ‘post__in’, $post_ids );
// }
$query->set(‘post_type’, ‘task’);
$args = array();
$tax_query = array(
‘relation’ => get_option(‘workscout_taxonomy_or_and’, ‘AND’)
);
$taxonomy_objects = get_object_taxonomies(‘task’, ‘objects’);
foreach ($taxonomy_objects as $tax) {
$get_tax = get_query_var(‘tax-‘ . $tax->name);
if (is_array($get_tax)) {
$tax_query[$tax->name] = array(‘relation’ => get_option(‘workscout_’ . $tax->name . ‘search_mode’, ‘OR’));
foreach ($get_tax as $key => $value) {
array_push($tax_query[$tax->name], array(
‘taxonomy’ => $tax->name,
‘field’ => ‘slug’,
‘terms’ => $value,
));
}
} else {
if ($get_tax) {
if(is_numeric($get_tax)){
$term = get_term_by(‘id’, $get_tax, $tax->name);
if ($term) {
array_push($tax_query, array(
‘taxonomy’ => $tax->name,
‘field’ => ‘term_id’,
‘terms’ => $term->term_id,
‘operator’ => ‘IN’
));
}
}else{
$term = get_term_by(‘slug’, $get_tax, $tax->name);
if ($term) {
array_push($tax_query, array(
‘taxonomy’ => $tax->name,
‘field’ => ‘slug’,
‘terms’ => $term->slug,
‘operator’ => ‘IN’
));
}
}
}
}
}
$query->set(‘tax_query’, $tax_query);
$available_query_vars = $this->build_available_query_vars();
$meta_queries = array();
// $selected_range = sanitize_text_field($form_data[‘filter_by_rate’]);
// $query_args[‘meta_query’][] = array(
// ‘key’ => ‘_rate_min’,
// ‘value’ => array_map(‘absint’, explode(‘,’, $selected_range)),
// ‘compare’ => ‘BETWEEN’,
// ‘type’ => ‘NUMERIC’
// );
foreach ($available_query_vars as $key => $meta_key) {
if (substr($meta_key, 0, 4) == “tax-“) {
continue;
}
if ($meta_key == ‘_price_range’) {
continue;
}
if (!empty($meta_min) && !empty($meta_max)) {
$meta_queries[] = array(
‘key’ => substr($meta_key, 0, -4),
‘value’ => array($meta_min, $meta_max),
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’
);
$meta_max = false;
$meta_min = false;
} else if (!empty($meta_min) && empty($meta_max)) {
$meta_queries[] = array(
‘key’ => substr($meta_key, 0, -4),
‘value’ => $meta_min,
‘compare’ => ‘>=’,
‘type’ => ‘NUMERIC’
);
$meta_max = false;
$meta_min = false;
} else if (empty($meta_min) && !empty($meta_max)) {
$meta_queries[] = array(
‘key’ => substr($meta_key, 0, -4),
‘value’ => $meta_max,
‘compare’ => ‘<=’,
‘type’ => ‘NUMERIC’
);
$meta_max = false;
$meta_min = false;
}
if ($meta_key == ‘_price’) {
$meta = get_query_var(‘_price_range’);
if (!empty($meta) && $meta != -1) {
$range = array_map(‘absint’, explode(‘,’, $meta));
$meta_queries[] = array(
‘relation’ => ‘OR’,
array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘_price_min’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_price_max’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
),
array(
‘relation’ => ‘AND’,
array(
‘key’ => ‘_price_min’,
‘value’ => $range[0],
‘compare’ => ‘<=’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_price_max’,
‘value’ => $range[1],
‘compare’ => ‘>=’,
‘type’ => ‘NUMERIC’,
),
),
);
}
} else {
if (substr($meta_key, -4) == “_min” || substr($meta_key, -4) == “_max”) {
continue;
}
$meta = get_query_var($meta_key);
if ($meta && $meta != -1) {
if (is_array($meta)) {
$meta_queries[] = array(
‘key’ => $meta_key,
‘value’ => array_keys($meta),
);
} else {
$meta_queries[] = array(
‘key’ => $meta_key,
‘value’ => $meta,
);
}
}
}
}
// var_dump($meta_queries);
if (isset($ordering_args[‘meta_key’]) && $ordering_args[‘meta_key’] == ‘_featured’) {
$query->set(‘order’, ‘ASC DESC’);
$query->set(‘orderby’, ‘meta_value date’);
$query->set(‘meta_key’, ‘_featured’);
}
if (!empty($meta_queries)) {
$query->set(‘meta_query’, array(
‘relation’ => ‘AND’,
$meta_queries
));
}
}
return $query;
} /*eof function*/
public static function get_task_ordering_args($orderby = ”, $order = ”)
{
// Get ordering from query string unless defined
if ($orderby) {
$orderby_value = $orderby;
} else {
$orderby_value = isset($_GET[‘workscout_freelancer_order’]) ? (string) $_GET[‘workscout_freelancer_order’] : get_option(‘workscout_freelancer_sort_by’, ‘date’);
}
// Get order + orderby args from string
$orderby_value = explode(‘-‘, $orderby_value);
$orderby = esc_attr($orderby_value[0]);
$order = !empty($orderby_value[1]) ? $orderby_value[1] : $order;
$args = array();
// default – menu_order
$args[‘orderby’] = ‘date ID’; //featured
$args[‘order’] = (‘desc’ === $order) ? ‘DESC’ : ‘ASC’;
$args[‘meta_key’] = ”;
switch ($orderby) {
case ‘rand’:
$args[‘orderby’] = ‘rand’;
break;
case ‘featured’:
$args[‘orderby’] = ‘meta_value_num date’;
$args[‘meta_key’] = ‘_featured’;
break;
case ‘verified’:
$args[‘orderby’] = ‘meta_value_num’;
$args[‘meta_key’] = ‘_verified’;
break;
case ‘date’:
$args[‘orderby’] = ‘date’;
$args[‘order’] = (‘asc’ === $order) ? ‘ASC’ : ‘DESC’;
break;
case ‘views’:
$args[‘orderby’] = ‘meta_value_num’;
$args[‘order’] = ‘DESC’;
$args[‘meta_type’] = ‘NUMERIC’;
$args[‘meta_key’] = ‘_task_views_count’;
break;
case ‘title’:
$args[‘orderby’] = ‘title’;
$args[‘order’] = (‘desc’ === $order) ? ‘DESC’ : ‘ASC’;
break;
default:
$args[‘orderby’] = ‘date ID’;
$args[‘order’] = (‘ASC’ === $order) ? ‘ASC’ : ‘DESC’;
break;
}
return apply_filters(‘workscout_freelancer_get_tasks_ordering_args’, $args);
}
public static function get_tasks($args)
{
global $wpdb;
global $paged;
if (isset($args[‘workscout_orderby’])) {
$ordering_args = WorkScout_Freelancer_Task::get_task_ordering_args($args[‘workscout_orderby’]);
} else {
$ordering_args = WorkScout_Freelancer_Task::get_task_ordering_args();
}
if (get_query_var(‘paged’)) {
$paged = get_query_var(‘paged’);
} elseif (get_query_var(‘page’)) {
$paged = get_query_var(‘page’);
} else {
$paged = 1;
}
$search_radius_var = get_query_var(‘search_radius’);
if (!empty($search_radius_var)) {
$args[‘search_radius’] = $search_radius_var;
}
$radius_type_var = get_query_var(‘radius_type’);
if (!empty($radius_type_var)) {
$args[‘radius_type’] = $radius_type_var;
}
$keyword_var = get_query_var(‘search_keywords’);
if (!empty($keyword_var)) {
$args[‘keyword’] = $keyword_var;
}
$location_var = get_query_var(‘location_search’);
if (!empty($location_var)) {
$args[‘location’] = $location_var;
}
$query_args = array(
‘query_label’ => ‘workscout_get_task_query’,
‘post_type’ => ‘task’,
‘post_status’ => ‘publish’,
‘ignore_sticky_posts’ => 1,
‘paged’ => $paged,
‘posts_per_page’ => intval($args[‘posts_per_page’]),
‘orderby’ => $ordering_args[‘orderby’],
‘order’ => $ordering_args[‘order’],
‘tax_query’ => array(),
‘meta_query’ => array(),
);
if (isset($args[‘offset’])) {
$query_args[‘offset’] = $args[‘offset’];
}
if (isset($ordering_args[‘meta_type’])) {
$query_args[‘meta_type’] = $ordering_args[‘meta_type’];
}
if (isset($ordering_args[‘meta_key’]) && $ordering_args[‘meta_key’] != ‘_featured’) {
$query_args[‘meta_key’] = $ordering_args[‘meta_key’];
}
$keywords_post_ids = array();
$location_post_ids = array();
$keyword_search = get_option(‘workscout_keyword_search’, ‘search_title’);
$search_mode = get_option(‘workscout_search_mode’, ‘exact’);
if (isset($args[‘keyword’]) && !empty($args[‘keyword’])) {
if ($search_mode == ‘exact’) {
$keywords = array_map(‘trim’, explode(‘+’, $args[‘keyword’]));
} else {
$keywords = array_map(‘trim’, explode(‘ ‘, $args[‘keyword’]));
}
// Setup SQL
$posts_keywords_sql = array();
$postmeta_keywords_sql = array();
// $postmeta_keywords_sql[] = ” meta_value LIKE ‘%” . esc_sql( $keywords[0] ) . “%’ “;
// // Create post title and content SQL
// $posts_keywords_sql[] = ” post_title LIKE ‘%” . esc_sql( $keywords[0] ) . “%’ OR post_content LIKE ‘%” . esc_sql( $keywords[0] ) . “%’ “;
foreach ($keywords as $keyword) {
# code…
if (strlen($keyword) > 2) {
// Create post meta SQL
if ($keyword_search == ‘search_title’) {
$postmeta_keywords_sql[] = ” meta_value LIKE ‘%” . esc_sql($keyword) . “%’ AND meta_key IN (‘workscout_subtitle’,’task_title’,’task_description’,’keywords’) “;
} else {
$postmeta_keywords_sql[] = ” meta_value LIKE ‘%” . esc_sql($keyword) . “%'”;
}
// Create post title and content SQL
$posts_keywords_sql[] = ” post_title LIKE ‘%” . esc_sql($keyword) . “%’ OR post_content LIKE ‘%” . esc_sql($keyword) . “%’ “;
}
}
// Get post IDs from post meta search
$post_ids = $wpdb->get_col(“
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE ” . implode(‘ OR ‘, $postmeta_keywords_sql) . “
“);
// Merge with post IDs from post title and content search
$keywords_post_ids = array_merge($post_ids, $wpdb->get_col(“
SELECT ID FROM {$wpdb->posts}
WHERE ( ” . implode(‘ OR ‘, $posts_keywords_sql) . ” )
AND post_type = ‘task’
“), array(0));
/* array( 0 ) is set to return no result when no keyword was found */
}
if (isset($args[‘location’]) && !empty($args[‘location’])) {
$radius = $args[‘search_radius’];
if (empty($radius)) {
$radius = get_option(‘workscout_maps_default_radius’);
}
$radius_type = get_option(‘workscout_radius_unit’, ‘km’);
$radius_api_key = get_option(‘workscout_maps_api_server’);
$geocoding_provider = get_option(‘workscout_geocoding_provider’, ‘google’);
if ($geocoding_provider == ‘google’) {
$radius_api_key = get_option(‘workscout_maps_api_server’);
} else {
$radius_api_key = get_option(‘workscout_geoapify_maps_api_server’);
}
if (!empty($args[‘location’]) && !empty($radius) && !empty($radius_api_key)) {
//search by google
$latlng = workscout_geocode($args[‘location’]);
$nearbyposts = workscout_get_nearby_jobs($latlng[0], $latlng[1], $radius, $radius_type);
workscout_array_sort_by_column($nearbyposts, ‘distance’);
$location_post_ids = array_unique(array_column($nearbyposts, ‘post_id’));
if (empty($location_post_ids)) {
$location_post_ids = array(0);
}
} else {
$locations = array_map(‘trim’, explode(‘,’, $args[‘location’]));
// Setup SQL
$posts_locations_sql = array();
$postmeta_locations_sql = array();
if (get_option(‘workscout_search_only_address’, ‘off’) == ‘on’) {
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ AND meta_key = ‘_address'”;
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ AND meta_key = ‘_friendly_address'”;
} else {
$postmeta_locations_sql[] = ” meta_value LIKE ‘%” . esc_sql($locations[0]) . “%’ “;
// Create post title and content SQL
$posts_locations_sql[] = ” post_title LIKE ‘%” . esc_sql($locations[0]) . “%’ OR post_content LIKE ‘%” . esc_sql($locations[0]) . “%’ “;
}
// Get post IDs from post meta search
$post_ids = $wpdb->get_col(“
SELECT DISTINCT post_id FROM {$wpdb->postmeta}
WHERE ” . implode(‘ OR ‘, $postmeta_locations_sql) . “
“);
// Merge with post IDs from post title and content search
if (get_option(‘workscout_search_only_address’, ‘off’) == ‘on’) {
$location_post_ids = array_merge($post_ids, array(0));
} else {
$location_post_ids = array_merge($post_ids, $wpdb->get_col(“
SELECT ID FROM {$wpdb->posts}
WHERE ( ” . implode(‘ OR ‘, $posts_locations_sql) . ” )
AND post_type = ‘task’
AND post_status = ‘publish’
“), array(0));
}
}
}
if (sizeof($keywords_post_ids) != 0 && sizeof($location_post_ids) != 0) {
$post_ids = array_intersect($keywords_post_ids, $location_post_ids);
if (!empty($post_ids)) {
$query_args[‘post__in’] = $post_ids;
} else {
$query_args[‘post__in’] = array(0);
}
} else if (sizeof($keywords_post_ids) != 0 && sizeof($location_post_ids) == 0) {
$query_args[‘post__in’] = $keywords_post_ids;
} else if (sizeof($keywords_post_ids) == 0 && sizeof($location_post_ids) != 0) {
$query_args[‘post__in’] = $location_post_ids;
}
if (isset($query_args[‘post__in’])) {
$posts_in_array = $query_args[‘post__in’];
} else {
$posts_in_array = array();
}
$posts_not_ids = array();
$query_args[‘post__in’] = array_diff($posts_in_array, $posts_not_ids);
$query_args[‘tax_query’] = array(
‘relation’ => ‘AND’,
);
$taxonomy_objects = get_object_taxonomies(‘task’, ‘objects’);
foreach ($taxonomy_objects as $tax) {
$get_tax = false;
if ((isset($_GET[‘tax-‘ . $tax->name]) && !empty($_GET[‘tax-‘ . $tax->name]))) {
$get_tax = $_GET[‘tax-‘ . $tax->name];
} else {
if (isset($args[‘tax-‘ . $tax->name])) {
$get_tax = $args[‘tax-‘ . $tax->name];
}
}
if (is_array($get_tax)) {
$query_args[‘tax_query’][$tax->name] =
array(‘relation’ => get_option(‘workscout_’ . $tax->name . ‘search_mode’, ‘OR’));
foreach ($get_tax as $key => $value) {
array_push($query_args[‘tax_query’][$tax->name], array(
‘taxonomy’ => $tax->name,
‘field’ => ‘ID’,
‘terms’ => $value,
));
}
} else {
if ($get_tax) {
if (is_numeric($get_tax)) {
$term = get_term_by(‘slug’, $get_tax, $tax->name);
if ($term) {
array_push($query_args[‘tax_query’], array(
‘taxonomy’ => $tax->name,
‘field’ => ‘ID’,
‘terms’ => $term->slug,
‘operator’ => ‘IN’
));
}
} else {
$get_tax_array = explode(‘,’, $get_tax);
//$query_args[‘tax_query’][$tax->name] = array(‘relation’=> ‘OR’);
array_push($query_args[‘tax_query’], array(
‘taxonomy’ => $tax->name,
‘field’ => ‘ID’,
‘terms’ => $get_tax_array,
));
}
}
}
}
$available_query_vars = WorkScout_Freelancer_Task::build_available_query_vars();
$meta_queries = array();
if (isset($args[‘featured’]) && !$args[‘featured’]) {
$available_query_vars[] = ‘featured’;
}
foreach ($available_query_vars as $key => $meta_key) {
if (substr($meta_key, 0, 4) == “tax-“) {
continue;
}
if ($meta_key == ‘_price_range’) {
continue;
}
if ($meta_key == ‘_price’) {
$meta = false;
if (!empty(get_query_var(‘_price_range’))) {
$meta = get_query_var(‘_price_range’);
} else if (isset($args[‘_price_range’])) {
$meta = $args[‘_price_range’];
}
if (!empty($meta)) {
$range = array_map(‘absint’, explode(‘,’, $meta));
$query_args[‘meta_query’][] = array(
‘relation’ => ‘OR’,
array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘_price_min’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_price_max’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_classifieds_price’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
),
// array(
// ‘relation’ => ‘AND’,
// array(
// ‘key’ => ‘_price_min’,
// ‘value’ => $range[0],
// ‘compare’ => ‘>=’,
// ‘type’ => ‘NUMERIC’,
// ),
// array(
// ‘key’ => ‘_price_max’,
// ‘value’ => $range[1],
// ‘compare’ => ‘>=’,
// ‘type’ => ‘NUMERIC’,
// ),
// ),
);
}
} else {
if (substr($meta_key, -4) == “_min” || substr($meta_key, -4) == “_max”) {
continue;
}
$meta = false;
if (!empty(get_query_var($meta_key))) {
$meta = get_query_var($meta_key);
} else if (isset($args[$meta_key])) {
$meta = $args[$meta_key];
}
if ($meta) {
if ($meta === ‘featured’) {
$query_args[‘meta_query’][] = array(
‘key’ => ‘_featured’,
‘value’ => ‘on’,
‘compare’ => ‘=’
);
} else {
if (is_array($meta)) {
$query_args[‘meta_query’][] = array(
‘key’ => $meta_key,
‘value’ => array_keys($meta),
‘compare’ => ‘IN’
);
} else {
$query_args[‘meta_query’][] = array(
‘key’ => $meta_key,
‘value’ => $meta,
);
}
}
}
}
}
if (isset($args[‘filter_by_fixed_check’]) && $args[‘filter_by_fixed_check’] == ‘on’) {
if (isset($args[‘filter_by_fixed’]) && !empty($args[‘filter_by_fixed’])) {
$selected_range = sanitize_text_field($args[‘filter_by_fixed’]);
$range = array_map(‘absint’, explode(‘,’, $selected_range));
$query_args[‘meta_query’][] = array(
‘relation’ => ‘OR’,
array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘_budget_min’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_budget_max’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
),
array(
‘relation’ => ‘AND’,
array(
‘key’ => ‘_budget_min’,
‘value’ => $range[0],
‘compare’ => ‘<=’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_budget_max’,
‘value’ => $range[1],
‘compare’ => ‘>=’,
‘type’ => ‘NUMERIC’,
),
),
);
$query_args[‘meta_query’][] = array(
‘key’ => ‘_task_type’,
‘value’ => ‘fixed’,
‘compare’ => ‘=’
);
}
}
if (isset($args[‘filter_by_hourly_rate_check’]) && $args[‘filter_by_hourly_rate_check’] == ‘on’) {
if (isset($args[‘filter_by_hourly_rate’]) && !empty($args[‘filter_by_hourly_rate’])) {
$selected_range = sanitize_text_field($args[‘filter_by_hourly_rate’]);
$range = array_map(‘absint’, explode(‘,’, $selected_range));
$query_args[‘meta_query’][] = array(
‘relation’ => ‘OR’,
array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘_hourly_min’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_hourly_max’,
‘value’ => $range,
‘compare’ => ‘BETWEEN’,
‘type’ => ‘NUMERIC’,
),
),
// array(
// ‘key’ => ‘_task_type’,
// ‘value’ => ‘hourly’,
// ‘compare’ => ‘=’
// )
array(
‘relation’ => ‘AND’,
array(
‘key’ => ‘_hourly_min’,
‘value’ => $range[0],
‘compare’ => ‘<=’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘_hourly_max’,
‘value’ => $range[1],
‘compare’ => ‘>=’,
‘type’ => ‘NUMERIC’,
),
),
);
$query_args[‘meta_query’][] = array(
‘key’ => ‘_task_type’,
‘value’ => ‘hourly’,
‘compare’ => ‘=’
);
}
}
if (isset($args[‘featured’]) && $args[‘featured’] !== ‘null’) {
if ($args[‘featured’] == ‘true’ || $args[‘featured’] == true) {
$query_args[‘meta_query’][] = array(
‘key’ => ‘_featured’,
‘value’ => ‘on’,
‘compare’ => ‘=’
);
}
}
if (isset($args[‘featured’]) && $args[‘featured’] === ‘null’) {
$query_args[‘meta_query’][] = array(
‘key’ => ‘_featured’,
‘value’ => ‘on’,
‘compare’ => ‘!=’
);
}
if (isset($ordering_args[‘meta_key’]) && $ordering_args[‘meta_key’] == ‘_featured’) {
$query_args[‘order’] = ‘ASC DESC’;
$query_args[‘orderby’] = ‘meta_value date’;
$query_args[‘meta_key’] = ‘_featured’;
}
//workscout_write_log($query_args[‘meta_query’]);
if (empty($query_args[‘meta_query’]))
unset($query_args[‘meta_query’]);
$query_args = apply_filters(‘workscout_freelancer_get_tasks’, $query_args, $args);
$result = new WP_Query($query_args);
return $result;
}
public function ajax_get_tasks()
{
global $wp_post_types;
$template_loader = new WorkScout_Freelancer_Template_Loader;
$location = (isset($_REQUEST[‘search_location’])) ? sanitize_text_field(stripslashes($_REQUEST[‘search_location’])) : ”;
$keyword = (isset($_REQUEST[‘search_keywords’])) ? sanitize_text_field(stripslashes($_REQUEST[‘search_keywords’])) : ”;
$radius = (isset($_REQUEST[‘search_radius’])) ? sanitize_text_field(stripslashes($_REQUEST[‘search_radius’])) : ”;
$orderby = (isset($_REQUEST[‘orderby’])) ? sanitize_text_field(stripslashes($_REQUEST[‘orderby’])) : ”;
$order = (isset($_REQUEST[‘order’])) ? sanitize_text_field(stripslashes($_REQUEST[‘order’])) : ”;
$style = sanitize_text_field(stripslashes($_REQUEST[‘style’]));
$per_page = sanitize_text_field(stripslashes($_REQUEST[‘per_page’]));
$region = (isset($_REQUEST[‘tax-region’])) ? ($_REQUEST[‘tax-region’]) : ”;
$category = (isset($_REQUEST[‘tax-task_category’])) ? ($_REQUEST[‘tax-task_category’]) : ”;
$skill = (isset($_REQUEST[‘tax-task_skill’])) ? ($_REQUEST[‘tax-task_skill’]) : ”;
$filter_by_hourly_rate_check = (isset($_REQUEST[‘filter_by_hourly_rate_check’])) ? ($_REQUEST[‘filter_by_hourly_rate_check’]) : ”;
$filter_by_hourly_rate = (isset($_REQUEST[‘filter_by_hourly_rate’])) ? ($_REQUEST[‘filter_by_hourly_rate’]) : ”;
$filter_by_fixed_check = (isset($_REQUEST[‘filter_by_fixed_check’])) ? ($_REQUEST[‘filter_by_fixed_check’]) : ”;
$filter_by_fixed = (isset($_REQUEST[‘filter_by_fixed’])) ? ($_REQUEST[‘filter_by_fixed’]) : ”;
$date_start = ”;
$date_end = ”;
if (empty($per_page)) {
$per_page = Kirki::get_option(‘workscout’, ‘tasks_per_page’);
}
$query_args = array(
‘ignore_sticky_posts’ => 1,
‘post_type’ => ‘task’,
‘orderby’ => $orderby,
‘order’ => $order,
‘offset’ => (absint($_REQUEST[‘page’]) – 1) * absint($per_page),
‘location’ => $location,
‘keyword’ => $keyword,
‘search_radius’ => $radius,
‘posts_per_page’ => $per_page,
‘tax-task_skill’ => $skill,
‘filter_by_hourly_rate_check’ => $filter_by_hourly_rate_check,
‘filter_by_hourly_rate’ => $filter_by_hourly_rate,
‘filter_by_fixed_check’ => $filter_by_fixed_check,
‘filter_by_fixed’ => $filter_by_fixed,
);
$query_args[‘workscout_orderby’] = (isset($_REQUEST[‘workscout_core_order’])) ? sanitize_text_field($_REQUEST[‘workscout_core_order’]) : false;
$taxonomy_objects = get_object_taxonomies(‘task’, ‘objects’);
foreach ($taxonomy_objects as $tax) {
if (isset($_REQUEST[‘tax-‘ . $tax->name])) {
$query_args[‘tax-‘ . $tax->name] = $_REQUEST[‘tax-‘ . $tax->name];
}
}
$available_query_vars = $this->build_available_query_vars();
foreach ($available_query_vars as $key => $meta_key) {
if (isset($_REQUEST[$meta_key]) && $_REQUEST[$meta_key] != -1) {
$query_args[$meta_key] = $_REQUEST[$meta_key];
}
}
// add meta boxes support
$orderby = isset($_REQUEST[‘workscout_core_order’]) ? $_REQUEST[‘workscout_core_order’] : ‘date’;
// if ( ! is_null( $featured ) ) {
// $featured = ( is_bool( $featured ) && $featured ) || in_array( $featured, array( ‘1’, ‘true’, ‘yes’ ) ) ? true : false;
// }
$tasks = WorkScout_Freelancer_Task::get_tasks(apply_filters(‘workscout_core_output_defaults_args’, $query_args));
$result = array(
‘found_tasks’ => $tasks->have_posts(),
‘max_num_pages’ => $tasks->max_num_pages,
);
ob_start();
if ($result[‘found_tasks’]) {
$style_data = array(
‘style’ => $style,
// ‘class’ => $custom_class,
//’in_rows’ => $in_rows,
‘max_num_pages’ => $tasks->max_num_pages,
‘counter’ => $tasks->found_posts
);
//$template_loader->set_template_data( $style_data )->get_template_part( ‘tasks-start’ );
?>
<div class=”loader-ajax-container”>
<div class=”loader-ajax”></div>
</div>
<?php
while ($tasks->have_posts()) {
$tasks->the_post();
$template_loader->set_template_data($style_data)->get_template_part(‘content-task’, $style);
}
?>
<div class=”clearfix”></div>
</div>
<?php
//$template_loader->set_template_data( $style_data )->get_template_part( ‘tasks-end’ );
} else {
?>
<div class=”loader-ajax-container”>
<div class=”loader-ajax”></div>
</div>
<?php
$template_loader->get_template_part(‘no-task-found’);
?><div class=”clearfix”></div>
<?php
}
$result[‘html’] = ob_get_clean();
$result[‘counter’] = $tasks->found_posts;
$result[‘pagination’] = workscout_freelancer_ajax_pagination($tasks->max_num_pages, absint($_REQUEST[‘page’]));
wp_send_json($result);
}
}
class-workscout-freelancer-templates.php
<?php
/**
* Template loader for PW Sample Plugin.
*
* Only need to specify class listings here.
*
*/
class WorkScout_Freelancer_Template_Loader extends Gamajo_Template_Loader {
/**
* Prefix for filter names.
*
* @since 1.0.0
* @type string
*/
protected $filter_prefix = ‘workscout_freelancer’;
/**
* Directory name where custom templates for this plugin should be found in the theme.
*
* @since 1.0.0
* @type string
*/
protected $theme_template_directory = ‘workscout-freelancer’;
/**
* Reference to the root directory path of this plugin.
*
* @since 1.0.0
* @type string
*/
protected $plugin_directory = WORKSCOUT_FREELANCER_PLUGIN_DIR;
/**
* Directory name where templates are found in this plugin.
*
* Can either be a defined constant, or a relative reference from where the subclass lives.
*
* e.g. ‘templates’ or ‘includes/templates’, etc.
*
* @since 1.1.0
*
* @var string
*/
protected $plugin_template_directory = ‘templates’;
}
class-workscout-freelancer-user.php
<?php
// Exit if accessed directly
if ( ! defined( ‘ABSPATH’ ) )
exit;
/**
* WPSight_Meta_Boxes class
*/
class WorkScout_Freelancer_User {
static function on_load()
{
add_action(‘init’, array(__CLASS__, ‘init’));
add_action(‘wp_insert_post’, array(__CLASS__, ‘wp_insert_post’), 10, 2);
add_action(‘profile_update’, array(__CLASS__, ‘profile_update’), 10, 2);
add_action(‘user_register’, array(__CLASS__, ‘profile_update’));
add_filter(‘author_link’, array(__CLASS__, ‘author_link’), 10, 2);
add_filter(‘get_the_author_url’, array(__CLASS__, ‘author_link’), 10, 2);
// add_filter(‘workscout/my-account/custom-fields’, array(__CLASS__, ‘custom_fields’));
add_filter(‘worscout_core_user_fields’, array(__CLASS__, ‘user_fields’));
}
static function user_fields($fields){
$fields[] = ‘freelancer_rate’;
$fields[] = ‘freelancer_tagline’;
$fields[] = ‘freelancer_country’;
return $fields;
}
static function custom_fields(){
$template_loader = new WorkScout_Freelancer_Template_Loader;
$template_loader->get_template_part(‘account/freelancer-fields’);
}
static function init()
{
register_post_type(
‘workscout-freelancer’,
array(
‘labels’ => array(‘name’ => ‘Freelancer’, ‘singular_name’ => ‘Freelancer’),
‘public’ => true,
‘show_ui’ => true,
‘rewrite’ => array(‘slug’ => ‘freelancer’),
‘hierarchical’ => false,
//’supports’ => array(‘title’,’editor’,’custom-fields’),
)
);
$singular = __(‘User Skill’, ‘workscout-freelancer’);
$plural = __(‘Users Skills’, ‘workscout-freelancer’);
$rewrite = array(
‘slug’ => _x(‘skill’, ‘Skill slug – resave permalinks after changing this’, ‘workscout-freelancer’),
‘with_front’ => false,
‘hierarchical’ => false
);
$public = true;
register_taxonomy(
“skill”,
apply_filters(‘register_taxonomy_user_types_object_type’, array(‘workscout-freelancer’)),
apply_filters(‘register_taxonomy_user_types_args’, array(
‘hierarchical’ => true,
/*’update_count_callback’ => ‘_update_post_term_count’,*/
‘label’ => $plural,
‘labels’ => array(
‘name’ => $plural,
‘singular_name’ => $singular,
‘menu_name’ => ucwords($plural),
‘search_items’ => sprintf(__(‘Search %s’, ‘workscout-freelancer’), $plural),
‘all_items’ => sprintf(__(‘All %s’, ‘workscout-freelancer’), $plural),
‘parent_item’ => sprintf(__(‘Parent %s’, ‘workscout-freelancer’), $singular),
‘parent_item_colon’ => sprintf(__(‘Parent %s:’, ‘workscout-freelancer’), $singular),
‘edit_item’ => sprintf(__(‘Edit %s’, ‘workscout-freelancer’), $singular),
‘update_item’ => sprintf(__(‘Update %s’, ‘workscout-freelancer’), $singular),
‘add_new_item’ => sprintf(__(‘Add New %s’, ‘workscout-freelancer’), $singular),
‘new_item_name’ => sprintf(__(‘New %s Name’, ‘workscout-freelancer’), $singular)
),
‘show_ui’ => true,
‘show_in_rest’ => true,
‘show_tagcloud’ => false,
‘public’ => $public,
/*’capabilities’ => array(
‘manage_terms’ => $admin_capability,
‘edit_terms’ => $admin_capability,
‘delete_terms’ => $admin_capability,
‘assign_terms’ => $admin_capability,
),*/
‘rewrite’ => $rewrite,
))
);
}
static function get_email_key()
{
return apply_filters(‘freelancer_email_key’, ‘_email’);
}
static function profile_update($user_id, $old_user_data = false)
{
global $wpdb;
$is_new_freelancer = false;
$user = get_userdata($user_id);
$user_email = ($old_user_data ? $old_user_data->user_email : $user->user_email);
$email_key = self::get_email_key();
$freelancer_id = $wpdb->get_var($wpdb->prepare(“SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key=’%s’ AND meta_value=’%s'”, $email_key, $user_email));
if (!is_numeric($freelancer_id)) {
$freelancer_id = $is_new_freelancer = wp_insert_post(array(
‘post_type’ => ‘workscout-freelancer’,
‘post_status’ => ‘publish’, // Maybe this should be pending or draft?
‘post_title’ => $user->display_name,
));
}
update_user_meta($user_id, ‘_freelancer_id’, $freelancer_id);
update_post_meta($freelancer_id, ‘_user_id’, $user_id);
if ($is_new_freelancer || ($old_user_data && $user->user_email != $old_user_data->user_email)) {
update_post_meta($freelancer_id, $email_key, $user->user_email);
}
}
static function wp_insert_post($freelancer_id, $freelancer)
{
if ($freelancer->post_type == ‘workscout-freelancer’) {
$email = get_post_meta($freelancer_id, self::get_email_key(), true);
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$user = get_user_by(’email’, $email);
if ($user) { // Associate the user IF there is an user with the same email address
update_user_meta($user->ID, ‘_freelancer_id’, $freelancer_id);
update_post_meta($freelancer_id, ‘_user_id’, $user->ID);
} else {
delete_post_meta($freelancer_id, ‘_user_id’);
}
}
}
}
static function get_user_id($freelancer_id)
{
return get_user_meta($user_id, ‘_user_id’, true);
}
static function get_user($freelancer_id)
{
$user_id = self::get_user_id($freelancer_id);
return get_userdata($user_id);
}
static function get_freelancer_id($user_id)
{
return get_user_meta($user_id, ‘_freelancer_id’, true);
}
static function get_freelancer($user_id)
{
$freelancer_id = self::get_freelancer_id($user_id);
return get_post($freelancer_id);
}
static function author_link($permalink, $user_id)
{
$author_id = get_user_meta($user_id, ‘freelancer_profile’, true);
if ($author_id) {
$permalink = get_post_permalink($author_id);
}
return $permalink;
}
}
WorkScout_Freelancer_User::on_load();
Freelancer-fields.php
<?php $current_user = wp_get_current_user(); ?>
<div class=”submit-field”>
<div class=”bidding-widget”>
<!– Headline –>
<span class=”bidding-detail”> <?php esc_html_e(‘Set your minimal hourly rate’, ‘workscout-freelancer’); ?></span>
<?php
$default_freelancer_rate = ($current_user->freelancer_rate) ? $current_user->freelancer_rate : 45; ?>
<!– Slider –>
<div class=”bidding-value margin-bottom-10″>$<span id=”biddingVal”></span></div>
<input name=”freelancer_rate” class=”bidding-slider” type=”text” value=”” data-slider-handle=”custom” data-slider-currency=”$” data-slider-min=”5″ data-slider-max=”150″ data-slider-value=”<?php echo $default_freelancer_rate; ?>” data-slider-step=”1″ data-slider-tooltip=”hide” />
</div>
</div>
<div class=”submit-field”>
<h5>Skills <i class=”help-icon” data-tippy-placement=”right” title=”<?php esc_html_e(‘Add up to 10 skills’, ‘workscout-freelancer’); ?>”></i></h5>
<!– Skills List –>
<div class=”keywords-container”>
<div class=”keyword-input-container”>
<input type=”text” class=”keyword-input with-border” placeholder=”<?php esc_html_e(‘e.g. Angular, Laravel’, ‘workscout-freelancer’); ?>” />
<button class=”keyword-input-button ripple-effect”><i class=”icon-material-outline-add”></i></button>
</div>
<?php //get terms from
$terms = get_terms(array(
‘taxonomy’ => ‘user_skill’,
‘hide_empty’ => false,
));
?>
<div class=”keywords-list”>
<!– <span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>Angular</span></span>
<span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>Vue JS</span></span>
<span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>iOS</span></span>
<span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>Android</span></span>
<span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>Laravel</span></span> –>
</div>
<div class=”clearfix”></div>
</div>
</div>
<div class=”submit-field”>
<h5><?php esc_html_e(‘Attachments’); ?></h5>
<!– Attachments –>
<?php $freelancer_attachemnts = get_user_meta($current_user->ID, ‘freelancer_attachments’, true);
if ($freelancer_attachemnts) :
$attachment_ids = explode(‘,’, $freelancer_attachemnts); ?>
<div class=”attachments-container”>
<?php foreach ($attachment_ids as $attachment_id) {
$attachment = get_post($attachment_id);
$filetype = wp_check_filetype($attachment->guid);
$filetype = $filetype[‘ext’];
$filename = basename($attachment->guid);
$file_url = wp_get_attachment_url($attachment_id);
?>
<div class=”attachment-box ripple-effect”>
<span><?php
// make the filename max 20 characters long and add … if it’s longer
if (strlen($filename) > 20) {
$filename = substr($filename, 0, 20) . ‘…’;
}
echo $filename; ?></span>
<i><?php echo $filetype; ?></i>
<button class=”remove-attachment” data-tippy-placement=”top” title=”<?php echo esc_html(‘Remove’, ‘workscout-freelancer’); ?>”></button>
</div>
<?php } ?>
</div>
<div class=”clearfix”></div>
<?php endif; ?>
<!– Upload Button –>
<div class=”uploadButton margin-top-0″>
<input class=”uploadButton-input” name=”freelancer_attachments[]” type=”file” accept=”image/*, application/pdf” id=”upload” multiple />
<label class=”uploadButton-button ripple-effect” for=”upload”><?php esc_html_e(‘Upload Files’,’workscout-freelancer’); ?></label>
<s<span class=”uploadButton-file-name”><?php printf(esc_html__(‘Maximum file size: %s.’, ‘workscout-freelancer’), size_format(wp_max_upload_size())); ?></span>
</div>
</div>
<div class=”submit-field”>
<h5><?php esc_html_e(‘Tagline’); ?></h5>
<input name=”freelancer_tagline” type=”text” class=”with-border” value=”<?php echo $current_user->freelancer_tagline ? $current_user->freelancer_tagline : ”; ?>” placeholder=”<?php esc_html_e(‘iOS Expert + Node Dev’); ?>”>
</div>
<div class=”submit-field”>
<h5><?php esc_html_e(‘Nationality’, ‘workscout-freelancer’); ?></h5>
<select name=”freelancer_country” class=”selectpicker with-border” data-size=”7″ data-live-search=”true”>
<option value=””><?php esc_html_e(‘Select Country’, ‘workscout-freelancer’); ?></option>
<?php
$countries = workscoutGetCountries();
foreach ($countries as $key => $value) {
$selected = ($current_user->freelancer_country == $key) ? ‘selected’ : ”;
echo ‘<option value=”‘ . $key . ‘” ‘ . $selected . ‘>’ . $value . ‘</option>’;
}
?>
</select>
</div>
Dynamic-input-field.php
<?php
/**
* Shows the `keyword input` form field on job listing forms.
*
* This template can be overridden by copying it to yourtheme/job_manager/form-fields/text-field.php.
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Purethemes
* @package wp-job-manager
* @category Template
* @version 1.31.1
*/
if (!defined(‘ABSPATH’)) {
exit; // Exit if accessed directly.
}
$field_name = isset($field[‘name’]) ? $field[‘name’] : $key;
// Get selected value.
if (isset($field[‘value’])) {
$selected = $field[‘value’];
} elseif (is_int($field[‘default’])) {
$selected = $field[‘default’];
} elseif (!empty($field[‘default’]) && ($term = get_term_by(‘slug’, $field[‘default’], $field[‘taxonomy’]))) {
$selected = $term->term_id;
} else {
$selected = ”;
}
// turn array into string with comma separated values
$selected_terms = array();
?>
<div class=”keywords-container”>
<div class=”keyword-input-container”>
<input type=”text” class=”keyword-input with-border” placeholder=”<?php esc_html_e(‘Add Skills’, ‘workscout-freelancer’); ?>” />
<button class=”keyword-input-button ripple-effect”><i class=”icon-material-outline-add”></i></button>
</div>
<div class=”keywords-list”>
<!– keywords go here –>
<?php if(is_array($selected)){
foreach($selected as $key ){
$term = get_term_by(‘id’, $key, ‘task_skill’);
$selected_terms[] = $term->name;
echo ‘<span class=”keyword”><span class=”keyword-remove”></span><span class=”keyword-text”>’. $term->name.'</span></span>’;
}
}
?>
</div>
<input type=”hidden” name=”<?php echo esc_attr($field_name); ?>” class=”keyword-input-real” id=”<?php echo esc_attr($key); ?>” placeholder=”” value=”<?php echo isset($field[‘value’]) ? implode(‘,’, $selected_terms) : ”; ?>” <?php if (!empty($field[‘required’])) echo ‘required’; ?> />
<div class=”clearfix”></div>
</div>
Radio-field.php
<?php
/**
* Shows the `radio` form field on job listing forms.
*
* This template can be overridden by copying it to yourtheme/job_manager/form-fields/radio-field.php.
*
* Example definition:
*
* ‘test_radio’ => array(
* ‘label’ => __( ‘Test Radio’, ‘wp-job-manager’ ),
* ‘type’ => ‘radio’,
* ‘required’ => false,
* ‘default’ => ‘option2’,
* ‘priority’ => 1,
* ‘options’ => array(
* ‘option1’ => ‘This is option 1’,
* ‘option2’ => ‘This is option 2’
* )
* )
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Automattic
* @package wp-job-manager
* @category Template
* @version 1.31.1
*/
if (!defined(‘ABSPATH’)) {
exit; // Exit if accessed directly.
}
$field[‘default’] = empty($field[‘default’]) ? current(array_keys($field[‘options’])) : $field[‘default’];
$default = !empty($field[‘value’]) ? $field[‘value’] : $field[‘default’];
?>
<div class=”feedback-yes-no margin-top-0″>
<?php
$i = 0;
foreach ($field[‘options’] as $option_key => $value) :
$i++; ?>
<div class=”radio”>
<input type=”radio” id=”<?php echo esc_attr(isset($field[‘name’]) ? $field[‘name’] : $key); echo $i;?>” name=”<?php echo esc_attr(isset($field[‘name’]) ? $field[‘name’] : $key); ?>” value=”<?php echo esc_attr($option_key); ?>” <?php checked($default, $option_key); ?> />
<label for=”<?php echo esc_attr(isset($field[‘name’]) ? $field[‘name’] : $key); echo $i; ?>”><span class=”radio-label”></span> <?php echo esc_html($value); ?></label>
</div>
<?php endforeach; ?>
</div>
Single-company.php
<?php
$company_id = get_post_meta($post->ID, ‘_company_id’, true);
if ($company_id) : ?>
<h5><?php esc_html_e(‘Added by’, ‘workscout-freelancer’); ?></h5>
<ul>
<li><a href=”<?php echo get_permalink($company_id); ?>”><i class=”icon-material-outline-business”></i> <?php echo get_the_title($company_id); ?></a></li>
<?php
if (function_exists(‘mas_wpjmcr_get_reviews_average’)) {
$rating = mas_wpjmcr_get_reviews_average($company_id);
if ($rating) { ?>
<li>
<div class=”star-rating” data-rating=”<?php echo number_format_i18n($rating, 1); ?>”></div>
</li>
<?php } else { ?>
<li>
<div class=”no-reviews”><?php esc_html_e(‘No reviews yet’, ‘workscout-freelancer’); ?></div>
</li>
<?php }
}
$country = get_post_meta($company_id, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries();
?>
<li><img class=”flag” src=”<?php echo WORKSCOUT_FREELANCER_PLUGIN_URL; ?>/assets/images/flags/<?php echo strtolower($country); ?>.svg” alt=””> <?php echo $countries[$country]; ?></li>
<?php } ?>
<!– <li>
<div class=”verified-badge-with-title”>Verified</div>
</li> –>
</ul>
<?php endif; ?>
Single-task-attachments.php
<?php
$attachments = get_post_meta($post->ID, ‘_task_file’,true);
//if attachemnts is not empty
if($attachments) :
?>
<!– Atachments –>
<div class=”single-page-section margin-bottom-60 “>
<h3><?php esc_html_e(‘Attachments’, ‘workscout-freelancer’); ?></h3>
<div class=”attachments-container”>
<?php
//$attachments = get_posts(‘post_parent=’ . $post->ID . ‘&post_type=attachment&fields=ids&post_mime_type=image&numberposts=-1’);
foreach ((array) $attachments as $attachment_id => $attachment_url) {
//get the attachment url
$attachment_url = wp_get_attachment_url($attachment_id);
if(!$attachment_url){
//skip if no url
continue;
}
//get the attachment filename
$attachment_title = get_the_title($attachment_id);
if(!$attachment_title){
}
$attachment_title = basename($attachment_url);
//$attachment_title = get_the_title($id);
//get the attachment file type
$attachment_filetype = wp_check_filetype($attachment_url);
?>
<a href=”<?php echo $attachment_url;?>” class=”attachment-box ripple-effect”><span><?php echo $attachment_title; ?></span><i><?php echo $attachment_filetype[‘ext’]; ?></i></a>
<?php } ?>
</div>
</div>
<?php endif; ?>
Single-task-bids.php
<!– Freelancers Bidding –>
<?php
$bids_args = array(
‘post_type’ => ‘bid’,
‘posts_per_page’ => 10,
‘post_parent’ => $post->ID,
//’post_status’ => ‘publish’,
‘orderby’ => ‘date’,
‘order’ => ‘DESC’,
);
$wp_query = new WP_Query($bids_args);
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
if ($wp_query->have_posts()) { ?>
<div class=”boxed-list margin-bottom-60 “>
<div class=”boxed-list-headline”>
<h3><i class=”icon-material-outline-group”></i> <?php echo esc_html_e(‘Freelancers Bidding’, ‘workscout-freelancer’) ?></h3>
</div>
<ul class=”boxed-list-ul”>
<?php while ($wp_query->have_posts()) : $wp_query->the_post();
$author_id = $post->post_author;
// check if has profile
$has_profile = get_the_author_meta(‘freelancer_profile’, $author_id);
if ($has_profile) {
$avatar = “<img src=” . get_the_candidate_photo($has_profile) . ” class=’avatar avatar-32 photo’/>”;
$username = get_the_title($has_profile);
} else {
$avatar = get_avatar($author_id, 100);
$username = get_the_author_meta(‘display_name’, $author_id);
}
?>
<li>
<div class=”bid”>
<!– Avatar –>
<div class=”bids-avatar”>
<div class=”freelancer-avatar”>
<?php if (workscout_is_user_verified($author_id)) { ?>
<div class=”verified-badge”></div>
<?php } ?>
<a href=”<?php echo get_author_posts_url($author_id); ?>”> <?php echo $avatar; ?></a>
</div>
</div>
<!– Content –>
<div class=”bids-content”>
<!– Name –>
<div class=”freelancer-name”>
<h4><a href=”<?php echo get_author_posts_url($author_id); ?>”><?php echo $username; ?>
<?php
if ($has_profile) {
$country = get_post_meta($has_profile, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries(); ?>
<img class=”flag” src=”<?php echo WORKSCOUT_FREELANCER_PLUGIN_URL; ?>/assets/images/flags/<?php echo strtolower($country); ?>.svg” title=” <?php echo $countries[$country]; ?>” data-tippy-placement=”top”>
<?php }
} ?>
</a></h4>
<?php
if ($has_profile) { ?>
<?php $rating_value = get_post_meta($has_profile, ‘workscout-avg-rating’, true);
if ($rating_value) { ?>
<div class=”star-rating” data-rating=”<?php echo esc_attr(number_format(round($rating_value, 2), 1)); ?>”></div>
<?php } ?>
<?php } ?>
</div>
</div>
<?php
$budget = get_post_meta($post->ID, ‘_budget’, true);
$time = get_post_meta($post->ID, ‘_time’, true);
?>
<!– Bid –>
<div class=”bids-bid”>
<div class=”bid-rate”>
<div class=”rate”>
<?php
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo (is_numeric($budget)) ? number_format_i18n($budget) : $budget;
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
} ?></div>
<span><?php esc_html_e(‘in ‘, ‘workscout-freelancer’); ?><?php echo $time; ?> <?php esc_html_e(‘days’,’workscout-freelancer’); ?></span>
</div>
</div>
</div>
</li>
<?php endwhile; // end of the loop.
?>
</ul>
</div>
<?php } ?>
<?php wp_reset_postdata();
wp_reset_query();
?>
Single-task-skills.php
<?php
$terms = get_the_terms($post->ID, ‘task_skill’);
if ($terms && !is_wp_error($terms)) : ?>
<!– Skills –>
<div class=”single-page-section margin-bottom-60 “>
<h3><?php esc_html_e(‘Skills Required’, ‘workscout-freelancer’); ?></h3>
<div class=”task-tags”>
<?php
foreach ($terms as $term) {
$term_link = get_term_link($term);
if (is_wp_error($term_link))
continue;
echo ‘<span><a href=”‘ . $term_link . ‘”>’ . $term->name . ‘</a></span>’;
}
?>
</div>
</div>
<div class=”clearfix”></div>
<?php endif; ?>
Archive-task.php
<?php
/**
* The template for displaying tasks
*
* @link https://codex.wordpress.org/Template_Hierarchy
*
* @package hireo
*/
$template_loader = new WorkScout_Freelancer_Template_Loader;
$task_layout = Kirki::get_option(‘workscout’, ‘tasks_archive_layout’);
wp_enqueue_script(“workscout-freelancer-ajaxsearch”);
$sidebar_site = Kirki::get_option(‘workscout’, ‘tasks_sidebar_layout’);
switch ($task_layout) {
case ‘standard-list’:
$task_list_class = ‘compact-list’;
$template = ‘content-task’;
break;
// case ‘standard-grid’:
// $task_list_class = ‘regular-list’;
// $template = ‘content-task’;
// break;
case ‘standard-grid’:
$task_list_class = ‘tasks-grid-layout ‘;
$template = ‘content-task-grid’;
break;
case ‘full-page’:
$task_list_class = ‘tasks-grid-layout ‘;
$template = ‘content-task-grid’;
break;
default:
$task_list_class = ‘compact-list’;
$template = ‘content-task’;
break;
}
($task_layout == ‘full-page’) ? get_header(‘split’) : get_header();
if ($task_layout == ‘full-page’) {
$template_loader->get_template_part(‘archive-task-full’);
} else {
if (!empty($header_image)) {
$transparent_status = Kirki::get_option(‘workscout’, ‘pp_jobs_transparent_header’);
if ($transparent_status) { ?>
<div id=”titlebar” class=”photo-bg single with-transparent-header <?php if ($map) echo ” with-map”; ?>”” style=” background: url(‘<?php echo esc_url($header_image); ?>’)”>
<?php } else { ?>
<div id=”titlebar” class=”photo-bg single <?php if ($map) echo ” with-map”; ?>” style=”background: url(‘<?php echo esc_url($header_image); ?>’)”>
<?php } ?>
<?php } else { ?>
<div id=”titlebar” class=”single “>
<?php } ?>
<div class=”container”>
<div class=”sixteen columns”>
<div class=”ten columns”>
<?php
$hide_counter = Kirki::get_option(‘workscout’, ‘pp_disable_jobs_counter’, true);
$hide_counter = false;
//if it’s archive page for taxonomy show how many items in this taxonomy
if ($hide_counter) { ?>
<?php $count_tasks = wp_count_posts(‘task’, ‘readable’);
if (is_tax()) {
$term = get_term_by(‘slug’, get_query_var(‘term’), get_query_var(‘taxonomy’));
$count_tasks->publish = $term->count;
}?>
<span class=”showing_jobs” style=”display: none”>
<?php esc_html_e(‘Browse Tasks’, ‘workscout’) ?>
</span>
<h2><?php
printf(_n(‘We have <em class=”count_jobs”>%s</em> <em class=”tasks_text”>tasks</em> for you’, ‘We have <em class=”count_jobs”>%s</em> <em class=”tasks_text”>tasks</em> for you’, $count_tasks->publish, ‘workscout-freelancer’), $count_tasks->publish); ?>
</h2>
<?php } else { ?>
<h1><?php esc_html_e(‘Tasks’, ‘workscout’); ?></h1>
<?php } ?>
</div>
<?php
$call_to_action = Kirki::get_option(‘workscout’, ‘pp_call_to_action_jobs’, ‘job’);
switch ($call_to_action) {
case ‘job’:
get_template_part(‘template-parts/button’, ‘job’);
break;
case ‘resume’:
get_template_part(‘template-parts/button’, ‘resume’);
break;
default:
# code…
break;
}
?>
</div>
</div>
</div>
<div class=”margin-top-90″></div>
<div class=”container”>
<div class=”row”>
<?php
if ($sidebar_site == ‘left’) {
$classes = ‘col-xl-9 col-lg-9 content-left-offset’;
} else {
$classes = ‘col-xl-9 col-lg-9 content-right-offset’;
} ?>
<?php if ($sidebar_site == ‘left’) { ?>
<div class=”col-xl-3 col-lg-3″>
<div class=”sidebar-container”>
<?php echo workscout_generate_tasks_sidebar(); ?>
<div class=”clearfix”></div>
</div>
</div>
<?php } ?>
<div class=”<?php echo $classes; ?>”>
<div class=”tasks-list-container <?php echo $task_list_class; ?> margin-top-35″>
<?php /* Start the Loop */
if (have_posts()) :
/* Start the Loop */
while (have_posts()) : the_post();
$template_loader->get_template_part($template);
endwhile;
else :
get_template_part(‘template-parts/content’, ‘none’);
endif;
?>
</div>
<!– Pagination –>
<div class=”clearfix”></div>
<div class=”row”>
<div class=”col-md-12″>
<?php $ajax_browsing = get_option(‘task_ajax_browsing’); ?>
<!– Pagination –>
<div class=”pagination-container <?php if ($ajax_browsing == ‘1’) {
echo ‘ajax-search’;
} ?> “>
<nav class=”pagination”>
<?php
if ($ajax_browsing == ‘1’) {
global $wp_query;
$pages = $wp_query->max_num_pages;
echo workscout_freelancer_ajax_pagination($pages, 1);
} else
if (function_exists(‘wp_pagenavi’)) {
wp_pagenavi(array(
‘next_text’ => ‘<i class=”fa fa-chevron-right”></i>’,
‘prev_text’ => ‘<i class=”fa fa-chevron-left”></i>’,
‘use_pagenavi_css’ => false,
));
} else {
global $wp_query;
$pages = $wp_query->max_num_pages;
echo workscout_freelancer_pagination($pages, 1);
} ?>
</nav>
</div>
</div>
</div>
<!– Pagination / End –>
</div>
<?php if ($sidebar_site == ‘right’) { ?>
<div class=”col-xl-3 col-lg-3″>
<div class=”sidebar-container”>
<?php echo workscout_generate_tasks_sidebar(); ?>
<div class=”clearfix”></div>
</div>
</div>
<?php } ?>
</div>
</div>
<?php
get_footer();
}
Archive-task-full.php
<?php
/**
* The template for displaying tasks
*
* @link https://codex.wordpress.org/Template_Hierarchy
*
* @package hireo
*/
$top_layout = get_option(‘wf_task_layout’);
wp_enqueue_script(“workscout-freelancer-ajaxsearch”);
get_header(‘split’);
$template_loader = new WorkScout_Freelancer_Template_Loader;
?>
<!– Page Content
================================================== –>
<div class=”full-page-container-v2″>
<div class=”full-page-sidebar-v2″>
<div class=”full-page-sidebar-inner-v2″ data-simplebar>
<div class=”sidebar-container-v2″>
<?php echo workscout_generate_tasks_sidebar(); ?>
</div>
<!– Sidebar Container / End –>
<!– Search Button –>
<div class=”sidebar-search-button-container”>
<button class=”button ripple-effect”><?php esc_html_e(‘Search’, ‘workscout-freelancer’)?></button>
</div>
<!– Search Button / End–>
</div>
</div>
<!– Full Page Sidebar / End –>
<!– Full Page Content –>
<div class=”full-page-content-container-v2″ data-simplebar>
<div class=”full-page-content-inner-v2″>
<h3 class=”page-title”><?php esc_html_e(‘Search Results’, ‘workscout-freelancer’); ?></h3>
<div class=”tasks-list-container tasks-grid-layout margin-top-35″>
<?php /* Start the Loop */
while (have_posts()) : the_post();
$template_loader->get_template_part(‘content-task-grid’);
endwhile;
?>
</div>
<!– Pagination –>
<div class=”clearfix”></div>
<?php $ajax_browsing = get_option(‘task_ajax_browsing’); ?>
<!– Pagination –>
<div class=”pagination-container <?php if ($ajax_browsing == ‘1’) {
echo ‘ajax-search’;
} ?> “>
<nav class=”pagination”>
<?php
if ($ajax_browsing == ‘1’) {
global $wp_query;
$pages = $wp_query->max_num_pages;
echo workscout_freelancer_ajax_pagination($pages, 1);
} else
if (function_exists(‘wp_pagenavi’)) {
wp_pagenavi(array(
‘next_text’ => ‘<i class=”fa fa-chevron-right”></i>’,
‘prev_text’ => ‘<i class=”fa fa-chevron-left”></i>’,
‘use_pagenavi_css’ => false,
));
} else {
the_posts_navigation();
} ?>
</nav>
</div>
<!– Pagination / End –>
<div class=”clearfix”></div>
<!– Pagination / End –>
<!– Footer –>
<?php get_template_part(‘template-parts/split-footer’); ?>
<!– Footer / End –>
</div>
</div>
<!– Full Page Content / End –>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
Content-single-task.php
<?php
if (!defined(‘ABSPATH’)) {
exit;
}
$template_loader = new WorkScout_Freelancer_Template_Loader;
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$task_type = get_post_meta($post->ID, ‘_task_type’, true);
$company = get_post_meta($post->ID, ‘_company_id’, true);
$header_bg_image = get_post_meta($post->ID, ‘_header_bg_image’, true);
$budget_min = get_post_meta($post->ID, ‘_budget_min’, true);
$budget_max = get_post_meta($post->ID, ‘_budget_max’, true);
$hourly_min = get_post_meta($post->ID, ‘_hourly_min’, true);
$hourly_max = get_post_meta($post->ID, ‘_hourly_max’, true);
if ($task_type == ‘hourly’) {
$range_min = $hourly_min;
$range_max = $hourly_max;
} else {
$range_min = $budget_min;
$range_max = $budget_max;
}
if (empty($range_min) && !empty($range_max)) {
$range_min = $range_max – ($range_max * 0.3);
}
if (empty($range_max) && !empty($range_min)) {
$range_max = $range_min – ($range_max * 0.3);
}
?>
<!– Titlebar
================================================== –>
<div class=”single-page-header” <?php if ($header_bg_image) : ?>data-background-image=”<?php echo $header_bg_image; ?>” <?php endif; ?>>
<div class=”container”>
<div class=”row”>
<div class=”col-md-12″>
<div class=”single-page-header-inner”>
<div class=”left-side”>
<?php if (!empty($company)) { ?>
<div class=”header-image”><a href=”<?php get_permalink($company); ?>”> <?php
if ($company) {
the_company_logo(‘medium’, null, $company);
} else {
the_company_logo(‘medium’);
} ?></a></div>
<?php } ?>
<div class=”header-details”>
<h3><?php the_title(); ?></h3>
<?php $template_loader->get_template_part(‘single-partials/single-company’, ‘data’); ?>
</div>
</div>
<div class=”right-side”>
<div class=”salary-box”>
<div class=”salary-type”>
<?php
if ($task_type == ‘hourly’) {
esc_html_e(‘Hourly Rate’, ‘workscout-freelancer’);
} else {
esc_html_e(‘Project Budget’, ‘workscout-freelancer’);
} ?>
</div>
<div class=”salary-amount”>
<?php
if ($task_type == ‘hourly’) {
if ($hourly_min) {
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_min));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
if ($hourly_max && $hourly_max > $hourly_min) {
if ($hourly_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_max));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
} else {
if ($budget_min) {
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_min));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
if ($budget_max && $budget_max > $budget_min) {
if ($budget_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_max));
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
}
}
}
?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!– Page Content
================================================== –>
<div class=”container”>
<div class=”row”>
<!– Content –>
<div class=”col-xl-8 col-lg-8 content-right-offset”>
<div class=”single-page-section”>
<h3 class=”margin-bottom-25″><?php esc_html_e(‘Project Description’, ‘workscout-freelancer’); ?></h3>
<?php the_content(); ?>
</div>
<?php $template_loader->get_template_part(‘single-partials/single-task’, ‘attachments’); ?>
<?php $template_loader->get_template_part(‘single-partials/single-task’, ‘skills’); ?>
</div>
<!– Sidebar –>
<div class=”col-xl-4 col-lg-4″>
<div class=”sidebar-container”>
<?php
$deadline = workscout_get_bidding_deadline($post->ID);
if (!$deadline) {
if (is_array($deadline)) : ?>
<div class=”countdown green margin-bottom-35″>
<?php echo $deadline[‘days’];
echo $deadline[‘hours’] ?> left </div>
<?php else : ?>
<div class=”countdown green margin-bottom-35″><?php esc_html_e(‘Bidding has closed’, ‘workscout-freelancer’); ?></div>
<?php endif;
} ?>
<?php get_sidebar(‘task’); ?>
</div>
</div>
</div>
</div>
Content-task.php
<?php setup_postdata($post->ID); ?>
<!– Task –>
<a href=”<?php the_permalink(); ?>” class=”task-listing <?php if (is_position_featured()) {
echo ‘task-listing-featured’;
} ?>”>
<?php if (is_position_featured()) { ?>
<div class=”listing-badge”><i class=”fa fa-star”></i></div>
<?php } ?>
<!– Job Listing Details –>
<div class=”task-listing-details”>
<!– Details –>
<div class=”task-listing-description”>
<h3 class=”task-listing-title”>
<?php the_title(); ?>
</h3>
<ul class=”task-icons”>
<?php $company = get_post_meta($post->ID, ‘_company_id’, true);
if ($company) { ?>
<li><i class=”icon-material-outline-business”></i> <?php echo get_the_title($company); ?></li>
<?php } else { ?>
<li><i class=”icon-material-outline-account-circle”></i> <?php esc_html_e(‘Private Person’, ‘workscout-freelancer’); ?></li>
<?php } ?>
<li><i class=”icon-material-outline-location-on”></i> <?php ws_task_location(); ?></li>
<li><i class=”icon-material-outline-access-time”></i> <?php task_publish_date() ?></li>
</ul>
<p class=”task-listing-text”><?php $content = get_the_content();
echo wp_trim_words(get_the_content(), 20, ‘…’); ?></p>
<?php
$terms = get_the_terms($post->ID, ‘task_skill’);
if ($terms && !is_wp_error($terms)) :
echo ‘<div class=”task-tags”>’;
$jobcats = array();
foreach ($terms as $term) {
echo “<span>” . $term->name . “</span>”;
}
?>
</div>
<?php
endif; ?>
</div>
</div>
<div class=”task-listing-bid”>
<div class=”task-listing-bid-inner”>
<?php
?>
<div class=”task-offers”>
<strong><?php echo get_workscout_task_range(); ?></strong>
<span><?php echo get_workscout_task_type(); ?></span>
</div>
<span class=”button button-sliding-icon ripple-effect”><?php esc_html_e(‘Bid Now’, ‘workscout-freelancer’); ?> <i class=”icon-material-outline-arrow-right-alt”></i></span>
</div>
</div>
</a>
Content-task-grid.php
<?php
$currency_position = get_option(‘workscout_currency_position’, ‘before’); ?>
<!– Task –>
<a href=”<?php the_permalink(); ?>” class=”task-listing <?php if (is_position_featured()) {
echo ‘task-listing-featured’;
} ?>”>
<!– Job Listing Details –>
<div class=”task-listing-details”>
<?php if (is_position_featured()) { ?>
<div class=”listing-badge”><i class=”fa fa-star”></i></div>
<?php } ?>
<!– Details –>
<div class=”task-listing-description”>
<h3 class=”task-listing-title”>
<?php the_title(); ?>
</h3>
<ul class=”task-icons”>
<?php $company = get_post_meta($post->ID, ‘_company_id’, true);
if ($company) { ?>
<li><i class=”icon-material-outline-business”></i> <?php echo get_the_title($company); ?></li>
<?php } else { ?>
<li><i class=”icon-material-outline-account-circle”></i> <?php esc_html_e(‘Private Person’, ‘workscout-freelancer’); ?></li>
<?php } ?>
<li><i class=”icon-material-outline-location-on”></i> <?php ws_task_location(); ?></li>
<li><i class=”icon-material-outline-access-time”></i> <?php task_publish_date() ?></li>
</ul>
<?php
$terms = get_the_terms($post->ID, ‘task_skill’);
if ($terms && !is_wp_error($terms)) :
echo ‘<div class=”task-tags”>’;
$jobcats = array();
foreach ($terms as $term) {
echo “<span>” . $term->name . “</span>”;
}
?>
</div>
<?php
endif; ?>
</div>
</div>
<div class=”task-listing-bid”>
<div class=”task-listing-bid-inner”>
<?php
$budget_min = get_post_meta($post->ID, ‘_budget_min’, true);
$budget_max = get_post_meta($post->ID, ‘_budget_max’, true);
?>
<div class=”task-offers”>
<strong><?php echo get_workscout_task_range(); ?></strong>
<span><?php echo get_workscout_task_type(); ?></span>
</div>
<span class=”button button-sliding-icon ripple-effect”><?php esc_html_e(‘Bid Now’, ‘workscout-freelancer’); ?> <i class=”icon-material-outline-arrow-right-alt”></i></span>
</div>
</div>
</a>
My-bids.php
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<?php $currency_position = get_option(‘workscout_currency_position’, ‘before’); ?>
<!– Headline –>
<div class=”headline”>
<h3><i class=”icon-material-outline-gavel”></i> <?php esc_html_e(‘Bids List’, ‘workscout-freelancer’); ?></h3>
<div class=”sort-by”>
<form id=”tasks-sort-by-form” action=” <?php the_permalink(); ?>” method=”get”>
<?php
$selected = isset($_REQUEST[‘sort-by’]) ? $_REQUEST[‘sort-by’] : ”;
?>
<select name=”sort-by” class=”select2-single hide-tick tasks-sort-by”>
<option <?php selected($selected, ”) ?> value=””><?php esc_html_e(‘Active’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘closed’) ?>value=”closed”><?php esc_html_e(‘Closed’, ‘workscout-freelancer’); ?></option>
</select>
</form>
</div>
</div>
<div class=”content”>
<ul class=”dashboard-box-list”>
<?php if (!$bids) : ?>
<li><?php esc_html_e(‘You do not have any bids.’, ‘workscout’); ?></li>
<?php endif; ?>
<?php foreach ($bids as $key => $bid) {
$task_id = wp_get_post_parent_id($bid->ID);
$has_won = get_post_meta($bid->ID, ‘_selected_for_task_id’, true);
// check status of task_id
$task_status = get_post_status($task_id);
?>
<li id=”my-bids-bid-id-<?php echo $bid->ID; ?>” data-bid-id=”<?php echo $bid->ID; ?>” class=” <?php if ($has_won) echo “bid-selected-for-task” ?>”>
<!– Job Listing –>
<div class=”item-listing width-adjustment”>
<!– Job Listing Details –>
<div class=”item-listing-details”>
<!– Details –>
<div class=”item-listing-description”>
<h3 class=”item-listing-title”><a href=”<?php echo get_the_permalink($task_id); ?>”><?php echo get_the_title($task_id); ?></a></h3>
<?php if ($has_won) : ?>
<p><?php esc_html_e(‘Your bid was accepted for task’, ‘workscout-freelancer’); ?> <a href=”<?php echo get_the_permalink($has_won); ?>”><?php echo get_the_title($has_won); ?></a></p>
<?php endif;
if (!$has_won && $task_status == ‘expired’) : ?>
<p><?php esc_html_e(‘Task has expired, your bid was not accepted’, ‘workscout-freelancer’); ?></p>
<?php endif; ?>
</div>
</div>
</div>
<?php
$budget = get_post_meta($bid->ID, ‘_budget’, true);
$scale = get_post_meta($bid->ID, ‘_time_scale’, true);
$time = get_post_meta($bid->ID, ‘_time’, true);
if ($budget) { ?>
<!– Bid Details –>
<ul class=”dashboard-task-info”>
<li id=”bid-info-budget”><strong><?php
if ($currency_position == ‘before’) {
echo get_workscout_currency_symbol();
} ?><?php echo (is_numeric($budget)) ? number_format_i18n($budget) : $budget;
if ($currency_position == ‘after’) {
echo get_workscout_currency_symbol();
} ?></strong><span><?php esc_html_e(‘Hourly Rate’, ‘workscout-freelancer’); ?></span></li>
<li id=”bid-info-time”><strong><?php echo $time; ?> <?php echo $scale; ?></strong><span><?php esc_html_e(‘Delivery Time’, ‘workscout-freelancer’); ?></span></li>
</ul>
<?php } ?>
<?php
if (!$has_won) : ?>
<!– Buttons –>
<div data-bid-id=”<?php echo esc_attr($bid->ID) ?>” class=”buttons-to-right always-visible”>
<a class=”bids-action-edit-bid button dark ripple-effect ico” title=”<?php esc_html_e(‘Edit Bid’, ‘workscout-freelancer’); ?>” data-tippy-placement=”top”><i class=”icon-feather-edit”></i></a>
<?php
$actions = apply_filters(‘task_manager_bookmark_actions’, array(
‘delete’ => array(
‘label’ => esc_html__(‘Cancel Bid’, ‘workscout-freeelancer’),
‘url’ => wp_nonce_url(add_query_arg(‘remove_bid’, $bid->ID), ‘remove_bid’)
)
), $bid);
foreach ($actions as $action => $value) {
echo ‘<a href=”‘ . esc_url($value[‘url’]) . ‘” title=’ . $value[‘label’] . ‘ data-tippy-placement=”top” class=”button red ripple-effect ico delete workscout-bid-action-‘ . $action . ‘”><i class=”icon-feather-trash-2″></i> </a>’;
}
?>
</div>
<?php endif; ?>
</li>
<?php } ?>
</ul>
</div>
</div>
<!– Edit Bid Popup
================================================== –>
<?php
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$currency_symbol = get_workscout_currency_symbol();
?>
<div id=”small-dialog” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Edit Bid’, ‘workscout-freelancer’); ?></h3>
</div>
<!– Bidding –>
<div class=”bidding-widget”>
<!– Headline –>
<form autocomplete=”off” id=”form-bidding-update” data-post_id=”” class=”” method=”post”>
<!– Headline –>
<span class=”bidding-detail bidding-detail-hourly”><?php esc_html_e(‘Set your’, ‘workscout’); ?> <strong><?php esc_html_e(‘hourly rate’, ‘workscout-freelancer’); ?></strong></span>
<span class=”bidding-detail bidding-detail-fixed”><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘bid amount’, ‘workscout-freelancer’); ?></strong></span>
<!– Price Slider –>
<!– Price Slider –>
<div class=”bidding-value”>
<?php
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
?><span class=”biddingVal”></span>
<?php
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
?></div>
<input name=”budget” class=” bidding-slider-popup” type=”text” value=”” data-slider-handle=”custom” data-slider-currency=”$” data-slider-min=”10″ data-slider-max=”20″ data-slider-step=”1″ data-slider-tooltip=”hide” />
<!– Headline –>
<span class=”bidding-detail bidding-detail-hourly margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in hours’, ‘workscout-freelancer’); ?></span>
<span class=”bidding-detail bidding-detail-fixed margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in days’, ‘workscout-freelancer’); ?></span>
<!– Fields –>
<div class=”bidding-fields”>
<div class=”bidding-field”>
<!– Quantity Buttons –>
<div class=”qtyButtons”>
<div class=”qtyDec”></div>
<input type=”text” class=”bidding-time bidding-time-popup” id=”qtyInput” name=”bid-time” value=”1″>
<div class=”qtyInc”></div>
</div>
</div>
</div>
<div>
<div class=”bidding-field”>
<span class=”bidding-detail margin-top-30″><?php esc_html_e(‘Describe your proposal’, ‘workscout-freelancer’); ?></span>
<textarea name=”bid-proposal” id=”bid-proposal” cols=”30″ rows=”5″ placeholder=”<?php esc_html_e(‘What makes you the best candidate for that project?’, ‘workscout-freelancer’); ?>”></textarea>
</div>
</div>
<input type=”hidden” name=”bid_id” id=”bid_id”>
<!– Button –>
<button id=”snackbar-place-bid” form=”form-bidding-update” class=”button ripple-effect move-on-hover full-width margin-top-30″><span><?php esc_html_e(‘Update your Bid’, ‘workscout-freelancer’); ?></span></button>
</form>
</div>
</div>
<a style=”display: none;” href=”#small-dialog” class=”popup-with-zoom-anim button dark ripple-effect ico” title=”Edit Bid” data-tippy-placement=”top”><i class=”icon-feather-edit”></i></a>
<!– Edit Bid Popup / End –>
My-projects.php
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<?php $currency_position = get_option(‘workscout_currency_position’, ‘before’); ?>
<!– Headline –>
<div class=”headline”>
<h3><i class=”icon-material-outline-folder”></i> <?php esc_html_e(‘Projects List’, ‘workscout-freelancer’); ?></h3>
<div class=”sort-by”>
<form id=”tasks-sort-by-form” action=” <?php the_permalink(); ?>” method=”get”>
<?php
$selected = isset($_REQUEST[‘sort-by’]) ? $_REQUEST[‘sort-by’] : ”;
?>
<select name=”sort-by” class=”select2-single hide-tick tasks-sort-by”>
<option <?php selected($selected, ”) ?> value=””><?php esc_html_e(‘Active’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘closed’) ?>value=”closed”><?php esc_html_e(‘Closed’, ‘workscout-freelancer’); ?></option>
</select>
</form>
</div>
</div>
<div class=”content”>
<ul class=”dashboard-box-list”>
<?php if (!$projects) : ?>
<li><?php esc_html_e(‘You do not have any projects.’, ‘workscout’); ?></li>
<?php endif; ?>
<?php foreach ($projects as $key => $project) {
$task_id = get_post_meta($project->ID, ‘_task_id’, true);
$status = get_post_meta($project->ID, ‘_status’, true);
$task_status = get_post_status($task_id);
$action_url = add_query_arg(array(‘action’ => ‘view-project’, ‘task_id’ => $task_id, ‘project_id’ => $project->ID)); ?>
<li id=”my-projects-project-id-<?php echo $project->ID; ?>” data-project-id=”<?php echo $project->ID; ?>” class=””>
<!– Job Listing –>
<div class=”item-listing width-adjustment”>
<!– Job Listing Details –>
<div class=”item-listing-details”>
<!– Details –>
<div class=”item-listing-description”>
<h3 class=”item-listing-title”><a href=”<?php echo $action_url; ?>”><?php echo get_the_title($project->ID); ?></a>
<?php
$task_id = get_post_meta($project->ID, ‘_task_id’, true);
?>
<span class=”dashboard-status-button <?php switch ($project->post_status) {
case ‘expired’:
echo ‘red’;
break;
case ‘publish’:
echo ‘green’;
break;
default:
echo ‘yellow’;
break;
}; ?>”>
<?php the_task_status($task_id); ?>
</span>
</h3>
<div class=”item-listing-footer”>
<?php
$project_class = new WorkScout_Freelancer_Project();
$completion = $project_class->calculate_project_completion($project->ID);
?>
<ul class=” item-details margin-top-10″>
<li><?php echo esc_html__(‘Project Completion:’, ‘workscout-freelancer’); ?> <strong><?php echo number_format($completion, 0); ?>%</strong></li>
</ul>
<progress value=”<?php echo number_format($completion, 0); ?>” max=”100″ style=”–value: <?php echo number_format($completion, 0); ?>; –max: 100;”></progress>
</div>
</div>
</div>
</div>
<div data-project-id=”<?php echo esc_attr($project->ID) ?>” class=”buttons-to-right always-visible”>
<a href=”<?php echo $action_url; ?>” class=”button dark ripple-effect” href=”#”><i class=”icon-material-outline-supervisor-account”></i><?php esc_html_e(‘View Project ‘, ‘workscout-freelancer’); ?></a>
<?php
?>
</div>
</li>
<?php } ?>
</ul>
</div>
</div>
<!– Edit project Popup
================================================== –>
<?php
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$currency_symbol = get_workscout_currency_symbol();
?>
<div id=”small-dialog” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Edit project’, ‘workscout-freelancer’); ?></h3>
</div>
<!– projectding –>
<div class=”projectding-widget”>
<!– Headline –>
<form autocomplete=”off” id=”form-projectding-update” data-post_id=”” class=”” method=”post”>
<!– Headline –>
<span class=”projectding-detail projectding-detail-hourly”><?php esc_html_e(‘Set your’, ‘workscout’); ?> <strong><?php esc_html_e(‘hourly rate’, ‘workscout-freelancer’); ?></strong></span>
<span class=”projectding-detail projectding-detail-fixed”><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘project amount’, ‘workscout-freelancer’); ?></strong></span>
<!– Price Slider –>
<!– Price Slider –>
<div class=”projectding-value”>
<?php
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
?><span class=”projectdingVal”></span>
<?php
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
?></div>
<input name=”budget” class=” projectding-slider-popup” type=”text” value=”” data-slider-handle=”custom” data-slider-currency=”$” data-slider-min=”10″ data-slider-max=”20″ data-slider-step=”1″ data-slider-tooltip=”hide” />
<!– Headline –>
<span class=”projectding-detail projectding-detail-hourly margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in hours’, ‘workscout-freelancer’); ?></span>
<span class=”projectding-detail projectding-detail-fixed margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in days’, ‘workscout-freelancer’); ?></span>
<!– Fields –>
<div class=”projectding-fields”>
<div class=”projectding-field”>
<!– Quantity Buttons –>
<div class=”qtyButtons”>
<div class=”qtyDec”></div>
<input type=”text” class=”projectding-time projectding-time-popup” id=”qtyInput” name=”project-time” value=”1″>
<div class=”qtyInc”></div>
</div>
</div>
</div>
<div>
<div class=”projectding-field”>
<span class=”projectding-detail margin-top-30″><?php esc_html_e(‘Describe your proposal’, ‘workscout-freelancer’); ?></span>
<textarea name=”project-proposal” id=”project-proposal” cols=”30″ rows=”5″ placeholder=”<?php esc_html_e(‘What makes you the best candidate for that project?’, ‘workscout-freelancer’); ?>”></textarea>
</div>
</div>
<input type=”hidden” name=”project_id” id=”project_id”>
<!– Button –>
<button id=”snackbar-place-project” form=”form-projectding-update” class=”button ripple-effect move-on-hover full-width margin-top-30″><span><?php esc_html_e(‘Update your project’, ‘workscout-freelancer’); ?></span></button>
</form>
</div>
</div>
<a style=”display: none;” href=”#small-dialog” class=”popup-with-zoom-anim button dark ripple-effect ico” title=”Edit project” data-tippy-placement=”top”><i class=”icon-feather-edit”></i></a>
<!– Edit project Popup / End –>
No-task-found.php
<ul class=”job_listings job-list full new-layout”>
<li class=”no_job_listings_found”><?php esc_html_e(‘There are no tasks matching your search.’, ‘workscout-freelancer’); ?></li>
</ul>
Project-view.php
<?php
$project_id = $project->ID;
$task_id = get_post_meta($project_id, ‘_task_id’, true);
$freelancer = get_post_meta($project_id, ‘_freelancer_id’, true);
$employer = get_post_meta($project_id, ‘_employer_id’, true);
$_selected_bid_id = get_post_meta($project_id, ‘_selected_bid_id’, true);
$bid = get_post($_selected_bid_id);
$bid_meta = get_post_meta($_selected_bid_id);
$bid_author = $bid->post_author;
$bid_proposal = $bid->post_content;
$bid_data = array(
‘budget’ => get_post_meta($_selected_bid_id, ‘_budget’, true),
‘time’ => get_post_meta($_selected_bid_id, ‘_time’, true),
‘proposal’ => $bid_proposal,
);
$freelancer_project = WorkScout_Freelancer_Project::instance();
// check if current author is freelancer or employer, if not return
if (get_current_user_id() != $freelancer && get_current_user_id() != $employer) {
return;
}
// get flag for user is freelancer or employer
if (get_current_user_id() == $freelancer) {
$is_freelancer = true;
} else {
$is_freelancer = false;
}
?>
<div class=”row”>
<div class=”col-lg-8″>
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<div class=”headline”>
<h3><i class=”icon-material-outline-assignment”></i> <?php esc_html_e(‘Project’, ‘workscout-freelancer’); ?>: <?php echo get_the_title($project_id) ?> </h3>
</div>
<div class=”content”>
<div class=”project-view-content”>
<h4><?php esc_html_e(‘Project Description:’, ‘workscout-freelancer’); ?></h4>
<div class=”project-view-description”>
<?php echo apply_filters(‘the_content’, get_post_field(‘post_content’, $project_id)); ?>
</div>
</div>
</div>
</div>
<div class=”dashboard-box dashboard-tasks-box”>
<div class=”headline”>
<h3><i class=”icon-material-baseline-mail-outline”></i> <?php esc_html_e(‘Discussion’, ‘workscout-freelancer’); ?> </h3>
</div>
<div class=”content”>
<div class=”project-discussion-content”>
<div class=”notification notice margin-bottom-25 “>
<?php esc_html_e(‘This session is private, comments are only visible to you and your expert’, ‘workscout-freelancer’); ?>
</div>
<?php
// Add this near the top of the comments section
if (isset($_GET[‘comment_posted’]) && $_GET[‘comment_posted’] === ‘true’) : ?>
<div class=”notification success closeable”>
<p><?php esc_html_e(‘Comment posted successfully!’, ‘workscout-freelancer’); ?></p>
<a class=”close”></a>
</div>
<?php endif; ?>
<?php
$comments = get_comments(array(
‘post_id’ => $project_id,
‘status’ => ‘approve’
));
if ($comments) {
echo ‘<ul class=”project-comment-list”>’;
wp_list_comments(array(
‘per_page’ => 10, // Number of comments to show per page
‘callback’ => ‘workscout_project_comment’,
), $comments);
echo ‘</ul>’;
} else {
echo ‘<p>’ . __(‘No comments yet.’, ‘workscout-freelancer’) . ‘</p>’;
}
?>
<form method=”post” action=”” enctype=”multipart/form-data” class=”project-comment-form”>
<?php wp_nonce_field(‘project_comment_action’, ‘project_comment_nonce’); ?>
<input type=”hidden” name=”project_id” value=”<?php echo esc_attr($project_id); ?>”>
<div class=”form-group”>
<textarea name=”comment_content” required class=”with-border” placeholder=”<?php esc_html_e(‘Type your message here…’, ‘workscout-freelancer’); ?>”></textarea>
</div>
<div class=”form-group”>
<label><?php esc_html_e(‘Attach Files:’, ‘workscout-freelancer’); ?></label>
<div class=”uploadButton margin-top-0″>
<input class=”uploadButton-input” type=”file” name=”comment_files[]” multiple id=”upload” accept=”image/*, application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/zip” />
<label class=”uploadButton-button ripple-effect” for=”upload”><?php esc_html_e(‘Upload Files’, ‘workscout-freelancer’); ?></label>
<span class=”uploadButton-file-name”><?php printf(esc_html__(‘Maximum file size: %s.’, ‘workscout-freelancer’), size_format(wp_max_upload_size())); ?></span>
</div>
</div>
<button type=”submit” name=”submit_project_comment” class=”button ripple-effect”><?php esc_html_e(‘Submit Comment’, ‘workscout-freelancer’); ?></button>
</form>
</div>
</div>
</div>
</div>
<div class=”col-lg-4″>
<?php if (!$is_freelancer) :
$user_info = get_userdata($freelancer); ?>
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<div class=”headline”>
<h3><i class=”icon-material-outline-account-circle”></i><?php esc_html_e(‘Your Freelancer:’, ‘listeo_core’); ?>
</div>
<div class=”content”>
<div class=”freelancer-overview project-view”>
<div class=”freelancer-overview-inner”>
<?php $user_profile_id = get_user_meta($freelancer, ‘freelancer_profile’, true);
if ($user_profile_id) {
$avatar = “<img src=” . get_the_candidate_photo($user_profile_id) . ” class=’avatar avatar-32 photo’/>”;
$username = get_the_title($user_profile_id);
} else {
$avatar = get_avatar($freelancer, 32);
$username = workscout_get_users_name($freelancer);
}
?>
<!– Avatar –>
<div class=”freelancer-avatar”>
<?php if (workscout_is_user_verified($freelancer)) { ?><div class=”verified-badge”></div><?php } ?>
<?php echo $avatar; ?>
</div>
<!– Name –>
<div class=”freelancer-name”>
<h4><a href=”<?php the_permalink(); ?>”><?php echo $username; ?>
<?php
if ($user_profile_id) {
$country = get_post_meta($user_profile_id, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries();
?>
<img class=” flag” src=”<?php echo get_template_directory_uri() ?>/images/flags/<?php echo strtolower($country); ?>.svg” alt=”” title=”<?php echo $countries[$country]; ?>” data-tippy-placement=”top”>
<?php }
} ?>
</a>
</h4>
<?php the_candidate_title(‘<span>’, ‘</span> ‘, true, $freelancer); ?>
<?php if (class_exists(‘WorkScout_Freelancer’)) { ?>
<?php $rating_value = get_post_meta($user_profile_id, ‘workscout-avg-rating’, true);
if ($rating_value) { ?>
<div class=”freelancer-rating”>
<div class=”star-rating” data-rating=”<?php echo esc_attr(number_format(round($rating_value, 2), 1)); ?>”></div>
</div>
<?php } else { ?>
<div class=”company-not-rated margin-bottom-5″><?php esc_html_e(‘Not rated yet’, ‘workscout’); ?></div>
<?php }
} ?>
</div>
</div>
</div>
<div class=”project-view-content”>
<div class=”item-listing-footer”>
<ul>
<li><a href=”mailto:<?php echo $user_info->user_email; ?>”><i class=”icon-feather-mail”></i>
<?php echo $user_info->user_email; ?>
</a></li>
<?php if ($user_info->phone) { ?>
<li><i class=”icon-feather-phone”></i> <?php echo $user_info->phone; ?></li>
<?php } ?>
<?php
$country = get_post_meta($user_profile_id, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries();
?>
<li class=”dashboard-resume-flag”><img class=”flag” src=”<?php echo WORKSCOUT_FREELANCER_PLUGIN_URL; ?>/assets/images/flags/<?php echo strtolower($country); ?>.svg” alt=””> <?php echo $countries[$country]; ?></li>
<?php } ?>
</ul>
</div>
</div>
</div>
</div>
<?php else :
// is employer :
?>
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<!– <div class=”headline”>
<h3><i class=”icon-material-outline-business-center”></i> <?php esc_html_e(‘Project Author:’, ‘listeo_core’); ?>
<?php echo get_avatar(get_the_author_meta(‘ID’, $employer), 50); ?>
<?php echo get_the_author_meta(‘display_name’, $employer); ?> </h3>
</div> –>
<div class=”freelancer-overview project-view”>
<div class=”freelancer-overview-inner”>
<?php $user_profile_id = get_user_meta($freelancer, ‘freelancer_profile’, true);
if ($user_profile_id) {
$avatar = “<img src=” . get_the_candidate_photo($user_profile_id) . ” class=’avatar avatar-32 photo’/>”;
$username = get_the_title($user_profile_id);
} else {
$avatar = get_avatar($freelancer, 32);
$username = workscout_get_users_name($freelancer);
}
?>
<!– Avatar –>
<div class=”freelancer-avatar”>
<?php if (workscout_is_user_verified($freelancer)) { ?><div class=”verified-badge”></div><?php } ?>
<?php echo $avatar; ?>
</div>
<!– Name –>
<div class=”freelancer-name”>
<h4><a href=”<?php the_permalink(); ?>”><?php echo $username; ?>
<?php
if ($user_profile_id) {
$country = get_post_meta($user_profile_id, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries();
?>
<img class=” flag” src=”<?php echo get_template_directory_uri() ?>/images/flags/<?php echo strtolower($country); ?>.svg” alt=”” title=”<?php echo $countries[$country]; ?>” data-tippy-placement=”top”>
<?php }
} ?>
</a>
</h4>
<?php the_candidate_title(‘<span>’, ‘</span> ‘, true, $freelancer); ?>
<?php if (class_exists(‘WorkScout_Freelancer’)) { ?>
<?php $rating_value = get_post_meta($user_profile_id, ‘workscout-avg-rating’, true);
if ($rating_value) { ?>
<div class=”freelancer-rating”>
<div class=”star-rating” data-rating=”<?php echo esc_attr(number_format(round($rating_value, 2), 1)); ?>”></div>
</div>
<?php } else { ?>
<div class=”company-not-rated margin-bottom-5″><?php esc_html_e(‘Not rated yet’, ‘workscout’); ?></div>
<?php }
} ?>
</div>
</div>
</div>
<div class=”content”>
<div class=”project-view-content”>
<div class=”employer-detail:””>
<strong><?php esc_html_e(‘Email: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo get_the_author_meta(‘user_email’, $employer); ?>
</div>
<?php $location = get_the_author_meta(‘location’, $employer);
if ($location) { ?>
<div class=” employer-detail”>
<strong><?php esc_html_e(‘Location: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo get_the_author_meta(‘location’, $employer); ?>
</div>
<?php } ?>
<div class=”employer-detail”>
<strong><?php esc_html_e(‘Profile: ‘, ‘workscout-freelancer’); ?></strong>
<a href=”<?php echo get_author_posts_url($employer); ?>”><?php esc_html_e(‘View Profile’, ‘listeo_core’); ?></a>
</div>
</div>
</div>
</div>
<?php endif; ?>
<div class=”dashboard-box dashboard-tasks-box margin-top-20″>
<div class=”headline”>
<h3><i class=”icon-material-outline-assignment”></i> <?php esc_html_e(‘Project details:’, ‘listeo_core’); ?></h3>
</div>
<div class=”content”>
<div class=”project-view-details”>
<div class=”bidding-detail”>
<i class=”icon-material-outline-date-range”></i> <strong><?php esc_html_e(‘Posted: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo get_the_date(‘F j, Y’, $project_id); ?>
</div>
<div class=”bidding-detail”>
<i class=”icon-material-outline-info”></i> <strong><?php esc_html_e(‘Status: ‘, ‘workscout-freelancer’); ?></strong>
<?php the_task_status($task_id); ?>
</div>
<div class=”bidding-detail”>
<i class=”icon-material-outline-local-atm”></i> <strong><?php esc_html_e(‘Budget: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo workscout_output_price($bid_data[‘budget’]); ?>
</div>
<div class=”bidding-detail”>
<i class=”icon-material-outline-access-time”></i> <strong><?php esc_html_e(‘Time: ‘, ‘workscout-freelancer’); ?></strong>
<?php echo $bid_data[‘time’]; ?> days
</div>
<div class=”bidding-detail”>
<i class=”icon-material-outline-reorder”></i> <strong><?php esc_html_e(‘Proposal: ‘, ‘workscout-freelancer’); ?></strong>
<div class=”bid-proposal-text”><?php echo $bid_data[‘proposal’]; ?></div>
</div>
</div>
</div>
</div>
<?php
// Milestones box
$milestones = get_post_meta($project_id, ‘_milestones’, true);
?>
<div class=”dashboard-box dashboard-tasks-box margin-top-20″>
<div class=”headline”>
<h3><i class=”icon-material-outline-check-circle”></i> <?php esc_html_e(‘Milestones’, ‘listeo_core’); ?></h3>
</div>
<div class=”content”>
<div id=”small-dialog” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Add New Milestone’, ‘workscout-freelancer’); ?></h3>
</div>
<!– Bidding –>
<div class=”bidding-widget”>
<form id=”milestone-form” data-project-budget=”<?php echo $bid_data[‘budget’]; ?>” class=”milestone-form”>
<?php
$project_value = get_post_meta($project_id, ‘project_value’, true);
$remaining_percentage = 100 – $freelancer_project->get_total_milestone_percentage($project_id);
?>
<?php wp_nonce_field(‘workscout_milestone_nonce’, ‘milestone_nonce’); ?>
<input type=”hidden” name=”project_id” value=”<?php echo $project_id; ?>”>
<div class=”form-group”>
<label>Title</label>
<input type=”text” id=”milestone-title” name=”milestone_title” class=”form-control” required>
</div>
<div class=”form-group”>
<label><?php esc_html_e(‘Description’, ‘listeo_core’); ?></label>
<textarea id=”milestone-description” name=”milestone_description” class=”form-control” required></textarea>
</div>
<div class=”form-group form-milestone-slider”>
<label><?php esc_html_e(‘Percentage of Project Value’, ‘listeo_core’); ?></label>
<div class=”percentage-input-wrapper”>
<input type=”number”
id=”milestone-percentage”
name=”percentage”
class=”form-control”
step=”5″
min=”5″
data-slider-min=”5″ data-slider-max=”<?php echo esc_attr($remaining_percentage); ?>” data-slider-step=”5″
data-slider-handle=”custom” data-slider-currency=”%”
value=”5″
max=”<?php echo esc_attr($remaining_percentage); ?>”
required>
<!– <span class=”percentage-symbol”>%</span> –>
</div>
<div class=”amount-preview”>
<?php esc_html_e(‘Amount’, ‘listeo_core’); ?>: $<span id=”amount-preview”>0.00</span>
</div>
</div>
<!– <div class=”form-group”>
<label>Due Date</label>
<input type=”date” id=”milestone-due-date” name=”milestone_due_date” class=”form-control” required>
</div> –>
<button type=”submit” class=”button”><?php esc_html_e(‘Save Milestone’, ‘listeo_core’); ?></button>
</form>
</div>
</div>
<!– Milestones List Template –>
<div class=”milestones-list”>
<?php
$milestones = $freelancer_project->get_milestones($project_id);
$completion_progress = 0;
if (!empty($milestones)) {
foreach ($milestones as $milestone):
$completion_progress += $milestone[‘percentage’];
$can_edit = $freelancer_project->can_edit_milestone($project_id, $milestone[‘id’]);
?>
<div class=”milestone-item” data-id=”<?php echo esc_attr($milestone[‘id’]); ?>”>
<h4><?php echo esc_html($milestone[‘title’]); ?><?php echo $freelancer_project->get_status_badge($milestone[‘status’]); ?></h4>
<span class=”milestone-cost”><i class=”icon-material-outline-local-atm”></i> Cost: <?php echo workscout_output_price($milestone[‘amount’]); ?></span><br>
<span class=”milosteon-completion”><i class=”icon-feather-bar-chart”></i> Completion: <?php echo $milestone[‘percentage’]; ?>% <?php if ($completion_progress != $milestone[‘percentage’]) { ?> (<?php echo $completion_progress; ?>%) <?php } ?></span>
<p><?php echo wp_kses_post($milestone[‘description’]); ?></p>
<div class=”milestone-approvals”>
<?php
$user_type = $freelancer_project->get_user_type($project_id);
$can_approve = !($user_type === ‘client’ ? $milestone[‘client_approval’] : $milestone[‘freelancer_approval’]);
?>
<div class=”approval-status”>
<span class=”client-approval <?php echo $milestone[‘client_approval’] ? ‘approved’ : ”; ?>”>
<?php esc_html_e(‘Client:’, ‘listeo_core’); ?> <?php echo $milestone[‘client_approval’] ? ‘✓ Approved’ : ‘Pending’; ?>
</span>
<span class=”freelancer-approval <?php echo $milestone[‘freelancer_approval’] ? ‘approved’ : ”; ?>”>
<?php esc_html_e(‘Freelancer:’, ‘listeo_core’); ?> <?php echo $milestone[‘freelancer_approval’] ? ‘✓ Approved’ : ‘Pending’; ?>
</span>
</div>
<?php
$wait_for_freelancer = false;
if (!$milestone[‘freelancer_approval’] && $user_type === ‘client’) {
$wait_for_freelancer = true;
}
if ($milestone[‘status’] === ‘pending’ && $can_approve): ?>
<div class=”milestone-actions”>
<button <?php if ($wait_for_freelancer) {
echo ‘disabled’;
} ?> class=”approve-milestone button” data-id=”<?php echo esc_attr($milestone[‘id’]); ?>”>
<i class=”icon-feather-check”></i>
<?php esc_html_e(‘Approve Milestone’, ‘listeo_core’); ?>
</button>
</div>
<?php endif; ?>
<?php if ($milestone[‘status’] === ‘approved’): ?>
<div class=”milestone-payment”>
<?php echo $freelancer_project->get_milestone_payment_link($milestone); ?>
</div>
<?php endif; ?>
</div>
<?php if ($can_edit): ?>
<div class=”milestone-actions”>
<a href=”#” class=” edit-milestone”
data-milestone-id=”<?php echo esc_attr($milestone[‘id’]); ?>”
data-project-id=”<?php echo esc_attr($project_id); ?>”>
<i class=”icon-feather-edit”></i> <?php esc_html_e(‘Edit’, ‘workscout-freelancer’); ?>
</a>
<a href=”#” class=” delete-milestone”
data-milestone-id=”<?php echo esc_attr($milestone[‘id’]); ?>”
data-project-id=”<?php echo esc_attr($project_id); ?>”>
<i class=”icon-feather-trash-2″></i> <?php esc_html_e(‘Delete’, ‘workscout-freelancer’); ?>
</a>
</div>
<?php endif; ?>
</div>
<?php endforeach;
} else { ?>
<p><?php esc_html_e(‘No milestones defined yet.’, ‘listeo_core’); ?></p>
<?php } ?>
</div>
<?php if ($is_freelancer) : ?>
<div class=”milestones-action”>
<a href=”#small-dialog” class=”contact-popup popup-with-zoom-anim ripple-effect ico” title=”<?php esc_html_e(‘Add Milestone’, ‘workscout-freelancer’); ?>” data-tippy-placement=”top”><i class=”icon-feather-plus-circle”></i> <?php esc_html_e(‘Submit Milestone’, ‘listeo_core’); ?></a>
</div>
<!– Add this modal template to your project template file –>
<div id=”edit-milestone-popup” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”sign-in-form”>
<ul class=”popup-tabs-nav”>
<li><a href=”#tab”><?php esc_html_e(‘Edit Milestone’, ‘workscout-freelancer’); ?></a></li>
</ul>
<div class=”popup-tabs-container”>
<div class=”popup-tab-content” id=”tab”>
<form id=”edit-milestone-form” method=”post”>
<input type=”hidden” name=”project_id” id=”edit-project-id” value=””>
<input type=”hidden” name=”milestone_id” id=”edit-milestone-id” value=””>
<?php
$project_value = get_post_meta($project_id, ‘project_value’, true);
$remaining_percentage = 100 – $freelancer_project->get_total_milestone_percentage($project_id);
?>
<?php wp_nonce_field(‘workscout_milestone_nonce’, ‘milestone_nonce’); ?>
<input type=”hidden” name=”project_id” value=”<?php echo $project_id; ?>”>
<div class=”form-group”>
<label>Title</label>
<input type=”text” id=”edit-milestone-title” name=”milestone_title” class=”form-control” required>
</div>
<div class=”form-group”>
<label><?php esc_html_e(‘Description’, ‘listeo_core’); ?></label>
<textarea id=”edit-milestone-description” name=”milestone_description” class=”form-control” required></textarea>
</div>
<div class=”form-group”>
<label><?php esc_html_e(‘Percentage of Project Value’, ‘listeo_core’); ?></label>
<div class=”percentage-input-wrapper”>
<input type=”number”
id=”edit-milestone-percentage”
name=”percentage”
class=”form-control”
step=”5″
min=”5″
data-slider-min=”5″ data-slider-max=”<?php echo esc_attr($remaining_percentage); ?>” data-slider-step=”5″
data-slider-handle=”custom” data-slider-currency=”%”
max=”<?php echo esc_attr($remaining_percentage); ?>”
required>
<span class=”percentage-symbol”>%</span>
</div>
<div class=”amount-preview”>
<?php esc_html_e(‘Amount’, ‘listeo_core’); ?>: $<span id=”edit-amount-preview”>0.00</span>
</div>
</div>
<button class=”button full-width margin-top-10″ type=”submit”>
<?php esc_html_e(‘Save Changes’, ‘workscout-freelancer’); ?>
</button>
</form>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php $attachments = get_post_meta($task_id, ‘_task_file’, true);
if ($attachments) { ?>
<div class=”dashboard-box dashboard-task-files-box margin-top-20″>
<div class=”headline”>
<h3><i class=”icon-material-outline-attach-file”></i><?php esc_html_e(‘ Task Files’, ‘listeo_core’); ?></h3>
</div>
<div class=”content project-task-files”>
<?php
//$attachments = get_posts(‘post_parent=’ . $post->ID . ‘&post_type=attachment&fields=ids&post_mime_type=image&numberposts=-1’);
foreach ((array) $attachments as $attachment_id => $attachment_url) {
//get the attachment url
if (!$attachment_url) {
$attachment_url = wp_get_attachment_url($attachment_id);
}
if (!$attachment_url) {
//skip if no url
continue;
}
//get the attachment filename
$attachment_title = get_the_title($attachment_id);
if (!$attachment_title) {
}
$attachment_title = basename($attachment_url);
//$attachment_title = get_the_title($id);
//get the attachment file type
$attachment_filetype = wp_check_filetype($attachment_url);
?>
<a href=”<?php echo $attachment_url; ?>” class=”attachment-box ripple-effect”><span><?php echo $attachment_title; ?></span><i><?php echo $attachment_filetype[‘ext’]; ?></i></a>
<?php } ?>
</div>
</div>
<?php }
// get attachments from all the comments and display them
$project_files = $freelancer_project->get_project_files($project_id);
if (!empty($project_files)) { ?>
<div class=”dashboard-box dashboard-project-files-box margin-top-20″>
<div class=”headline”>
<h3><i class=”icon-material-outline-business-center”></i><?php esc_html_e(‘ Project Files’, ‘listeo_core’); ?></h3>
</div>
<div class=”content project-files”>
<?php foreach ($project_files as $file) { ?>
<a href=” <?php echo esc_url($file[‘url’]); ?>” target=”_blank” class=”attachment-box ripple-effect”>
<span><?php echo esc_html($file[‘name’]); ?></span><i> <?php echo esc_html($file[‘type’]) . ‘ | ‘ .
esc_html($file[‘size’]) . ‘ | ‘ .
‘Uploaded by ‘ . esc_html($file[‘comment_author’]) . ‘ on ‘ .
date(‘M j, Y’, strtotime($file[‘comment_date’]));
?></i>
</a>
</div>
<?php } ?>
</div>
</div>
<?php } ?>
</div>
</div>
Sidebar-tasks.php
<form action=”” id=”workscout-frelancer-search-form-tasks” class=”ajax-search”>
<!– Location –>
<div class=”sidebar-widget”>
<div class=”search_location widget task-widget-location widget_range_filter”>
<h4><?php esc_html_e(‘Location’, ‘workscout-freelancer’); ?></h4>
<?php
if (!empty($_GET[‘search_location’])) {
$location = sanitize_text_field($_GET[‘search_location’]);
} else {
$location = ”;
} ?>
<div class=”sidebar-search_location-container”>
<input type=”text” name=”search_location” id=”search_location” placeholder=”<?php esc_attr_e(‘Location’, ‘workscout-freelancer’); ?>” value=”<?php echo esc_attr($location); ?>” />
<a href=”#”><i title=”<?php esc_html_e(‘Find My Location’, ‘workscout-freelancer’) ?>” class=”tooltip left la la-map-marked-alt”></i></a>
<?php if (get_option(‘workscout_map_address_provider’, ‘osm’) == ‘osm’) : ?><span class=”type-and-hit-enter”><?php esc_html_e(‘type and hit enter’, ‘workscout-freelancer’) ?></span> <?php endif; ?>
</div>
<?php
$geocode = get_option(‘workscout_maps_api_server’, 0);
$default_radius = get_option(‘workscout_maps_default_radius’);
if ($geocode) : ?>
<h4 class=”checkboxes” style=”margin-bottom: 0;”>
<input type=”checkbox” name=”filter_by_radius_check” id=”radius_check” class=”filter_by_radius” <?php if (get_option(‘workscout_radius_state’) == ‘enabled’) echo “checked”; ?>>
<label for=”radius_check”><?php esc_html_e(‘Search by Radius’, ‘workscout-freelancer’); ?></label>
</h4>
<div class=”widget_range_filter-inside”>
<span class=”range-slider-subtitle”><?php esc_html_e(‘Radius around selected destination’, ‘workscout-freelancer’) ?></span>
<input name=”search_radius” id=”search_radius” data-slider-currency=”<?php echo get_option(‘workscout_radius_unit’); ?>” data-slider-min=”0″ data-slider-max=”100″ data-slider-step=”1″ data-slider-value=”<?php echo get_option(‘workscout_maps_default_radius’); ?>”>
<div class=” margin-bottom-50″></div>
</div>
<div class=”clearfix”></div>
<?php endif; ?>
</div>
</div>
<div class=”sidebar-widget widget”>
<?php
if (!empty($_GET[‘search_keywords’])) {
$keywords = sanitize_text_field($_GET[‘search_keywords’]);
} else {
$keywords = ”;
}
?>
<div class=”search_keywords”>
<h4><?php esc_html_e(‘Keywords’, ‘workscout-freelancer’) ?></h4>
<input type=”text” name=”search_keywords” id=”search_keywords” placeholder=”<?php esc_attr_e(‘job title, keywords or company’, ‘workscout-freelancer’); ?>” value=”<?php echo esc_attr($keywords); ?>” />
<div class=”clearfix”></div>
</div>
</div>
<!– Category –>
<div class=”widget sidebar-widget”>
<h4><?php esc_html_e(‘Category’, ‘workscout-freelancer’) ?></h4>
<?php
if (!empty($_GET[‘tax-task_category’])) {
$selected_category = sanitize_text_field($_GET[‘tax-task_category’]);
} else {
$selected_category = “”;
}
$dropdown = job_manager_dropdown_categories(
array(
‘taxonomy’ => ‘task_category’,
‘hierarchical’ => 1,
‘depth’ => -1,
‘class’ => ‘select2-multiple job-manager-category-dropdown ‘ . (is_rtl() ? ‘chosen-rtl’ : ”),
‘name’ => ‘tax-task_category’,
‘orderby’ => ‘name’,
‘selected’ => $selected_category,
‘placeholder’ => __(‘Choose a category’, ‘workscout-freelancer’),
‘hide_empty’ => false,
‘echo’ => false
)
);
$fixed_dropdown = str_replace(‘ ’, ‘- ‘, $dropdown);
echo $fixed_dropdown; ?>
</div>
<!– Budget –>
<div class=”widget sidebar-widget”>
<div class=”widget widget_range_filter widget-fixed_rate-filter”>
<h4 class=”checkboxes” style=”margin-bottom: 0;”>
<input type=”checkbox” name=”filter_by_fixed_check” id=”fixed_rate” class=”filter_by_check”>
<label for=”fixed_rate”><?php esc_html_e(‘Fixed Price’, ‘workscout-freelancer’); ?></label>
</h4>
<div class=”widget_range_filter-inside”>
<input class=”range-slider” name=”filter_by_fixed” type=”text” value=”” data-slider-currency=”<?php echo get_workscout_currency_symbol(); ?>” data-slider-min=”10″ data-slider-max=”2500″ data-slider-step=”25″ data-slider-value=”[10,2500]” />
</div>
</div>
</div>
<!– Hourly Rate –>
<div class=”widget sidebar-widget”>
<div class=”widget widget_range_filter widget-hourly_rate-filter”>
<h4 class=”checkboxes” style=”margin-bottom: 0;”>
<input type=”checkbox” name=”filter_by_hourly_rate_check” id=”hourly_rate” class=”filter_by_check”>
<label for=”hourly_rate”><?php esc_html_e(‘Hourly Rate’, ‘workscout-freelancer’); ?></label>
</h4>
<div class=”widget_range_filter-inside”>
<input class=”range-slider” name=”filter_by_hourly_rate” type=”text” value=”” data-slider-currency=”<?php echo get_workscout_currency_symbol(); ?>” data-slider-min=”10″ data-slider-max=”150″ data-slider-step=”5″ data-slider-value=”[10,200]” />
</div>
</div>
<!– Range Slider –>
</div>
<!– Tags –>
<div class=”widget sidebar-widget”>
<h4><?php esc_html_e(‘Skills’, ‘workscout-freelancer’) ?></h4>
<div class=”tags-container”>
<?php
$tasks = workscout_get_options_array(‘taxonomy’, ‘task_skill’);
$selected = array();
// if(is_tax(‘task_skill’)){
// $selected[get_query_var(‘task_skill’)] = ‘on’;
// }
foreach ($tasks as $key => $value) {
?>
<div class=”tag”>
<input <?php if (array_key_exists($value[‘slug’], $selected)) {
echo ‘checked=”checked”‘;
} ?> id=”tax-<?php echo esc_html($value[‘slug’]) ?>-task_skill” value=”<?php echo esc_html($value[‘id’]) ?>” type=”checkbox” name=”tax-task_skill<?php echo ‘[‘ . esc_html($value[‘slug’]) . ‘]’; ?>”>
<label for=”tax-<?php echo esc_html($value[‘slug’]) ?>-task_skill”><?php echo esc_html($value[‘name’]) ?></label>
</div>
<?php }
?>
</div>
<div class=”clearfix”></div>
</div>
<!– Keywords –>
</form>
Single-task.php
<?php
if (!defined(‘ABSPATH’)) {
exit;
}
$template_loader = new WorkScout_Freelancer_Template_Loader;
get_header(get_option(‘header_bar_style’, ‘standard’));
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
$currency_symbol = get_workscout_currency_symbol();
$task_type = get_post_meta($post->ID, ‘_task_type’, true);
// get current post status
$task_status = get_post_status($post->ID);
//if task status is expired, then show the message
$selected_bid = get_post_meta($post->ID, ‘_selected_bid_id’, true);
if (have_posts()) :
while (have_posts()) : the_post();
$show_bid_form = false;
$budget_min = get_post_meta($post->ID, ‘_budget_min’, true);
$budget_max = get_post_meta($post->ID, ‘_budget_max’, true);
$hourly_min = get_post_meta($post->ID, ‘_hourly_min’, true);
$hourly_max = get_post_meta($post->ID, ‘_hourly_max’, true);
if ($task_type == ‘hourly’) {
$range_min = $hourly_min;
$range_max = $hourly_max;
} else {
$range_min = $budget_min;
$range_max = $budget_max;
}
if (empty($range_min) && $range_min !== “” && !empty($range_max)) {
$range_min = $range_max – ($range_max * 0.3);
}
if (empty($range_max) && $range_max !== “” && !empty($range_min)) {
// why is this empty?
$range_max = $range_min – ($range_max * 0.3);
}
if (!empty($range_min) && is_numeric($range_min) && !empty($range_max) && is_numeric($range_max)) {
$show_bid_form = true;
}
if ($show_bid_form) {
$range = $range_max – $range_min;
if ($range <= 1000) {
$step = 1; // Set a small step for a narrow range
} else if ($range <= 10000) {
$step = 100; // Set a medium step for a moderate range
} else {
$step = 500; // Set a larger step for a wide range
}
}
if ($selected_bid) {
$show_bid_form = false;
}
$company = get_post_meta($post->ID, ‘_company_id’, true);
// check if company post exists
if ($company) {
$company_post = get_post($company);
if (!$company_post) {
$company = false;
}
}
$header_bg_image = get_post_meta($post->ID, ‘_header_bg_image’, true);
?>
<!– Titlebar
================================================== –>
<div class=”single-page-header” <?php if ($header_bg_image) : ?>data-background-image=”<?php echo $header_bg_image; ?>” <?php endif; ?>>
<div class=”container”>
<div class=”row”>
<div class=”col-md-12″>
<div class=”single-page-header-inner”>
<div class=”left-side”>
<?php if (!empty($company)) { ?>
<div class=”header-image”><a href=”<?php get_permalink($company); ?>”>
<?php
if ($company) {
the_company_logo(‘medium’, null, $company);
} else {
the_company_logo(‘medium’);
} ?>
</a></div>
<?php } ?>
<div class=”header-details”>
<h3><?php the_title(); ?></h3>
<?php
if (!$company) { ?>
<h5><?php esc_html_e(‘Added by’, ‘workscout-freelancer’); ?></h5>
<ul>
<li><i class=”icon-material-outline-account-circle”></i> <?php esc_html_e(‘Private Person’, ‘workscout-freelancer’); ?></li>
</ul>
<?php } else {
$template_loader->get_template_part(‘single-partials/single-company’, ‘data’);
} ?>
</div>
</div>
<div class=”right-side”>
<?php if ($show_bid_form) { ?>
<div class=”salary-box”>
<div class=”salary-type”>
<?php
if ($task_type == ‘hourly’) {
esc_html_e(‘Hourly Rate’, ‘workscout-freelancer’);
} else {
esc_html_e(‘Budget’, ‘workscout-freelancer’);
} ?>
</div>
<div class=”salary-amount”>
<?php
if ($task_type == ‘hourly’) {
if ($hourly_min) {
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_min));
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
}
if ($hourly_max && $hourly_max > $hourly_min) {
if ($hourly_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
echo esc_html(workscoutThousandsCurrencyFormat($hourly_max));
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
}
} else {
if ($budget_min) {
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_min));
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
}
if ($budget_max && $budget_max > $budget_min) {
if ($budget_min) {
echo ‘ – ‘;
}
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
echo esc_html(workscoutThousandsCurrencyFormat($budget_max));
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
}
}
?>
</div>
</div>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
</div>
<!– Page Content
================================================== –>
<div class=”container”>
<div class=”row”>
<!– Content –>
<div class=”col-xl-8 col-lg-8 content-right-offset”>
<div class=”single-page-section”>
<h3 class=”margin-bottom-25″><?php esc_html_e(‘Project Description’, ‘workscout-freelancer’); ?></h3>
<?php the_content(); ?>
</div>
<?php $template_loader->get_template_part(‘single-partials/single-task’, ‘attachments’); ?>
<?php $template_loader->get_template_part(‘single-partials/single-task’, ‘skills’); ?>
<?php
// get option task_hide_bidders and if it is not set to hide, show the bidders
if (get_option(‘task_hide_bidders’) != ‘1’)
$template_loader->get_template_part(‘single-partials/single-task’, ‘bids’);
?>
</div>
<!– Sidebar –>
<div class=”col-xl-4 col-lg-4″>
<div class=”sidebar-container”>
<?php
if ($task_status == ‘expired’) { ?>
<div class=”countdown yellow margin-bottom-35″ role=”alert”><?php esc_html_e(‘This task has expired.’, ‘workscout-freelancer’); ?></div>
<?php } else {
$deadline = workscout_get_bidding_deadline($post->ID);
if ($selected_bid) {
$deadline = ‘closed’;
}
if ($deadline) {
if (is_array($deadline)) : ?>
<div class=”countdown green margin-bottom-35″>
<?php esc_html_e(‘ Bidding ends in ‘, ‘workscout-freelancer’); ?><?php echo $deadline[‘days’];
echo $deadline[‘hours’] ?> </div>
<?php else :
$show_bid_form = false; ?>
<div class=”countdown green margin-bottom-35″><?php esc_html_e(‘Bidding has closed’, ‘workscout-freelancer’); ?></div>
<?php endif;
} ?>
<div class=”sidebar-widget widget”>
<?php if ($show_bid_form) : ?>
<div class=”bidding-widget”>
<div class=”bidding-headline”>
<h3><?php esc_html_e(‘Bid on this job!’, ‘workscout-freelancer’); ?></h3>
</div>
<div class=”bidding-inner”>
<!– Headline –>
<?php if ($task_type == ‘hourly’) { ?>
<span class=”bidding-detail”><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘hourly rate’, ‘workscout-freelancer’); ?></strong></span>
<?php } else { ?>
<span class=”bidding-detail”><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘bid amount’, ‘workscout-freelancer’); ?></strong></span>
<?php } ?>
<!– Price Slider –>
<div class=”bidding-value”>
<?php
if ($currency_position == ‘before’) {
echo $currency_symbol;
}
?><span class=”biddingVal”></span>
<?php
if ($currency_position == ‘after’) {
echo $currency_symbol;
}
?></div>
<input name=”budget” class=”bidding-slider bidding-slider-widget” type=”text” value=”” data-slider-handle=”custom” data-slider-currency=”<?php echo $currency_symbol; ?>” data-slider-min=”<?php echo $range_min; ?>” data-slider-max=”<?php echo $range_max; ?>” data-slider-value=”auto” data-slider-step=”<?php echo $step; ?>” data-slider-tooltip=”hide” />
<!– Headline –>
<?php if ($task_type == ‘hourly’) { ?>
<span class=”bidding-detail margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in hours’, ‘workscout-freelancer’); ?></span>
<?php } else { ?>
<span class=”bidding-detail margin-top-30″><?php esc_html_e(‘Set your’, ‘workscout-freelancer’); ?> <strong><?php esc_html_e(‘delivery time’, ‘workscout-freelancer’); ?></strong> <?php esc_html_e(‘in days’, ‘workscout-freelancer’); ?></span>
<?php } ?>
<!– Fields –>
<div class=”bidding-fields”>
<div class=”bidding-field”>
<!– Quantity Buttons –>
<div class=”qtyButtons”>
<div class=”qtyDec”></div>
<input type=”text” class=”bidding-time bidding-time-widget” id=”qtyInput” name=”time” value=”1″>
<div class=”qtyInc”></div>
</div>
</div>
</div>
<?php if (workscout_freelancer_user_can_bid($post->ID)) { ?>
<!– Button –>
<button id=”snackbar-place-bid” class=”button bid-now-btn ripple-effect move-on-hover full-width margin-top-30″><span><?php esc_html_e(‘Place a Bid’, ‘workscout-freelancer’); ?></span></button>
<a style=”display: none;” href=”#small-dialog” class=”popup-with-zoom-anim button trigger-bid-popup ripple-effect ico button ripple-effect move-on-hover full-width margin-top-30″><span><?php esc_html_e(‘Place a Bid’, ‘workscout-freelancer’); ?></span></a>
<?php } else {
if (is_user_logged_in()) { ?>
<div class=”bidding-detail margin-top-20″><?php esc_html_e(‘You have already bid on this project.’, ‘workscout-freelancer’); ?> <br> <?php esc_html_e(‘You can edit your bids’, ‘workscout-freelancer’); ?> <a href=”<?php echo get_permalink(get_option(‘workscout_freelancer_manage_my_bids_page_id’)) ?>”><?php esc_html_e(‘here’, ‘workscout-freelancer’); ?></a>.</div>
<?php } else { ?>
<a href=”#login-dialog” class=”small-dialog popup-with-zoom-anim login-btn button margin-top-30″><?php esc_html_e(‘Login to Bid’, ‘workscout-freelancer’); ?></a>
<?php } ?>
<?php } ?>
</div>
<div class=”bidding-inner-success bidding-inner” style=”display:none;”>
<i class=”fa fa-check-circle”></i>
<br>
<h3><?php esc_html_e(‘Thanks for the bid!’, ‘workscout-freelancer’); ?></h3>
</div>
<?php if (!is_user_logged_in()) : ?>
<div class=”bidding-signup”><?php esc_html_e(‘Don\’t have an account? ‘, ‘workscout-freelancer’); ?><a href=”#signup-dialog” class=”register-tab sign-in popup-with-zoom-anim”><?php esc_html_e(‘Sign Up’, ‘workscout-freelancer’); ?></a></div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php } ?>
<?php get_sidebar(‘task’); ?>
</div>
</div>
</div>
</div>
<?php endwhile; ?>
<?php else : ?>
<?php get_template_part(‘content’, ‘none’); ?>
<?php endif; ?>
<?php if ($show_bid_form) : ?>
<!– Reply to review popup –>
<div id=”small-dialog” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Place Bid’, ‘workscout-freelancer’); ?></h3>
</div>
<!– Bidding –>
<div class=”bidding-widget”>
<!– Headline –>
<form autocomplete=”off” id=”form-bidding” data-post_id=”<?php echo $post->ID; ?>” class=”form-bidding-<?php echo $post->ID; ?>” method=”post”>
<!– Headline –>
<?php if ($task_type == ‘hourly’) { ?>
<span class=”bidding-detail”><?php echo sprintf(__(‘Set your %s hourly rate %s’, ‘workscout-freelancer’), ‘<strong>’, ‘</strong>’); ?></span>
<?php } else { ?>
<span class=”bidding-detail”><?php echo sprintf(__(‘Set your %s bid amount %s’, ‘workscout-freelancer’), ‘<strong>’, ‘</strong>’); ?></span>
<?php } ?>
<!– Price Slider –>
<div class=”bidding-value”><?php echo $currency_symbol; ?><span class=”biddingVal”></span></div>
<input name=”budget” class=”bidding-slider bidding-slider-popup” type=”text” value=”” data-slider-handle=”custom” data-slider-currency=”<?php echo $currency_symbol; ?>” data-slider-min=”<?php echo $range_min; ?>” data-slider-max=”<?php echo $range_max; ?>” data-slider-value=”auto” data-slider-step=”<?php echo $step; ?>” data-slider-tooltip=”hide” />
<!– Headline –>
<?php if ($task_type == ‘hourly’) { ?>
<span class=”bidding-detail margin-top-30″><?php echo sprintf(__(‘Set your %s delivery time %s in hours’, ‘workscout-freelancer’), ‘<strong>’, ‘</strong>’); ?></span>
<?php } else { ?>
<span class=”bidding-detail margin-top-30″><?php echo sprintf(__(‘Set your %s delivery time %s in days’, ‘workscout-freelancer’), ‘<strong>’, ‘</strong>’); ?></span>
<?php } ?>
<!– Fields –>
<div class=”bidding-fields”>
<div class=”bidding-field”>
<!– Quantity Buttons –>
<div class=”qtyButtons”>
<div class=”qtyDec”></div>
<input type=”text” class=”bidding-time bidding-time-popup” id=”qtyInput” name=”bid-time” value=”1″>
<div class=”qtyInc”></div>
</div>
</div>
</div>
<div>
<div class=”bidding-field”>
<span class=”bidding-detail margin-top-30″><?php esc_html_e(‘Describe your proposal’, ‘workscout-freelancer’); ?></span>
<textarea name=”bid-proposal” id=”bid-proposal” cols=”30″ rows=”5″ placeholder=”<?php esc_html_e(‘What makes you the best candidate for that project?’, ‘workscout-freelancer’); ?>”></textarea>
</div>
</div>
<!– Button –>
<button id=”snackbar-place-bid” form=”form-bidding” class=”button ripple-effect move-on-hover full-width margin-top-30″><span><?php esc_html_e(‘Place a Bid’, ‘workscout-freelancer’); ?></span></button>
</form>
</div>
</div>
<?php endif; ?>
<?php
get_footer(); ?>
task-bids.php
<?php
/**
* Lists the job applications for a particular job listing.
*
* This template can be overridden by copying it to yourtheme/wp-job-manager-applications/job-applications.php.
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Automattic
* @package WP Job Manager – Applications
* @category Template
* @version 1.7.1
*/
if (!defined(‘ABSPATH’)) {
exit;
}
if (!isset($_REQUEST[‘task_id’])) {
return;
}
if (isset($_REQUEST[‘task_id’])) {
$task_id = absint($_REQUEST[‘task_id’]);
$task = get_post($task_id);
}
$currency_position = get_option(‘workscout_currency_position’, ‘before’);
?>
<!– Row –>
<div class=”row”>
<!– Dashboard Box –>
<div class=”col-xl-12″>
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<!– Headline –>
<div class=”headline”>
<h3><i class=”icon-material-outline-supervisor-account”></i> <?php $count = count($bids);
printf(_n(‘%s Bidder’, ‘%s Bidders’, $count, ‘workscout-freelancer’), number_format_i18n($count)); ?> </h3>
<div class=”sort-by”>
<select class=”select2-single hide-tick”>
<option><?php esc_html_e(‘Highest First’, ‘workscout-freelancer’); ?></option>
<option><?php esc_html_e(‘Lowest First’, ‘workscout-freelancer’); ?></option>
<option><?php esc_html_e(‘Fastest First’, ‘workscout-freelancer’); ?></option>
</select>
</div>
</div>
<div class=”content”>
<ul class=”dashboard-box-list”>
<?php foreach ($bids as $bid) :
//get post author avatar
$post = get_post($bid->ID);
$author_id = $bid->post_author;
//check if user has active freelance profile
$user_profile_id = get_user_meta($author_id, ‘freelancer_profile’, true);
// get wordpress avatar
?>
<li>
<!– Job Listing –>
<div class=”item-listing”>
<?php
$user_info = get_userdata($author_id);
if ($user_profile_id) {
$avatar = “<img src=” . get_the_candidate_photo($user_profile_id) . ” class=’avatar avatar-32 photo’/>”;
$username = get_the_title($user_profile_id);
} else {
$avatar = get_avatar($bid->post_author, 32);
$username = workscout_get_users_name($author_id);
}
?>
<!– Job Listing Details –>
<div class=”item-listing-details”>
<a href=”#” class=”item-listing-company-logo”>
<?php if (workscout_is_user_verified($bid->post_author)) { ?> <div class=”verified-badge”></div><?php } ?>
<?php echo $avatar; ?>
</a>
<!– Details –>
<div class=”item-listing-description”>
<h3 class=”item-listing-title”>
<a href=”#”><?php
//get user display name
echo $username;
?></a>
</h3>
<?php
if ($user_profile_id) { ?>
<?php $rating_value = get_post_meta($user_profile_id, ‘workscout-avg-rating’, true);
if ($rating_value) { ?>
<div class=”freelancer-rating”>
<div class=”star-rating” data-rating=”<?php echo esc_attr(number_format(round($rating_value, 2), 1)); ?>”></div>
</div>
<?php } ?>
<?php } ?>
<div class=”freelancer-proposal”>
<?php echo get_the_excerpt($bid) ?>
</div>
<!– Job Listing Footer –>
<div class=”item-listing-footer”>
<ul>
<li><a href=”mailto:<?php echo $user_info->user_email; ?>”><i class=”icon-feather-mail”></i>
<?php echo $user_info->user_email; ?>
</a></li>
<?php if ($user_info->phone) { ?>
<li><i class=”icon-feather-phone”></i> <?php echo $user_info->phone; ?></li>
<?php } ?>
<?php
$country = get_post_meta($user_profile_id, ‘_country’, true);
if ($country) {
$countries = workscoutGetCountries();
?>
<li class=”dashboard-resume-flag”><img class=”flag” src=”<?php echo WORKSCOUT_FREELANCER_PLUGIN_URL; ?>/assets/images/flags/<?php echo strtolower($country); ?>.svg” alt=””> <?php echo $countries[$country]; ?></li>
<?php } ?>
</ul>
</div>
</div>
<ul class=”dashboard-task-info bid-info”>
<li><strong>
<?php
if (
$currency_position == ‘before’
) {
echo get_workscout_currency_symbol();
}
echo get_post_meta($bid->ID, ‘_budget’, true);
if (
$currency_position == ‘after’
) {
echo get_workscout_currency_symbol();
} ?>
</strong>
<span><?php echo get_workscout_task_type($task); ?></span>
</li>
<li><strong><?php echo get_post_meta($bid->ID, ‘_time’, true); ?> <?php esc_html_e(‘days’, ‘workscout-freelancer’); ?></strong><span><?php esc_html_e(‘Delivery Time’, ‘workscout-freelancer’); ?></span></li>
</ul>
<div data-bid-id=”<?php echo esc_attr($bid->ID) ?>” class=”buttons-to-right always-visible margin-top-25 margin-bottom-0″>
<a href=”#” class=”bids-action-accept-offer button ripple-effect”><i class=”icon-material-outline-check”></i> <?php esc_html_e(‘Accept Offer’, ‘workscout-freelancer’); ?></a>
<a href=”#” data-recipient=”<?php echo esc_attr($author_id); ?>” data-bid_id=”bid_<?php echo esc_attr($bid->ID); ?>” class=”bids-action-send-msg button dark ripple-effect”><i class=”icon-feather-mail”></i> Send Message</a>
<?php
// $actions[‘remove_bid’] = array(
// ‘label’ => esc_html__(‘Delete’, ‘workscout’),
// ‘nonce’ => true,
// ‘class’ => ‘task-dashboard-action-delete’
// );
// $actions = apply_filters(‘workscout_freelancer_my_task_bids_actions’, $actions, $task);
// foreach ($actions as $action => $value) {
// $action_url = add_query_arg(array(‘action’ => $action, ‘bid_id’ => $bid->ID));
// $class = isset($value[‘class’]) ? $value[‘class’] : ”;
// if ($value[‘nonce’])
// $action_url = wp_nonce_url($action_url, ‘workscout_freelancer_my_task_bids_actions’);
// echo ‘<a class=” ‘ . $class . ‘ button gray ripple-effect ico” title=”‘ . $value[‘label’] . ‘” href=”‘ . $action_url . ‘” data-tippy-placement=”top” class=”task-dashboard-action-‘ . $action . ‘”><i class=”icon-feather-trash-2″></i></a>’;
// }
?>
<!– <a href=”#” class=”bids-action-delete-bid button gray ripple-effect ico” title=”Remove Bid” data-tippy-placement=”top”><i class=”icon-feather-trash-2″></i></a> –>
</div>
</div>
</div>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
<!– Row / End –>
<!– Bid Acceptance Popup
================================================== –>
<!– Reply to review popup –>
<div id=”small-dialog-1″ class=”zoom-anim-dialog mfp-hide small-dialog apply-popup bid-accept-popup”>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Accept Offer’, ‘workscout’); ?></h3>
</div>
<!– Welcome Text –>
<div class=”welcome-text”>
<div class=”bid-acceptance margin-top-15″> </div>
<div class=”bid-proposal margin-top-15″>
<div class=”bid-proposal-text”></div> </div>
</div>
<!– Tab –>
<!– Tab –>
<!– Bidding –>
<div class=”bidding-widget”>
<form id=”accept-bid-form”>
<input type=”hidden” id=”task_id” name=”task_id” value=””>
<input type=”hidden” id=”bid_id” name=”bid_id” value=””>
<div class=”radio”>
<input id=”radio-1″ name=”radio” type=”radio” required>
<label for=”radio-1″><span class=”radio-label”></span> <?php esc_html_e(‘I have read and agree to the Terms and Conditions’, ‘workscout-freelancer’); ?></label>
</div>
<button id=”approve-bid” class=”margin-top-15 button full-width button-sliding-icon ripple-effect” type=”submit” form=”accept-bid-form”><?php esc_html_e(‘Accept’, ‘workscout-freelancer’); ?> <i class=”icon-material-outline-arrow-right-alt”></i></button>
</form>
</div>
<!– Button –>
</div>
<a style=”display: none;” href=”#small-dialog-1″ class=”bids-popup-accept-offer popup-with-zoom-anim ripple-effect”><?php esc_html_e(‘Accept Offer’, ‘workscout-freelancer’); ?></a>
<!– Bid Acceptance Popup / End –>
<!– Send Direct Message Popup
================================================== –>
<!– Reply to review popup –>
<div id=”small-dialog-2″ class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Send Message’, ‘workscout-freelancer’); ?></h3>
</div>
<div class=”message-reply margin-top-0″>
<!– Form –>
<form action=”” id=”send-message-from-task” data-task_id=””>
<textarea data-recipient=”” data-referral=”” id=”contact-message” name=”textarea” cols=”10″ placeholder=”Message” class=”with-border” required></textarea>
<!– Button –>
<button class=”button full-width button-sliding-icon ripple-effect” type=”submit” form=”send-message-from-task”><?php esc_html_e(‘Send’, ‘workscout-freelancer’); ?> <i class=”icon-material-outline-arrow-right-alt”></i></button>
<div class=”notification closeable success margin-top-20″></div>
</form>
</div>
</div>
<a style=”display: none;” href=”#small-dialog-2″ class=”bids-popup-msg popup-with-zoom-anim button dark ripple-effect”><i class=”icon-feather-mail”></i> <?php esc_html_e(‘Send Message’, ‘workscout-freelancer’); ?></a>
<!– Send Direct Message Popup / End –>
Task-dashboard.php
<?php
$submission_limit = get_option(‘workscout_freelancer_submission_limit’);
$submit_task_form_page_id = get_option(‘workscout_freelancer_submit_task_form_page_id’);
global $post;
?>
<!– Row –>
<div class=”row”>
<!– Dashboard Box –>
<div class=”col-xl-12″>
<div class=”dashboard-box dashboard-tasks-box margin-top-0″>
<!– Headline –>
<div class=”headline”>
<h3><i class=”icon-material-outline-assignment”></i><?php esc_html_e(‘ My Tasks’, ‘workscout-freelancer’); ?></h3>
<div class=”sort-by”>
<form id=”tasks-sort-by-form” action=” <?php the_permalink(); ?>” method=”get”>
<?php
$selected = isset($_REQUEST[‘sort-by’]) ? $_REQUEST[‘sort-by’] : ”;
?>
<select name=”sort-by” class=”select2-single hide-tick tasks-sort-by”>
<option <?php selected($selected, ”) ?> value=””><?php esc_html_e(‘All’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘publish’) ?>value=”publish”><?php esc_html_e(‘Published’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘in_progress’) ?>value=”in_progress”><?php esc_html_e(‘In progress’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘completed’) ?>value=”completed”><?php esc_html_e(‘Completed’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘hidden’) ?>value=”hidden”><?php esc_html_e(‘Hidden’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘pending’) ?>value=”pending”><?php esc_html_e(‘Pending’, ‘workscout-freelancer’); ?></option>
<option <?php selected($selected, ‘closed’) ?>value=”closed”><?php esc_html_e(‘Closed’, ‘workscout-freelancer’); ?></option>
</select>
</form>
</div>
</div>
<div class=”content”>
<ul class=”dashboard-box-list”>
<?php if (!$tasks) : ?>
<li><?php esc_html_e(‘You do not have any active task listings.’, ‘workscout-freelancer’); ?></li>
<?php else : ?>
<?php foreach ($tasks as $task) :
$status = get_post_status($task);
?>
<li>
<!– Job Listing –>
<div class=”item-listing width-adjustment”>
<!– Job Listing Details –>
<div class=”item-listing-details”>
<!– Details –>
<div class=”item-listing-description”>
<h3 class=”item-listing-title”> <a href=”<?php echo get_permalink($task->ID); ?>”><?php echo esc_html($task->post_title); ?></a> <span class=”dashboard-status-button <?php switch (get_the_job_status_class($task)) {
case ‘expired’:
echo ‘red’;
break;
case ‘completed’:
case ‘in_progress’:
echo ‘green’;
break;
case ‘publish’:
echo ‘green’;
break;
default:
echo ‘yellow’;
break;
}; ?>”><?php the_task_status($task); ?></span></h3>
<!– Job Listing Footer –>
<div class=”item-listing-footer”>
<ul>
<?php
$deadline = workscout_get_bidding_deadline($task->ID);
if ($deadline) {
if (is_array($deadline)) :
?>
<li><i class=”icon-material-outline-access-time”></i>
<?php echo $deadline[‘days’];
echo $deadline[‘hours’] ?> <?php esc_html_e(‘left’, ‘workscout-freelancer’); ?> </li>
<?php else : ?>
<li><i class=”icon-material-outline-access-time”></i><?php esc_html_e(‘Bidding has closed’, ‘workscout-freelancer’); ?></li>
<?php endif;
} ?>
</ul>
</div>
</div>
</div>
</div>
<!– Task Details –>
<?php
$count = get_task_bidders_count($task->ID);
$task_range = get_workscout_task_range($task);
if (!empty($count) || !empty($task_range)) {
?>
<ul class=”dashboard-task-info”>
<?php
if ($count) { ?>
<li><strong><?php echo get_task_bidders_count($task->ID) ?></strong><span><?php esc_html_e(‘Bids’, ‘workscout-freelancer’); ?></span></li>
<li><strong><?php echo get_workscout_task_bidders_average($task->ID); ?></strong><span><?php esc_html_e(‘Avg. Bid’, ‘workscout-freelancer’); ?></span></li>
<?php } ?>
<?php
if (!empty($task_range)) { ?>
<li><strong><?php echo get_workscout_task_range($task); ?></strong><span><?php echo get_workscout_task_type($task); ?></span></li>
<?php } ?>
</ul>
<?php } ?>
<!– Buttons –>
<div class=”buttons-to-right always-visible”>
<?php
$actions = array();
switch ($task->post_status) {
case ‘publish’:
$actions[‘edit’] = array(
‘label’ => esc_html__(‘Edit’, ‘workscout-freelancer’),
‘nonce’ => false
);
$actions[‘hide’] = array(
‘label’ => esc_html__(‘Hide’, ‘workscout-freelancer’),
‘nonce’ => true
);
break;
case ‘in_progress’:
$actions[‘completed’] = array(
‘label’ => esc_html__(‘Set Task as Completed’, ‘workscout-freelancer’),
‘nonce’ => true,
‘class’ => ‘task-dashboard-action-delete’
);
break;
case ‘hidden’:
$actions[‘edit’] = array(
‘label’ => esc_html__(‘Edit’, ‘workscout-freelancer’),
‘nonce’ => false
);
$actions[‘publish’] = array(
‘label’ => esc_html__(‘Publish’, ‘workscout-freelancer’),
‘nonce’ => true
);
break;
case ‘pending_payment’:
case ‘pending’:
$actions[‘edit’] = array(
‘label’ => __(‘Edit’, ‘workscout-freelancer’),
‘nonce’ => false,
);
break;
case ‘expired’:
if (get_option(‘workscout_freelancer_submit_task_form_page_id’)) {
$actions[‘relist’] = array(‘label’ => esc_html__(‘Relist’, ‘workscout-freelancer’), ‘nonce’ => true);
}
break;
}
if (!in_array($status, array(‘completed’, ‘in_progress’))) {
$actions[‘delete’] = array(
‘label’ => esc_html__(‘Delete’, ‘workscout-freelancer’),
‘nonce’ => true,
‘class’ => ‘task-dashboard-action-delete’
);
}
$actions = apply_filters(‘workscout_freelancer_my_task_actions’, $actions, $task);
?>
<?php
global $post;
if ($status == ‘publish’) {
echo ($count = get_task_bidders_count($task->ID)) ? ‘<a href=”‘ . add_query_arg(
[
‘action’ => ‘show_bidders’,
‘task_id’ => $task->ID,
],
get_permalink($post->ID)
) . ‘” class=”button ripple-effect”><i class=”icon-material-outline-supervisor-account”></i>’ . esc_html__(“Manage Bidders”, ‘workscout-freelancer’) . ‘<span class=”button-info”>’ . $count . ‘</span></a>’ : ”;
}
if ($status == “in_progress” || $status == “completed”) {
$project_id = get_post_meta($task->ID, ‘_project_id’, true);
if ($project_id) {
$action_url = add_query_arg(array(‘action’ => ‘view-project’, ‘task_id’ => $task->ID, ‘project_id’ => $project_id));
?>
<a href=”<?php echo $action_url; ?>” class=”button dark ripple-effect” href=”#”><i class=”icon-material-outline-supervisor-account”></i><?php esc_html_e(‘View Project ‘, ‘workscout-freelancer’); ?></a>
<?php } ?>
<a data-task=”<?php echo $task->ID; ?>” class=”button dark task-dashboard-action-contact-bidder ripple-effect” href=”#”><i class=”icon-material-outline-supervisor-account”></i><?php esc_html_e(‘Order Summary’, ‘workscout-freelancer’); ?></a>
<?php }
?>
<?php
$selected_bid = get_post_meta($task->ID, ‘_selected_bid_id’, true);
// get author of selected bid
$selected_bid_author = get_post_field(‘post_author’, $selected_bid);
//var_dump($selected_bid_author);
if ($status == ‘completed’) {
//check if selected bid author has any comments
$reviewed_id = get_the_author_meta(‘freelancer_profile’, $selected_bid_author);
if (empty($reviewed_id)) {
// get ID of last post by user
$reviewed_id = get_posts(array(
‘author’ => $selected_bid_author,
‘posts_per_page’ => 1,
‘post_type’ => ‘resume’,
‘fields’ => ‘ids’,
‘orderby’ => ‘date’,
‘order’ => ‘DESC’
));
$reviewed_id = $reviewed_id[0];
}
//check if post with id $reviewed_id has a comment made by current user
$reviewed = get_comments(array(
‘post_id’ => $reviewed_id,
‘user_id’ => get_current_user_id(),
‘count’ => true
));
//var_dump($reviewed);
if ($reviewed == 0) { ?>
<a href=”” data-task=”<?php echo $task->ID; ?>” class=”button gray task-dashboard-action-review ripple-effect” href=”#”><i class=”icon-material-outline-rate-review”></i><?php esc_html_e(‘Rate Freelancer’, ‘workscout-freelancer’); ?></a>
<?php } else { ?>
<a href=”” data-task=”<?php echo $task->ID; ?>” class=”button gray task-dashboard-action-review ripple-effect” href=”#”><i class=”icon-material-outline-rate-review”></i><?php esc_html_e(‘Edit your rating’, ‘workscout-freelancer’); ?></a>
<?php }
}
foreach ($actions as $action => $value) {
$action_url = add_query_arg(array(‘action’ => $action, ‘task_id’ => $task->ID));
$class = isset($value[‘class’]) ? $value[‘class’] : ”;
if ($value[‘nonce’])
$action_url = wp_nonce_url($action_url, ‘workscout_freelancer_my_task_actions’);
echo ‘<a class=” ‘ . $class . ‘ button gray ripple-effect ico” title=”‘ . $value[‘label’] . ‘” href=”‘ . $action_url . ‘” data-tippy-placement=”top” class=”task-dashboard-action-‘ . $action . ‘”>’ . workscout_manage_action_icons($action) . ‘</a>’;
}
?>
</div>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
</div>
</div>
</div>
</div>
<!– Row / End –>
<div id=”small-dialog” class=”zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Contact Freelancer’, ‘workscout-freelancer’); ?></h3>
</div>
<!– Bidding –>
<div class=”bidding-widget”>
<!– Headline –>
</div>
</div>
<a style=”display: none;” href=”#small-dialog” class=”contact-popup popup-with-zoom-anim button dark ripple-effect ico” title=”<?php esc_html_e(‘Edit Bid’, ‘workscout-freelancer’); ?>” data-tippy-placement=”top”><i class=”icon-feather-edit”></i></a>
<!– Edit Bid Popup / End –>
<!– Send Direct Message Popup
================================================== –>
<!– Reply to review popup –>
<div id=”small-dialog-2″ class=”workscout-rate-popup zoom-anim-dialog mfp-hide small-dialog apply-popup “>
<div class=”small-dialog-header”>
<h3><?php esc_html_e(‘Rate Freelancer’, ‘workscout-freelancer’); ?></h3>
</div>
<div class=”rate-form margin-top-0″>
<!– Form –>
</div>
<div class=”notification closeable success margin-top-20″ style=”display: none;”></div>
</div>
<a style=”display: none;” href=”#small-dialog-2″ class=”rate-popup popup-with-zoom-anim button dark ripple-effect”><i class=”icon-feather-mail”></i> <?php esc_html_e(‘Send Message’, ‘workscout-freelancer’); ?></a>
<!– Send Direct Message Popup / End –>
<?php get_job_manager_template(‘pagination.php’, array(‘max_num_pages’ => $max_num_pages)); ?>
Task-package-selection.php
<?php
/**
* Template for choosing a package during the Resume submission.
*
* This template can be overridden by copying it to yourtheme/wc-paid-listings/task-package-selection.php.
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Automattic
* @package wp-job-manager-tasks
* @category Template
* @since 1.0.0
* @version 2.7.3
*/
if (!defined(‘ABSPATH’)) {
exit; // Exit if accessed directly.
}
if ($packages || $user_packages) :
$checked = 1;
?>
<form method=”post” id=”task_package_selection”>
<!– <input type=”submit” name=”continue” class=”button” value=”<?php echo apply_filters(‘submit_task_step_choose_package_submit_text’, $button_text); ?>” /> –>
<input type=”hidden” name=”task_id” value=”<?php echo esc_attr($task_id); ?>” />
<input type=”hidden” name=”job_id” value=”0″ />
<input type=”hidden” name=”step” value=”<?php echo esc_attr($step); ?>” />
<input type=”hidden” name=”workscout_freelancer_form” value=”<?php echo $form_name; ?>” />
<div class=”job_task_packages margin-top-40″>
<ul class=”job_packages products user-packages”>
<?php if ($user_packages) : ?>
<h2><?php _e(‘Your active packages’, ‘workscout-freelancer’); ?></h2>
<?php foreach ($user_packages as $key => $package) :
$package = wc_paid_listings_get_package($package);
?>
<li class=”user-job-package <?php echo $package->is_featured() ? ‘user-job-package-featured’ : ” ?>”>
<input type=”radio” <?php checked($checked, 1); ?> name=”task_package” value=”user-<?php echo $key; ?>” id=”user-package-<?php echo $package->get_id(); ?>” />
<label for=”user-package-<?php echo $package->get_id(); ?>”><?php echo $package->get_title(); ?>
<p />
<?php
$featured_marking = $package->is_featured() ? __(‘featured’, ‘workscout-freelancer’) : ”;
if ($package->get_limit()) {
// translators: 1: Posted count. 2: Featured marking. 3: Limit.
$package_description = _n(‘%1$s %2$s task posted out of %3$d’, ‘%1$s %2$s tasks posted out of %3$d’, $package->get_count(), ‘workscout-freelancer’);
printf($package_description, $package->get_count(), $featured_marking, $package->get_limit());
} else {
// translators: 1: Posted count. 2: Featured marking.
$package_description = _n(‘%1$s %2$s task posted’, ‘%1$s %2$s tasks posted’, $package->get_count(), ‘workscout-freelancer’);
printf($package_description, $package->get_count(), $featured_marking);
}
if ($package->get_duration()) {
printf(‘, ‘ . _n(‘listed for %s day’, ‘listed for %s days’, $package->get_duration(), ‘workscout-freelancer’), $package->get_duration());
}
$checked = 0;
?>
</p>
</label>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
<h4 class=”headline centered margin-bottom-25″><strong>
<?php
if ($user_packages) :
esc_html_e(‘Or Purchase New Package’, ‘workscout-freelancer’);
else :
esc_html_e(‘Choose Package’, ‘workscout-freelancer’); ?>
<?php endif; ?>
</strong></h4>
<div class=”clearfix”></div>
<?php if ($packages) :
$counter = 0; ?>
<div class=”pricing-plans-container margin-top-40″>
<?php foreach ($packages as $key => $package) :
$product = wc_get_product($package);
if (!$product->is_type(array(‘task_package’, ‘task_package_subscription’)) || !$product->is_purchasable()) {
continue;
}
/* @var $product WC_Product_Resume_Package|WC_Product_Resume_Package_Subscription */
if ($product->is_type(‘variation’)) {
$post = get_post($product->get_parent_id());
} else {
$post = get_post($product->get_id());
}
?>
<!– Pricing Plans Container –>
<!– Plan –>
<div class=”pricing-plan <?php if ($product->is_featured()) echo “recommended”; ?> “>
<?php if ($product->is_featured()) { ?>
<div class=”recommended-badge”><?php esc_html_e(‘Recommended’, ‘workscout-freelancer’) ?></div>
<?php } ?>
<h3><?php echo $product->get_title(); ?></h3>
<?php if ($product->get_short_description()) { ?> <p class=”margin-top-10″><?php echo $product->get_short_description(); ?></p><?php } ?>
<div class=”pricing-plan-label billed-monthly-label”><?php echo $product->get_price_html(); ?></div>
<div class=”pricing-plan-features”>
<ul>
<?php
$listingslimit = $product->get_limit();
if (!$listingslimit) {
echo “<li>”;
esc_html_e(‘Unlimited number of listings’, ‘workscout-freelancer’);
echo “</li>”;
} else { ?>
<li>
<?php esc_html_e(‘This plan includes ‘, ‘workscout-freelancer’);
printf(_n(‘%d listing’, ‘%s listings’, $listingslimit, ‘workscout-freelancer’) . ‘ ‘, $listingslimit); ?>
</li>
<?php }
$duration = $product->get_duration();
if ($duration > 0) : ?>
<li>
<?php esc_html_e(‘Listings are visible ‘, ‘workscout-freelancer’);
printf(_n(‘for %s day’, ‘for %s days’, $product->get_duration(), ‘workscout-freelancer’), $product->get_duration()); ?>
</li>
<?php else : ?>
<li>
<?php esc_html_e(‘Unlimited availability of listings’, ‘workscout-freelancer’); ?>
</li>
<?php endif; ?>
<?php if ($product->is_featured()) : ?>
<li><?php esc_html_e(‘Highlighted in Search Results’, ‘workscout-freelancer’); ?></li>
<?php endif; ?>
</ul>
<?php
echo $product->get_description();
?>
<div class=”clearfix”></div>
</div>
<div class=”plan-features”>
<input type=”radio” <?php if (!$user_packages && $counter == 0) : ?> checked=”checked” <?php endif; ?> name=”task_package” value=”<?php echo $product->get_id(); ?>” id=”package-<?php echo $product->get_id(); ?>” />
<label class=”button full-width margin-top-20″ for=”package-<?php echo $product->get_id(); ?>”><?php ($product->get_price()) ? esc_html_e(‘Buy this package’, ‘workscout-freelancer’) : esc_html_e(‘Choose this package’, ‘workscout-freelancer’); ?></label>
</div>
</div>
<?php $counter++;
endforeach; ?>
<?php endif; ?>
</div>
<?php else : ?>
<p><?php _e(‘No packages found’, ‘workscout-freelancer’); ?></p>
<?php endif; ?>
<div class=”submit-page”>
<p>
<input type=”submit” name=”continue” class=”button” value=”<?php echo apply_filters(‘submit_task_step_choose_package_submit_text’, $button_text); ?>” />
<input type=”hidden” name=”task_id” value=”<?php echo esc_attr($task_id); ?>” />
<input type=”hidden” name=”step” value=”<?php echo esc_attr($step); ?>” />
<input type=”hidden” name=”workscout_freelancer_form” value=”<?php echo $form_name; ?>” />
</p>
</div>
</form>
Task-preview.php
<?php
/**
* Template to show when previewing a task being submitted.
*
* This template can be overridden by copying it to yourtheme/wp-job-manager-tasks/task-preview.php.
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Automattic
* @package wp-job-manager-tasks
* @category Template
* @version 1.18.0
*
* @var WorkScout_Freelancer_Form_Submit_Task $form Form object performing the action.
*/
if (!defined(‘ABSPATH’)) {
exit; // Exit if accessed directly.
}
?>
<form method=”post” id=”task_preview” action=”<?php echo esc_url($form->get_action()); ?>”>
<?php
/**
* Fires at the top of the preview task form.
*
* @since 1.18.0
*/
do_action(‘preview_task_form_start’);
?>
<div class=”job_listing_preview_title”>
<input type=”submit” name=”continue” id=”task_preview_submit_button” class=”button job-manager-button-submit-listing” value=”<?php echo esc_attr(apply_filters(‘submit_task_step_preview_submit_text’, __(‘Submit Task →’, ‘workscout-freelancer’))); ?>” />
<input type=”submit” name=”edit_task” class=”button” value=”<?php esc_attr_e(‘← Edit task’, ‘workscout-freelancer’); ?>” />
<input type=”hidden” name=”task_id” value=”<?php echo esc_attr($form->get_task_id()); ?>” />
<input type=”hidden” name=”step” value=”<?php echo esc_attr($form->get_step()); ?>” />
<input type=”hidden” name=”workscout_freelancer_form” value=”<?php echo esc_attr($form->form_name); ?>” />
<h2><?php esc_html_e(‘Preview’, ‘workscout-freelancer’); ?></h2>
</div>
<div class=”task_preview single-task”>
<?php get_job_manager_template_part(‘content-single’, ‘task’, ‘workscout-freelancer’, WORKSCOUT_FREELANCER_PLUGIN_DIR . ‘/templates/’); ?>
</div>
<?php
/**
* Fires at the bottom of the preview task form.
*
* @since 1.18.0
*/
do_action(‘preview_task_form_end’);
?>
</form>
Tasks-end.php
</div>
Tasks-start.php
<!– Listings –>
<?php
$ajax_browsing = get_option(‘hireo_ajax_browsing’);
$search_data = ”;
if (isset($data)) :
switch ($data->style) {
case ‘list’:
$list_class = ”;
break;
case ‘compact’:
$list_class = ‘compact-list’;
break;
case ‘grid’:
$list_class = ‘tasks-grid-layout’;
break;
default:
$template = ”;
$list_class = ”;
break;
}
$custom_class = (isset($data->class)) ? $data->class : ”;
$in_rows = (isset($data->in_rows)) ? $data->in_rows : ”;
$grid_columns = (isset($data->grid_columns)) ? $data->grid_columns : ”;
$per_page = (isset($data->per_page)) ? $data->per_page : get_option(‘hireo_listings_per_page’, 10);
$ajax_browsing = (isset($data->ajax_browsing)) ? $data->ajax_browsing : get_option(‘hireo_ajax_browsing’);
if (isset($data->{‘tax-region’})) {
$search_data .= ‘ data-region=”‘ . esc_attr($data->{‘tax-region’}) . ‘” ‘;
}
if (isset($data->{‘tax-listing_category’})) {
$search_data .= ‘ data-category=”‘ . esc_attr($data->{‘tax-listing_category’}) . ‘” ‘;
}
if (isset($data->{‘tax-listing_feature’})) {
$search_data .= ‘ data-feature=”‘ . esc_attr($data->{‘tax-listing_feature’}) . ‘” ‘;
}
endif;
?>
<div data-style=”<?php if(isset($data->style)) echo $data->style; ?>” class=”tasks-list-container <?php echo $list_class; ?> margin-top-35″>
<div class=”loader-ajax-container”>
<div class=”loader-ajax”></div>
</div>
Task-submit.php
<?php
/**
* Resume Submission Form
*/
if (!defined(‘ABSPATH’)) exit;
wp_enqueue_script(‘wp-task-manager-task-submission’);
$has_company = false;
if (class_exists(‘MAS_WP_Job_Manager_Company’) && is_user_logged_in()) {
if (!get_option(‘job_manager_job_submission_required_company’)) {
$has_company = true;
} else {
// Get the current logged in user’s ID
$current_user_id = get_current_user_id();
// Count the user’s posts for ‘resume’ CPT
$user_post_count = (int) count_user_posts($current_user_id, ‘company’);
// If the user has a ‘resume’ CPT published
if ($user_post_count > 0) {
$has_company = true;
}
}
} else {
$has_company = true;
}
?>
<form action=”<?php echo $action; ?>” method=”post” id=”submit-task-form” class=”job-manager-form” enctype=”multipart/form-data”>
<?php do_action(‘submit_task_form_start’); ?>
<?php if (workscout_freelancer_user_can_post_task()) : ?>
<?php if ($company_fields) : ?>
<div class=”dashboard-box margin-bottom-30″>
<div class=”headline”>
<h3><i class=”icon-feather-folder-plus”></i><?php esc_html_e(‘Select Company’, ‘workscout-freelancer’); ?></h3>
</div>
<div class=”task-form-container content with-padding padding-bottom-10″>
<?php do_action(‘submit_job_form_company_fields_start’); ?>
<?php foreach ($company_fields as $key => $field) : ?>
<fieldset class=”form fieldset-<?php echo esc_attr($key); ?>”>
<label for=”<?php echo esc_attr($key); ?>”><?php echo $field[‘label’] . apply_filters(‘submit_job_form_required_label’, $field[‘required’] ? ” : ‘ <small>’ . esc_html__(‘(optional)’, ‘workscout-freelancer’) . ‘</small>’, $field); ?></label>
<div class=”field <?php echo $field[‘required’] ? ‘required-field’ : ”; ?>”>
<?php get_job_manager_template(‘form-fields/’ . $field[‘type’] . ‘-field.php’, array(‘key’ => $key, ‘field’ => $field)); ?>
</div>
</fieldset>
<?php endforeach; ?>
<?php if (class_exists(‘MAS_WP_Job_Manager_Company’) && !$has_company) { ?>
<?php $submit_company = get_option(‘job_manager_submit_company_form_page_id’); ?>
<div class=”notification add-company-notice notice”><?php esc_html_e(“You can select your company before adding task. If you didn’t add company profile yet click button below.”, ‘workscout-freelancer’); ?></div>
<a href=”<?php echo esc_url(get_permalink($submit_company)); ?>” class=”button add-company-btn”><i class=”fa fa-plus-circle”></i> <?php esc_html_e(“Add Company”, ‘workscout-freelancer’); ?></a>
<?php } ?>
<?php do_action(‘submit_job_form_company_fields_end’); ?>
</div>
</div>
<?php endif; ?>
<div class=”dashboard-box margin-top-0″>
<!– Resume Fields –>
<?php do_action(‘submit_task_form_task_fields_start’); ?>
<div class=”headline”>
<h3><i class=”icon-feather-folder-plus”></i> <?php esc_html_e(‘Task Submission Form’, ‘workscout-freelancer’); ?></h3>
</div>
<div class=”task-form-container content with-padding padding-bottom-10″>
<?php
$total_width = 0;
$keys = array_keys($task_fields); // Get the keys of the array
if(isset($task_id) && !empty($task_id)){
$type = get_post_meta($task_id, ‘_task_type’, true);
if($type == ‘fixed’){
$exclude_keys = array(‘hourly_min’, ‘hourly_max’);
} else {
$exclude_keys = array(‘budget_min’, ‘budget_max’);
}
} else {
$exclude_keys = array(‘hourly_min’, ‘hourly_max’);
}
foreach ($keys as $index => $key) :
$field = $task_fields[$key];
if (in_array($key, $exclude_keys)) {
continue;
}
if (isset($field[‘width’])) {
switch ($field[‘width’]) {
case 2:
$wrap_class = ‘col-md-2’;
break;
case 3:
$wrap_class = ‘col-md-3’;
break;
case 4:
$wrap_class = ‘col-md-4’;
break;
case 6:
$wrap_class = ‘col-md-6’;
break;
case 12:
$wrap_class = ‘col-md-12’;
break;
default:
$wrap_class = ‘col-md-4’;
break;
}
} else {
$wrap_class = ‘col-md-4’;
}
if (isset($field[‘width’])) {
$width = $field[‘width’];
} else {
$width = 4;
}
if ($total_width == 0) {
echo “<div class=’row’>”;
}
?>
<div class=”<?php echo $wrap_class; ?> task-submit-form-container-<?php echo esc_attr($key); ?>”>
<div class=”submit-field”>
<fieldset class=”form fieldset-<?php echo esc_attr($key); ?>”>
<label for=”<?php echo esc_attr($key); ?>”><?php echo $field[‘label’] . apply_filters(‘submit_task_form_required_label’, $field[‘required’] ? ” : ‘ ‘, $field); ?></label>
<div class=”field”>
<?php
// if field is budget_min or budget_max then add required value to it
if($key == ‘budget_min’ || $key == ‘budget_max’){
$field[‘required’] = true;
}
$class->get_field_template($key, $field); ?>
</div>
</fieldset>
</div>
</div>
<?php
$total_width += $width;
if ($index < count($keys) – 1) {
$next_key = $keys[$index + 1];
$next_element = $task_fields[$next_key];
if (isset($next_element[‘width’])) {
$next_width = $next_element[‘width’];
} else {
$next_width = 4;
}
}
if ($total_width > 12 || $total_width + $next_width > 12) {
echo “</div>”;
$total_width = 0;
}
endforeach; ?>
<?php do_action(‘submit_task_form_task_fields_end’); ?>
</div>
</div>
<div id=”outside-task-form-container” style=”display: none;”>
<?php foreach ($keys as $index => $key) :
$field = $task_fields[$key];
if (in_array($key, $exclude_keys)) {
if (isset($field[‘width’])) {
switch ($field[‘width’]) {
case 2:
$wrap_class = ‘col-md-2’;
break;
case 3:
$wrap_class = ‘col-md-3’;
break;
case 4:
$wrap_class = ‘col-md-4’;
break;
case 6:
$wrap_class = ‘col-md-6’;
break;
case 12:
$wrap_class = ‘col-md-12’;
break;
default:
$wrap_class = ‘col-md-4’;
break;
}
} else {
$wrap_class = ‘col-md-4’;
}
if (isset($field[‘width’])) {
$width = $field[‘width’];
} else {
$width = 4;
}
?>
<div class=”<?php echo $wrap_class; ?> task-submit-form-container-<?php echo esc_attr($key); ?>”>
<div class=”submit-field”>
<fieldset class=”form fieldset-<?php echo esc_attr($key); ?>”>
<label for=”<?php echo esc_attr($key); ?>”><?php echo $field[‘label’] . apply_filters(‘submit_task_form_required_label’, $field[‘required’] ? ” : ‘ ‘, $field); ?></label>
<div class=”field”>
<?php $class->get_field_template($key, $field); ?>
</div>
</fieldset>
</div>
</div>
<?php
} else {
continue;
}
endforeach; ?>
</div>
<p class=”send-btn-border”>
<input type=”hidden” name=”workscout_freelancer_form” value=”<?php echo $form; ?>” />
<input type=”hidden” name=”task_id” value=”<?php echo esc_attr($task_id); ?>” />
<input type=”hidden” name=”step” value=”<?php echo esc_attr($step); ?>” />
<input type=”submit” name=”submit_task” class=”button big” value=”<?php echo esc_attr($submit_button_text); ?>” />
</p>
<?php else : ?>
<?php do_action(‘submit_task_form_disabled’); ?>
<?php endif; ?>
<?php do_action(‘submit_task_form_end’); ?>
</form>
Task-submitted.php
<?php
/**
* Message to display when a task has been submitted.
*
* This template can be overridden by copying it to yourtheme/wp-job-manager-tasks/task-submitted.php.
*
* @see https://wpjobmanager.com/document/template-overrides/
* @author Automattic
* @package wp-job-manager-tasks
* @category Template
* @version 1.18.0
*
* @var int $task_id When initiating task submission, this is the job that the user intends to apply for.
* @var WP_Post $task task post object that was just submitted.
*/
if (!defined(‘ABSPATH’)) {
exit;
}
?>
<div class=”listing-added-notice”>
<div class=”booking-confirmation-page”>
<i class=”fa fa-check-circle”></i>
<h2 class=”margin-top-30″><?php esc_html_e(‘Thanks for your submission!’, ‘workscout-freelancer’) ?></h2>
<?php
switch ( $task->post_status ) :
case ‘publish’:
echo ‘<p class=”task-submitted”>’;
echo wp_kses_post(
sprintf(
// translators: Placeholder is URL to view the task.
__( ‘Your task has been submitted successfully. To view your task <a href=”%s”>click here</a>.’, ‘workscout-freelancer’ ),
esc_url( get_permalink( $task->ID ) )
)
);
echo ‘</p>’;
break;
case ‘pending’:
echo ‘<p class=”task-submitted”>’;
echo esc_html( __( ‘Your task has been submitted successfully and is pending approval.’, ‘workscout-freelancer’ ) );
if (
$task_id
&& ‘publish’ === get_post_status( $task_id )
&& ‘task’ === get_post_type( $task_id )
) {
$task_title = get_the_title( $task_id );
$task_permalink = get_permalink( $task_id );
echo wp_kses_post(
sprintf(
// translators: %1$s is the url to the job listing; %2$s is the title of the job listing.
__( ‘ You will be able to apply for <a href=”%1$s”>%2$s</a> once your task has been approved.’, ‘workscout-freelancer’ ),
$task_permalink,
$task_title
)
);
}
echo ‘</p>’;
break;
default:
$hook_friendly_post_status = str_replace( ‘-‘, ‘_’, sanitize_title( $task->post_status ) );
do_action( ‘task_manager_task_submitted_content_’ . $hook_friendly_post_status, $task );
break;
endswitch; ?>
</p>
<?php if(get_post_status( $task->id ) == ‘publish’) : ?>
<a class=”button margin-top-30″ href=”<?php echo get_permalink( $task->id ); ?>”><?php esc_html_e( ‘View →’, ‘workscout-freelancer’ ); ?></a>
<?php endif; ?>
</div>
</div>
