db = $wpdb; $this->table_name = $wpdb->prefix . 'acare_ts'; $this->addr_table = $wpdb->prefix . 'acare_addr_distance'; $this->ndis_table = $wpdb->prefix . 'acare_ndis_price'; } /** * Autoload the custom theme classes */ public function class_loader() { // Create a new instance of the autoloader $loader = new \Psr4AutoloaderClass(); // Register this instance $loader->register(); // Add our namespace and the folder it maps to $loader->addNamespace('\XeroPHP', dirname(__FILE__) . '/xero-php-master/src/XeroPHP'); $loader->addNamespace('\Biukop', dirname(__FILE__) . '/' ); $this->xero = new Xero(); $this->xero->init_wp(); //$abc = new AddrMap("01515b52-6936-46b2-a000-9ad4cd7a5b50", "0768db6d-e5f4-4b45-89a2-29f7e8d2953c"); $abc = new AddrMap("122eb1d0-d8c4-4fc3-8bf8-b7825bee1a01", "0768db6d-e5f4-4b45-89a2-29f7e8d2953c"); } //init database public function db_install () { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); //table name: timesheets jobs $table_name = $this->table_name; $sql = "CREATE TABLE $table_name ( id INT NOT NULL AUTO_INCREMENT, tos VARCHAR(45) NULL, start DATETIME NULL, finish DATETIME NULL, rate VARCHAR(45) NULL, staff VARCHAR(45) NULL, client VARCHAR(45) NULL, ack TINYINT(4) NULL, rating INT(4) NULL DEFAULT 0, PRIMARY KEY (id) ) $charset_collate;"; //addr distance $addr_table = $this->addr_table; $sql_addr = "CREATE TABLE $addr_table ( id INT NOT NULL AUTO_INCREMENT, origin VARCHAR(1024) NULL, destination VARCHAR(1024) NULL, response VARCHAR(40960) NULL, distance INT NULL, PRIMARY KEY (id) ) $charset_collate;"; $ndis_table = $this->ndis_table; $sql_ndis_price = " CREATE TABLE $ndis_table ( code VARCHAR(45) NOT NULL, name VARCHAR(45) NULL, level INT NULL, unit VARCHAR(45) NULL, price FLOAT NULL, year INT NOT NULL, PRIMARY KEY (code, year) )$charset_collate;"; //create database require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); dbDelta( $sql ); dbDelta( $sql_addr); dbDelta( $sql_ndis_price); } // //query var public function add_query_vars($aVars) { $aVars[] = "bts_user_id"; // represents the name of the product category as shown in the URL $aVars[] = "bts_week_id"; // represents the name of the product category as shown in the URL $aVars[] = "bts_job_start"; // represents the name of the product category as shown in the URL $aVars[] = "bts_job_finish"; // represents the name of the product category as shown in the URL return $aVars; } //for customer profile and broker trans public function my_add_rewrite_rules($aRules) { $aNewRules = array( 'user/([^/]+)/?$' => 'index.php?pagename=user&bts_user_id=$matches[1]', 'task/week-([^/]+)/?$' => 'index.php?pagename=task&bts_week_id=$matches[1]', 'task/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=task&bts_job_start=$matches[1]&bts_job_finish=$matches[2]', 'task/([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]', 'task/([^/]+)/week-([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]&bts_week_id=$matches[2]', 'task/([^/]+)/start-([^/]+)/finish-([^/]+)/?$' => 'index.php?pagename=task&bts_user_id=$matches[1]&bts_job_start=$matches[2]&bts_job_finish=$matches[3]', ); $aRules = $aNewRules + $aRules; return $aRules; } // // ///check auth public function check_auth(){ global $pagename; switch($pagename){ case 'task': $this->cauth_task(); break; case 'time-sheets': $this->cauth_time_sheet(); } } private function cauth_task(){ $login = get_query_var( 'bts_user_id' ); $this->bts_job_start = get_query_var( 'bts_job_start' ); $this->bts_job_finish = get_query_var( 'bts_job_finish' ); $this->bts_week_id = get_query_var('bts_week_id'); $redirect_url = $this->get_redirect_url_for_task(); // wp_send_json(array( // 'week'=> $week, // 'userid'=>$login, // 'job_start' => $this->bts_job_start, // 'job_finish' => $this->bts_job_finish, // 'redirect' => $redirect_url, // )); if ($login != "")//perform autologin, and redirect { $staff = get_user_by('login', $login); if ($this->is_staff($staff)){//is valid staff; $current = wp_get_current_user(); if($current->ID != $staff->ID){ wp_logout(); wp_set_current_user($staff->ID, $staff->display_name); //this is a must wp_set_auth_cookie($staff->ID, true);//only with this, wordpress calls login + redirect and lost week-%d } } wp_redirect($redirect_url); return; } //no auto login is required if reach here. $current = wp_get_current_user(); if ($this->is_admin($current)){ wp_redirect("/time-sheets/"); return; } if (!$this->is_staff($current) && ! $this->is_admin($current)) { wp_logout(); wp_redirect("/login/"); return; } } private function get_week_id() { $week = get_query_var( 'bts_week_id' ); $week_id = intval($week); if ($week_id == 0 || $week_id >53 ||$week_id < 1) return $this->get_current_week_id(); else return $week; } private function get_current_week_id() { $now = new \DateTime(); $week = $now->format("W"); return $week; } private function get_redirect_url_for_task() { if ($this->bts_week_id != "") return "/task/week-" . $this->bts_week_id . "/"; if ($this->bts_job_start!="" && $this->bts_job_finish !="") return "/task/start-" . $this->bts_job_start . "/finish-" .$this->bts_job_finish . "/"; return '/task/'; } private function cauth_time_sheet() { $current = wp_get_current_user(); if ($current->ID == 0 ) { //visitor not logged in wp_redirect("/wp-login.php?"); return; } if ($this->is_staff($current)){ wp_redirect("/task"); return; } if ($this->is_admin($current)){ //proceed return; } if ($this->is_client($current)){ wp_redirect("/service"); return; } //everything else wp_redirect("/?invalid-access"); } /// // enqueue / register css /js // public function register_js_css() { $this->nonce = wp_create_nonce('acaresydney'); $this->bts_user_id = get_query_var( 'bts_user_id' ) ; $this->register_bts_js(); $this->register_timesheet_js_css(); $this->register_task_js_css(); } private function register_bts_js() { wp_enqueue_style( 'bts', plugins_url('css/ts.css', __FILE__)); wp_enqueue_script('bts', plugins_url('js/ts.js', __FILE__), array('jquery', 'jquery-ui-core')); wp_localize_script( 'bts', 'bts1', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => $this->nonce, // It is common practice to comma after 'display_name' => wp_get_current_user()->display_name, 'anonymous' => !is_user_logged_in(), 'me'=> get_current_user_id(), 'userid'=> $this->bts_user_id, 'load_user_img'=> plugins_url('img/loading_user.gif', __FILE__), 'load_job_img'=> plugins_url('img/loading_job.gif', __FILE__), 'earnings_rate'=> get_option('bts_payitem_earnings_rate'), 'high_pay_keywords' => ['sat ', 'sun ', 'high ', 'public holiday'], //space is important ) ); } private function register_timesheet_js_css(){ global $pagename; if ($pagename != 'time-sheets'){ return; } wp_enqueue_style( 'bts_ts', plugins_url('css/bts_timesheet.css', __FILE__)); wp_enqueue_script( 'bts_ts', plugins_url('js/bts_timesheet.js', __FILE__), array( 'jquery' , 'bts' )); wp_enqueue_script('mustache', plugins_url('js/mustache.min.js', __FILE__), array('jquery')); } private function register_task_js_css(){ global $pagename; if ($pagename != 'task'){ return; } $this->bts_job_start = get_query_var( 'bts_job_start' ); $this->bts_job_finish = get_query_var( 'bts_job_finish' ); $this->bts_week_id = get_query_var('bts_week_id'); wp_enqueue_style( 'bts_task', plugins_url('css/bts_task.css', __FILE__)); wp_enqueue_script( 'bts_task', plugins_url('js/bts_task.js', __FILE__), array( 'jquery' , 'bts' )); wp_enqueue_script('mustache', plugins_url('js/mustache.min.js', __FILE__), array('jquery')); wp_localize_script('bts_task','bts_task1',array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce('bts_task'), 'week_id' => $this->bts_week_id, 'bts_job_start' => $this->bts_job_start, 'bts_job_finish' => $this->bts_job_finish, ) ); } public function sync_users() { //dummy sync return; } // Usage: `wp sync_users --mininterval=123 public function sync_user_cli($args = array(), $assoc_args = array()){ $arguments = wp_parse_args( $assoc_args, array( 'mininterval' => 600, 'employeeonly' => false, 'clientsonly' => false, ) ); $this->xero->sync_users($arguments['mininterval'], $arguments['employeeonly'], $arguments['clientsonly']); return; } public function email_jobs($args = array(), $assoc_args = array()){ $users = get_users(array('role' => 'staff')); foreach ($users as $u){ $n = new UserJob($u->user_login); $resp = $n->list_jobs("2019-07-22 00:00:00", "2019-07-28 23:59:59"); if ($resp['status']=='success' && $resp['job_count'] >0 ){ if( $u->user_login != "9aa3308e-cc19-4c21-a110-f2c6abec4337" ) continue; $msg = sprintf("Staff = %s, Login=%s, email=%s Job=%d\n", $u->display_name, $u->user_login, $u->user_email, $resp['job_count']); echo $msg; $this->send_email_with_job_link($u, "2019-07-22", "2019-07-28"); } } return; } private function send_email_with_job_link($staff, $start, $finish) { $message = file_get_contents(plugin_dir_path(__FILE__) . "/html/email_job.html"); $message = str_ireplace("{{display_name}}", $staff->display_name, $message); $message = str_ireplace("{{user_login}}", $staff->user_login, $message); $message = str_ireplace("{{job_start}}", $start, $message); $message = str_ireplace("{{job_finish}}", $finish, $message); $headers = ['Bcc: patrick@biukop.com.au']; //wp_mail("sp@lawipac.com", "Your Job arrangement 22 July ~ 28 July", $message, $headers); wp_mail($staff->user_email, "Your Job arrangement $start ~ $finish", $message, $headers); } public function bts_staff_item($attr){ return $this->template('staff_item', 'staff.html'); } public function bts_client_item($attr){ return $this->template('client_item', 'client.html'); } public function bts_job_item($attr){ $html =$this->template('job_item', 'job.html'); //$html = str_replace('[bts-tos-options]', $this->bts_tos_options([]), $html); $html = do_shortcode($html); return $html; } public function bts_rate_options($attr){ $result = ""; return $result; } public function bts_select_staff($attr){ $result = ""; return $result; } public function bts_select_client($attr){ $result = ""; return $result; } public function bts_type_of_service($attr){ $n = new NdisPrice(2019); return $n->get_html(); } public function bts_user_name($attr) { $user = wp_get_current_user(); return $user->display_name; } public function bts_staff_job_summary($attr) { $result =" If there is more than one job, please click on 'confirm' to make sure it is included in your payment. "; return $result; } //generate template based on html file private function template($id, $file) { $text = ''; return $text; } function list_staff(){ check_ajax_referer('acaresydney'); // Handle the ajax request $response = array( 'status' =>'error', 'users' => [], ); //search all users that are staff $staffq = new \WP_User_Query(array('role'=>'staff','meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC')); $staff = $staffq->get_results(); if (! empty($staff)){ $response['status'] = 'success'; foreach( $staff as $s){ $response['users'][] = array( 'login' => $s->user_login, 'firstname'=> $s->first_name, 'lastname'=> $s->last_name, 'mobile'=> get_user_meta($s->ID, 'mobile', true), 'email'=> $s->user_email, 'wages'=> 0, 'hour' => 0 , 'OT' => 0 , 'petrol'=> 0 , 'rating'=> 0, 'unconfirmedjob'=> 0, ); } } wp_send_json($response); wp_die(); } function list_client(){ check_ajax_referer('acaresydney'); // Handle the ajax request $response = array( 'status' =>'error', 'users' => [], ); //search all users that are staff $clientq = new \WP_User_Query(array('role'=>'client', 'meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC')); $client = $clientq->get_results(); if (! empty($client)){ $response['status'] = 'success'; foreach( $client as $s){ $response['users'][] = array( 'login' => $s->user_login, 'firstname'=> $s->first_name, 'lastname'=> $s->last_name, 'display_name'=> $s->display_name, 'mobile'=> get_user_meta($s->ID, 'mobile', true), 'email'=> $s->user_email, 'account'=> get_user_meta($s->ID, 'account', true), 'address' => get_user_meta($s->ID, 'address', true), 'rating'=> 0, 'unconfirmedjob'=> 0, ); } } wp_send_json($response); wp_die(); } private function get_people_by_role($role){ //search all users that are staff $staffq = new \WP_User_Query(array('role'=>$role, 'meta_key'=>'first_name', 'orderby'=>'meta_value', 'order'=>'ASC')); $staff = $staffq->get_results(); return $staff; } //ajax get earnings rates function get_payitem_earnings_rate() { $response= array( 'status' => 'success', 'options'=> get_option('bts_payitem_earnings_rate'), ); wp_send_json($response); } //ajax job CRUD function save_job() { check_ajax_referer('acaresydney'); $r = $_POST['record']; $response = array(); $d = array( 'tos' => $r['tos'], 'start' => $r['start'], 'finish' => $r['finish'], 'rate' => $r['rate'], 'staff' => $r['staff'], 'client' => $r['client'], 'ack' => $r['ack']=='true'?1:0, 'rating'=>$r['rating'], ); //this is an update if ( isset($r['id']) && trim($r['id']) !='' && is_numeric($r['id'])){ $response['isNew'] = false; //add or update? $result = $this->db->update($this->table_name, $d, array('id' =>$r['id'])); if ($result !== false && $this->db->last_error == ''){ $d['id'] = $r['id']; $response['status'] = 'success'; //do data type conversion, string to int $response['newdata'] = $this->get_ts_record($r['id']); $response['errors'] = array(); //empty array }else{ $response['status'] = 'error'; $repsonse['errors'] = array( 'db' => "network database error" . $this->db->last_error, ); } }else{ $response['isNew'] = true; $result = $this->db->insert($this->table_name, $d); $lastid = $this->db->insert_id; if ($result != false && $this->db->last_error == ''){ $response['status'] = 'success'; $response['newdata'] = $this->get_ts_record($lastid); }else{ $response['status'] = 'error'; $response['errors'] = array( 'db' => 'network database error ' . $this->db->last_error, ); } } wp_send_json($response); wp_die(); } private function get_ts_record($id){ $sql = "SELECT * FROM $this->table_name WHERE id=%d"; $row = $this->db->get_row($this->db->prepare ($sql, array($id))); $response = []; if ($row != null){ $response = array( 'id' => (int)$row->id, 'tos' => $row->tos, 'start' => $row->start, 'finish' => $row->finish, 'rate' => $row->rate, 'staff' => $row->staff, 'client' => $row->client, 'ack' => (int)$row->ack, 'rating' =>(int) $row->rating, ); } return $response; } //ajax delete job function delete_job(){ check_ajax_referer('acaresydney'); $id = $_POST['jobid']; $result = $this->db->delete($this->table_name, array('id'=> $id)); $response=array( 'status' => 'success', 'id' => $id, 'action'=> 'delete', 'error' => '', ); if ($result == 1){ wp_send_json($response); }else{ $response['status'] = 'error'; $response['error'] = $this->db->last_error; wp_send_json($response); } wp_die(); } //ajax email staff their job arrangement function email_job() { check_ajax_referer('acaresydney'); $staff = $_POST['staff']; $start = $_POST['start']; $finish = $_POST['finish']; $response=array( 'status' => 'success', 'staff' => $staff, 'start' => $start, 'finish' => $finish, 'error' => '', 'sent' => false, 'emailstatus'=>"Bypass (no job)", ); $u = get_user_by('login', $staff); if ($this->is_staff($u)){ $n = new UserJob($staff); $resp = $n->list_jobs("$start 00:00:00", "$finish 23:59:59"); if ($resp['status']=='success' && $resp['job_count'] >0 ){ $msg = sprintf("Email to %s (with job=%d) \n", $u->user_email, $resp['job_count']); $this->send_email_with_job_link($u, $start, $finish); $response['sent'] = true; $response['emailstatus'] = $msg; } } wp_send_json($response); } //ajax browse job with different filters function list_job(){ check_ajax_referer('acaresydney'); $start = $_POST['start']; $finish = $_POST['finish']; $response = array( 'status'=>'success', 'jobs' => [], ); $sql = "SELECT * FROM $this->table_name WHERE start>='%s' and start <='%s' order by start ASC ,staff ASC"; $jobs = $this->db->get_results($this->db->prepare ($sql, array($start, $finish))); if (! empty($jobs)){ $response['status'] = 'success'; foreach( $jobs as $s){ $response['jobs'][] = array( 'id' => $s->id, 'tos' => $s->tos, 'start'=> $s->start, 'finish'=> $s->finish, 'rate'=> $s->rate, 'staff'=> $s->staff, 'client'=> $s->client, 'ack' => $s->ack, 'rating' =>$s->rating, ); } } wp_send_json($response); wp_die(); } public function list_job_by_staff() { //check_ajax_referer('acaresydney'); $start = $_POST['start']; $finish = $_POST['finish']; //$start="2019-07-01 00:00:00"; //$finish="2019-07-14 23:59:59"; $user = wp_get_current_user();// should be staff; if ( $this->is_staff($user) ){ $n = new UserJob($user->user_login); $response = $n->list_jobs($start, $finish); wp_send_json($response); }else{ $response = array( 'status' => 'error', 'errmsg' => 'invalid access', 'user' => $user, ); wp_send_json($response); } wp_die(); } private function is_staff($user) { return ($user->ID !=0 && in_array('staff', $user->roles)); } private function is_admin($user) { $allowed_roles = array('administrator', 'acare_owner'); if( array_intersect($allowed_roles, $user->roles ) ) { return true; } } public function staff_ack_job() { check_ajax_referer('acaresydney'); $jobs = $_POST['jobs']; $response = array( 'status'=>'success', 'jobs'=>$jobs, ); $yes=[]; $no=[]; foreach($jobs as $job){ if ( $job['ack'] == "true") $yes[] =(int) $job['id']; else $no[] = (int) $job['id']; } $err = $this->ack_multiple_job($yes, $no); if ($this->db->last_error !='') { $response['status']= 'error'; $response['err_msg']= $err; } $response['yes'] = $yes; $response['no'] = $no; wp_send_json($response); wp_die(); } public function ack_multiple_job($yes, $no) { $str_yes_ids = implode(",", $yes); $str_no_ids = implode(",", $no); $err = ""; if (count($yes) >0 ){ $sql = "UPDATE $this->table_name SET ack=1 WHERE id IN ( $str_yes_ids) ; "; $r = $this->db->get_results($sql); $err = $this->db->last_error; } if (count($no) >0 ){ $sql = "UPDATE $this->table_name SET ack=0 WHERE id IN ( $str_no_ids) ; "; $r = $this->db->get_results($sql); $err .= $this->db->last_error; } return $err; } } $bb = new AcareOffice(); if ( defined( 'WP_CLI' ) && WP_CLI ) { \WP_CLI::add_command( 'sync_users', array($bb, 'sync_user_cli')); \WP_CLI::add_command( 'email_jobs', array($bb, 'email_jobs')); } //$bb->class_loader(); //$bb->list_job_by_staff();