Jump to content

fastsol

Moderators
  • Posts

    827
  • Joined

  • Last visited

  • Days Won

    9

Everything posted by fastsol

  1. Yeah, I understand those apsects. The Config class is static mainly cause it's just used to get values from a certain array of values across the entire system. It makes it easier and faster to check certain vars by not having to use isset first and then check it's value, cause the class does all that for you. And yes I suppose it could have been made non-static but then I had to deal with scope and I just wanted a easier way around certain things. I fully understand scope and how the DI takes care of it. Beyond that stuff, are the classes decent? I know they're small so they can't be too bad and it's not like I don't know what I'm doing with php, just not totally with class methodology.
  2. I actually have a reminder in my phone calendar each month to go in and sync the server time. I ran into an error using the Google API that it wouldn't let the AUTH happen cause the time my server was returning was too far off from what they expected, so it wouldn't authorize the api call. As soon as I synced the time, the api loaded just fine again.
  3. Well I've decided to abandon this project for now. I need to learn too much to make it right and I don't have the time right now. Hopefully next spring I can rebuild the entire site in a solid framework and all will be well. But for now, I do have a couple small classes that I would like an opinion on how to improve. They are for connecting to and using the Google Calendar API. One class handles the connecting and the other makes the calls. I know for sure that one class is totally dependent on another static class in my system and I understand that that is wrong. I understand the concept of dependency injection but find the overall concept of throwing classes around to inject isn't good either. I'm sure that a solid framework solves those issues, but for now this is what I have to work with. So guidance would be greatly appreciated, examples speak louder GoogleAuth class <?php class GoogleAuth { protected $client; public function __construct(Google_Client $googleClient) { $this->client = $googleClient; if($this->client) { $this->client->setApplicationName(Config::get('cal_cred/cal_project_name')); $this->client->setAccessType("offline"); /*if (!empty($_SESSION['service_token'])) { $this->client->setAccessToken($_SESSION['service_token']); }*/ $cred = new Google_Auth_AssertionCredentials( Config::get('cal_cred/cal_email_address'), Config::get('cal_cred/cal_scopes'), file_get_contents(Config::get('cal_cred/cal_p12_file')) ); $this->client->setAssertionCredentials($cred); //diagDiv($this->client); if($this->client->getAuth()->isAccessTokenExpired()) { $this->client->getAuth()->refreshTokenWithAssertion($cred); } //$_SESSION['service_token'] = $this->client->getAccessToken(); } } } ?> GoogleCalendar class <?php class GoogleCalendar { protected $setup; protected $event_params; protected $cal_event; protected $createdEvent; protected $gsc; protected $auth; protected $cal; protected $lastInsertId; protected $deletedEvent; protected $updatedEvent; protected $error; public function __construct() { require_once(ROOT.'site_specific/other_pages/Google/autoload.php'); $this->client = new Google_Client; $this->auth = new GoogleAuth($this->client); $this->gsc = new Google_Service_Calendar($this->client); } // Must provide: desc, start and end elements. location is an optional element. // start and end must be in this format 2015-06-04T11:30:00 public function event_params(array $params) { $this->event_params = $params; return $this; } public function calendarEvent() { $this->cal_event = ''; $this->cal_event = new Google_Service_Calendar_Event(); $this->cal_event->setSummary($this->event_params['desc']); (!empty($this->event_params['location'])) ? $this->cal_event->setLocation($this->event_params['location']) : ''; $start = new Google_Service_Calendar_EventDateTime(); $start->setTimeZone(Config::get('cal_cred/cal_timezone')); $start->setDateTime($this->event_params['start']); $this->cal_event->setStart($start); $end = new Google_Service_Calendar_EventDateTime(); $end->setTimeZone(Config::get('cal_cred/cal_timezone')); $end->setDateTime($this->event_params['end']); $this->cal_event->setEnd($end); return $this; } public function insert_event() { try { $this->createdEvent = $this->gsc->events->insert(Config::get('cal_cred/cal_name'), $this->cal_event); $this->lastInsertId = $this->createdEvent->getId(); } catch(Google_Service_Exception $e) { $this->error = $e; } return $this; } public function update_event($event_id) { try { $this->updatedEvent = $this->gsc->events->update(Config::get('cal_cred/cal_name'), $event_id, $this->cal_event); } catch(Google_Service_Exception $e) { $this->error = $e; } return $this; } public function quickAdd_event($info) { try { $this->quickAddEvent = $this->gsc->events->quickAdd(Config::get('cal_cred/cal_name'), $info); $this->lastInsertId = $this->quickAddEvent->getId(); } catch(Google_Service_Exception $e) { $this->error = $e; } return $this; } public function delete_event($event_id) { try { $this->deletedEvent = $this->gsc->events->delete(Config::get('cal_cred/cal_name'), $event_id); } catch(Google_Service_Exception $e) { $this->error = $e; } return $this; } public function lastInsertId() { return $this->lastInsertId; } public function error() { return $this->error; } public function getItemById($id) { return $this->gsc->events->get(Config::get('cal_cred/cal_name'), $id); } } ?> This is how I would typically use these classes if(Config::get('use_gcal') === TRUE) { $gc = new GoogleCalendar; $event = $gc->getItemById($google_id); $time_format = "Y-m-d\TH:i:s"; $stime = date($time_format, $post_time); $etime = date($time_format, strtotime("+2 hours", $post_time)); $google_params = [ 'desc' => $event->summary, 'location' => html_entity_decode(Config::get('waiting_spot_options/'.$wait_id), ENT_QUOTES), 'start' => $stime, 'end' => $etime ]; $gc->event_params($google_params); $gc->calendarEvent(); $gc->update_event($google_id); }
  4. I've been battling this all day and haven't gotten nearly as far as I had hoped. I've made many new class pages and broken out many aspects, but I still can't get the flow down in my head. That processquote() does so much and it needs to do it in a certain order that I can't figure out how to break it apart without literally breaking it.
  5. Ahh, now I see the potential maxxd. As much as I'd love to integrate my cms into a far superior MVC type thing, it would be mind boggling hard and time consuming. It was built in procedural with tons of features and tons of files that would need complete recoding. So I'll just have to make it work in sections that are important to make easier to upgrade, like my quote system.
  6. I think I understand what you're getting at, but it doesn't seem to really solve a problem if you have to always do a method_exists or function_exists check every time you want to use the dynamic made function. Might as well just do it the way I am with still less code, unless I'm not understanding fully.
  7. I've watched some videos and read some things and I think I have a grasp as to what to do with the validation part of the processquote(). I also think I understand what I can do with the bottom part of the function to, but the middle area where I do a number of queries and some other logic I can't seem to grasp how to break that out into other classes or methods. Could anyone just give me a quick concept of how you would possibly break out this part of the code. I totally understand that it won't be anything real accurate, I'm just looking for an example of logic behind it. $now = time(); $units_text = "Prices include all parts and labor:\r\n".$email_units; $where = ''; $date_sent = ''; $date_modified = NULL; // INSERT/UPDATE QUOTE_RESPONSES $params = [ 'request_id' => [$q_id, 'INT'], 'date_modified' => NULL, 'body' => $ebody, 'code' => $code, 'notes' => $notes, 'unit_pricing' => $units_text ]; if($i->get('action') == "add") { $params['code'] = randomCode(20); $code = $params['code']; $set = $this->db->insert(QUOTE_RESPONSES, $params); } elseif($i->get('action') == "edit") { $params['date_modified'] = date("Y-m-d H:i:s"); $set = $this->db->update(QUOTE_RESPONSES, $params, '`id` = '.$resp_id, 1); } $last_id = ($i->get('action') == "add") ? $set->lastInsertId() : $resp_id; ///////////// END /////////////////////////////////// // UPDATE REFERRALS if($i->get('action') == "add") { (new QuoteReferral)->setQuoteId($last_id, $q_id); } //////////// END ////////////////////// // Clear QUOTE_ITEMS if($i->get('action') == "edit") { $qi->deleteQuoteItems($resp_id); } /////////// END ////////////////////// // UPDATE QUOTE_REQUESTS with posted vehicle info. $params = [ 'vehicle_make_id' => [$make_id, 'INT'], 'vehicle_model_id' => [$model_id, 'INT'], 'vehicle_year_id' => [$year, 'INT'], 'vehicle_sufix' => $car_sufix ]; (new QuoteRequest)->updateById($params, $q_id); ///////// END ////////////////////////////////////////// // SET new QUOTE_ITEMS foreach($unit as $key => $val) { $params = []; if(!empty($val['price'])) { $note = (!empty($val['note'])) ? sanitize($val['note']) : ''; $unit_price = addSalesTax($val['price'], Config::get('tax_rate')); $add_amt = ($val['on_sale'] == TRUE) ? (int)$val['price'] - (int)$val['sale_price'] : (int)$val['price'] - (int)$val['original_price']; $params = [ 'item' => $key, 'quote_price' => [$val['price'], 'INT'], 'response_id' => [$last_id, 'INT'], 'product_id' => [$val['product_id'], 'INT'], 'item_note' => $note, 'add_amt' => [$add_amt, 'INT'] ]; $qi->insertQuoteItems($params); } } ////////// END /////////////////////////////// if($i->get('action') == "add") { $link_url = 'http://remotelystartedmn.com/quotes.php?quote-id='.$last_id.'&c='.$code.'&direct'; $email_link_url = $link_url.'&e=1'; $set = $this->db->update(QUOTE_RESPONSES, [/*'signature' => $signature, */'quote_link' => $email_link_url], '`id`= '.$last_id); $qid = $i->get('quote-id', '', 'int'); (new QuoteRequest)->updateResponseType($qid);
  8. Thank you. I watched the video and will do plenty of research and playing to see what I can come up with.
  9. I fully agree citypaul. There is a tremendous amount of code that is intertwined. Much of this was written a few years ago while I was still learning mainstream php and have adapted it to better and better practices over the time, but I have always known that it's far from perfect. I fully understand this is procedural code, especially since I literally took a bunch of functions and placed them into a class, simply to try and organize them and maybe it would have just been better to make more organized function pages than classes that aren't really classes. I really really want to improve this code as I expect to expand it immensely in the future and I want it to be easier and more efficient when doing so. I believe I have the ability to make this better, but I think my main struggle in figuring out how to break this apart is dealing with the validation and then building the output desired without passing a ton of things back and forth amongst several classes that again probably don't have anything to do with each other. If I could get even a basic example based on my code of how to break it apart, that would likely help a ton.
  10. Sure. It gets called after submitting a form with in the admin area. I will only post the relevant code, the rest of the code just contains the setup of the form. if(Input::noVal('quote-id|g') && Input::noVal('response-id|g')) { redirect(Config::get('admin_redirect_page')); } elseif(Input::exists('submit|p') && Input::exists('action|g') && in_array(Input::val('action|g'), array("add", "edit"))) { $results = $qResponse->processQuote(); } elseif(Input::exists('quote-id|g') && Input::val('action|g') == "add") {$results = $qRequest->selectQuoteRequest()->results();} elseif(Input::exists('response-id|g') && Input::val('action|g') == "edit") {$results = $qResponse->selectResponse(Input::val('response-id|g'), TRUE);} $check_num = ''; if(Input::noVal('response-id|g') && Input::notExists('submit|p')) { $check = DB::getInstance()->query("SELECT `id` FROM `".QUOTE_RESPONSES."` WHERE `request_id` = ".(int)Input::val('quote-id|g')); if($check_num = $check->rowCount() > 0) { echo formComplete('A Quote has already been made for this request.', TRUE); } } if(!empty($results) && empty($check_num)) { The page that holds this code is not in a class, it's just an admin area viewing/posting page. This is the whole page, just in case you want more, but the code above is where the processquote() is. This code is an include file with in a wrapped admin area. So whatever happens on this page will display or happen within a predefined div within the page, so it can't/won't effect the rest of the admin area, like menus or manipulation of the page around it. <?php if(!defined('body_id')){ header("Location: /404.php"); exit; } $qRequest = new QuoteRequest; $qResponse = new QuoteResponse; /*if(Input::exists('update|p')) { $qRequest->changeResponseType(QUOTE_REQUESTS); echo formComplete("Emailed Updated", TRUE); } else*/if(empty(Input::super('post')) && Input::notExists('action|g')) { $results = $qRequest->allQuoteRequests($start)->results(); if(!empty($results)) {nexPrevStandardAdmin(end($results), Config::get('quote_requests_per_page'));} ?> <form action="" method="post"> <!--<div class="right"><?php //if(!empty($results)){echo '<input name="update" type="submit" value="Update Emailed" />';} ?></div>--> <table id="admin_table" cellpadding="4" class="admin-tbl"> <tr> <?php $th = array("Name", "Vehicle", "Date", "ID#", "Read", "Actions"); echo adminThList($th); ?> </tr> <?php if(empty($results)){} else { foreach($results as $r) { //print_r($r); if(!is_array($r)){} else { $already_quoted=''; $has_read=''; $name = (empty($r['response'])) ? '<span style="color: #FF0000">'.$r['name'].'</span>' : $r['name']; /*if(empty($r['response_id']) && $r['already_quoted'] > 0) { $already_quoted = 'style="background: yellow"'; }*/ if($r['email'] == Config::get('no_email')) { $has_read = NO_EMAIL_ICON; } elseif($r['viewed_by_email'] == FALSE && $r['viewed_by_txt'] == FALSE && $r['read_quote'] == TRUE) { $has_read = CHECK_MARK; } elseif($r['viewed_by_email'] == FALSE && $r['viewed_by_txt'] == FALSE && $r['read_quote'] == FALSE && empty($r['response_id'])) {} elseif($r['viewed_by_email'] == FALSE && $r['viewed_by_txt'] == FALSE && $r['read_quote'] == FALSE) { $has_read = RED_X; } else { $has_read .= ($r['viewed_by_email'] == TRUE) ? ENVELOPE_ICON : ''; $has_read .= ($r['viewed_by_txt'] == TRUE) ? SMS_ICON : ''; } $icon_spacing = ' '; // Used to mark quotes are emailed, keeping just in case need it later. //<input type="checkbox" name="iemailed['.$r['id'].']" value="'.$r['id'].'"> echo '<tr> <td style="max-width:150px">'.adminLinks('qsearch', 'tbl_field=Name&srch=Search&searched='.$r['name'], '', $name).'</td> <td '.$already_quoted.'>'.adminLinks('qsearch', 'tbl_field=Vehicle&srch=Search&searched='.$r['actual_vehicle'], '', $r['actual_vehicle']).'</td> <td class="center">', date("m-d-y", $r['date_sent']), '</td> <td class="center">', (!empty($r['response_id'])) ? adminLinks('sresponse', 'quote-id='.$r['response_id'], 'view', $r['response_id']) : '', (!empty($r['response_id']) && $r['quote_active'] == FALSE) ? '<br>'.RED_X : '', '</td> <td class="center">'.$has_read.'</td> <td class="center icon-spacing">', (empty($r['response_id']) && $r['response'] != "Emailed") ? '' : (($r['response'] == "Emailed") ? EMAILED_ICON : ''), (empty($r['response_id'])) ? adminLinks('', 'quote-id='.$r['id'], 'add', ADD_QUOTE_ICON) : '' /*adminLinks('', 'quote-id='.$r['id'], 'view', Q_INFO_ICON)*/, (!empty($r['response_id']) && empty($r['deposit_id'])) ? adminLinks('', 'response-id='.$r['response_id'], 'edit', UPDATE_Q_ICON) : '', (!empty($r['response_id']) && empty($r['deposit_id'])) ? adminLinks('sdeposit', 'quote-id='.$r['response_id'], 'add', DEPOSIT_ICON) : ((!empty($r['deposit_id'])) ? DEPOSIT_MADE_ICON : ''), (empty($r['response_id'])) ? adminLinks('', 'quote-id='.$r['id'], 'delete', GARBAGE): '', '</td>'; echo adminExtendedDisplay($r); echo '</tr>'; } } } ?> </table> </form> <?php } elseif(Input::val('action|g') == "view") { $results = $qRequest->selectQuoteRequest()->results(); $nodisplay = array('id', 'response', 'date_sent', 'signature', 'read_quote', 'purchased', 'body', 'notes', 'unit_pricing', 'code', 'request_id', 'vehicle_make_id', 'vehicle_model_id' , 'vehicle_year_id'); $html=''; foreach($results as $key => $val) { if(!in_array($key, $nodisplay)) { if($key == "city" && !empty($val)) { $html .= ucwords($key).' = '.getCityNameAndState($val).'<br>'; } elseif($key == "key_id" && !empty($val)) { $img_loc_string = getKeyImages($val); $html .= '<img src="'.IMAGE_LAY_SITE.$img_loc_string[0]['image'].'"><br>'; } elseif($key == "options") { $html .= nl2br(ucwords($val)); } else { if($val == "Push To Start"){ $val = '<span class="bold">'.$val.'</span>'; } elseif($val == "Manual"){ $val = '<span class="bold">'.$val.'</span>'; } elseif($val == "Turn A Knob"){ $val = '<span class="bold">'.$val.'</span>'; } $html .= ucwords($key).' = '.$val.'<br>'; } } } echo '<h1>Original Request</h1>'.$html; } elseif(Input::val('action|g') == "delete") { if(Input::exists('delete|p')) { if($qRequest->deleteRequest() === TRUE) {echo formComplete("Quote Request Deleted", TRUE);} } elseif(Input::exists('quote-id|g')) { $results = $qRequest->selectQuoteRequest()->results(); $form_fields = array( array("tag" => array("function", "class=\"bold\""), "text" => "name:", "name" => "name", "class_fields" => FALSE, "type" => "text", "required" => FALSE, "value_results_name" => "name", "admin_notes" => FALSE, "options" => array(), "function" => $results['name'] ), array("tag" => array("function", "class=\"bold\""), "text" => "vehicle:", "name" => "vehicle", "class_fields" => FALSE, "type" => "text", "required" => FALSE, "value_results_name" => "vehicle", "admin_notes" => FALSE, "options" => array(), "function" => $results['actual vehicle'] ), array("tag" => array("function", "class=\"bold\""), "text" => "date sent:", "name" => "date_sent", "class_fields" => FALSE, "type" => "text", "required" => FALSE, "value_results_name" => "date_sent", "admin_notes" => FALSE, "options" => array(), "function" => date("m-d-Y", $results['date_sent']) ), "form_button" => array("name" => "delete", "type" => "submit", "value" => "delete", "attributes" => "") ); adminForm($form_fields, (isset($results)) ? $results: ''); } } else { if(Input::noVal('quote-id|g') && Input::noVal('response-id|g')) { redirect(Config::get('admin_redirect_page')); } elseif(Input::exists('submit|p') && Input::exists('action|g') && in_array(Input::val('action|g'), array("add", "edit"))) { $results = $qResponse->processQuote(); } elseif(Input::exists('quote-id|g') && Input::val('action|g') == "add") {$results = $qRequest->selectQuoteRequest()->results();} elseif(Input::exists('response-id|g') && Input::val('action|g') == "edit") {$results = $qResponse->selectResponse(Input::val('response-id|g'), TRUE);} $check_num = ''; if(Input::noVal('response-id|g') && Input::notExists('submit|p')) { $check = DB::getInstance()->query("SELECT `id` FROM `".QUOTE_RESPONSES."` WHERE `request_id` = ".(int)Input::val('quote-id|g')); if($check_num = $check->rowCount() > 0) { echo formComplete('A Quote has already been made for this request.', TRUE); } } if(!empty($results) && empty($check_num)) { ?> <div id="admin-form" class="form-bkgnd"> <div id="original-request" style="padding-left: 6px;"> <?php if(Input::notExists('submit|p')) { $nodisplay = array('id', 'quote_active', 'request_active', 'response', 'date_sent', 'signature', 'read_quote', 'purchased', 'body', 'notes', 'unit_pricing', 'code', 'request_id', 'vehicle_make_id', 'vehicle_model_id', 'vehicle_year_id'); $html='<div id="request-info-left">'; $car_addition=''; $display_count = 0; foreach($results as $key => $val) { if(!in_array($key, $nodisplay)) { if($key == "city" && !empty($val)) { $html .= ucwords($key).' = '.getCityNameAndState($val).'<br>'; } elseif($key == "key_id" && !empty($val)) { $img_loc_string = getKeyImages($val); $html .= '<img src="'.IMAGE_LAY_SITE.$img_loc_string[0]['image'].'"><br>'; } elseif($key == 'key_image_upload' && !empty($val)) { $html .= '<a href="'.PLUGINS_QUOTES.'serve-key-image.php?image='.$val.'" target="_blank"> <img src="'.PLUGINS_QUOTES.'serve-key-image.php?image='.$val.'" class="key-image-upload-admin"> Click To Enlarge</a><br>'; } elseif($key == "options") { $html .= nl2br(ucwords($val)); } elseif(empty($val)) { $html .= ucwords($key).' = '.$val.'<br>'; } else/*if($key == "key_type")*/ { if($val == "Push To Start") { if(Input::val('action|g') != "edit") { $car_addition .= ' PTS'; } $val = '<span class="bold">'.$val.'</span>'; } elseif($val == "Manual") { if(Input::val('action|g') != "edit") { $car_addition .= ' Manual Trans'; } $val = '<span class="bold">'.$val.'</span>'; } elseif($val == "Turn A Knob") { if(Input::val('action|g') != "edit") { $car_addition .= ' Intellikey'; } $val = '<span class="bold">'.$val.'</span>'; } elseif($val == "Hybrid" || $val == "Diesel") { if(Input::val('action|g') != "edit") { $car_addition .= ' '.$val; } $val = '<span class="bold">'.$val.'</span>'; } /*elseif($key == '40bit' || $key == '80bit') { $car_addition .= $key; }*/ $html .= ucwords($key).' = '.$val.'<br>'; } //else{ $html .= ucwords($key).' = '.$val.'<br>'; } $display_count++; if($display_count == 9) { $html .= '</div><div id="request-info-right">'; } } } $html .= '</div><div class="clear"></div>'; $_SESSION['quote_original_info'] = $html; $html=''; } echo (isset($_SESSION['quote_original_info'])) ? $_SESSION['quote_original_info'] : ''; ?> </div><br> <?php echo (Input::hasVal('quote-id|g')) ? '<button onclick="window.location.href=\'/a.php?menu=Quotes&admin_page=quotes_send_email&action=add&quote-id='.(int)Input::val('quote-id|g').'\'">Email Client</button><br><br>' : ''; ?> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">Your car does require a bypass module for the chip in the key.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">The price will include keyless entry and trunk pop on the new remotes so you can retain those functions while the car is remote started.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">The keyless entry is included FREE of charge on your vehicle and is a $20 value.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">The trunk pop is included FREE of charge on your vehicle and is a $20 value.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">You will need to give up a key for the install. Meaning you would arrive with 2 keys and leave with 1 key in hand. The other key would be hidden permanently in the dash. If you need/want to have more than 1 key after the install, it is suggested to have an additional key cut and programmed by a locksmith or dealership before the install is performed.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">Great news, your car does not require any additional parts or labor when utilizing the Direct Fit kits.</span><br><br> <button class="copy-span">Copy To Email</button><span class="copy-to-textarea">Your factory remote key will still operate as it does now and will still be used to unlock the doors.</span><br><br> <!--<script type="text/javascript" src="scripts/jscripts/tiny_mce/tiny_mce.js"></script> <script type="text/javascript" src="scripts/textarea-mce.js"></script> --> <?php /*if(isset($drone)){ echo '<div id="drone_notes"><span class="bold">DroneMobile Notes:</span> <br>Make sure to check if the bypass being used will support Telematics Gateway when using the DroneMobile.</div>'; } */ //$car_make = explode(" ", $results['vehicle']); $car_model = stripKeyTypeFromName($results['vehicle_model_name']); $get_notes = adminVehicleNotes($results['vehicle_make_id']); echo (!empty($get_notes)) ? '<div id="car_notes"><span class="bold">'.$results['vehicle_make_name'].' Notes</span><br>'. nl2br(preg_replace("/\w*?".preg_quote($car_model)."\w*/i", '<span class="highlight-purple">$0</span>', $get_notes['notes'])).'</div>' : ''; if(Input::notExists('submit|p') && Input::exists('response-id|g')) { $_SESSION['units_requested'] = $results['units'] = explode(", ", $results['units']); } elseif(Input::notExists('submit|p') /*&& !isset($_GET['response-id'])*/) { $_SESSION['units_requested'] = explode(", ", $results['units']); } /*$units = (isset($results['units']) && !is_array($results['units'])) ? explode(", ", $results['units']) : ((isset($results['units'])) ? $results['units'] : '');*/ $quote_items = (Input::exists('response-id|g') && Input::val('action|g') == "edit" && Input::notExists('submit|p')) ? (new QuoteItems)->selectQuoteItems()->results() : array(); $num = 1; foreach(allUnits("(`".CATEGORIES."`.`cat_name` = 'Two Way Remotes' OR `".CATEGORIES."`.`cat_name` = 'One Way Remotes' OR `".CATEGORIES."`.`cat_name` = 'Make Specific Models' OR `".CATEGORIES."`.`cat_name` = 'Custom Packages')", "`".CATEGORIES."`.`cat_name`, `".PRODUCTS."`.`prod_name`, `".PRODUCTS."`.`price` ASC") as $u) { if(!empty($quote_items)) { foreach($quote_items as $key => $val) { if($val['product_id'] == $u['id']) { $results['units'][$u['prod_name']]['price'] = $val['quote_price']; $results['units'][$u['prod_name']]['note'] = $val['item_note']; } } } $html = '<div><label>';// Open wrap div $html .= (in_array($u['prod_name'], $_SESSION['units_requested'])) ? '<span class="bold">'.$u['prod_name'].'</span>' : $u['prod_name']; $html .= (isOnSale($u['sp_start'], $u['sp_end']) === TRUE) ? ' <span class="on-sale" id="price-'.$num.'">'.$u['sp_price'].'</span>' : ' <span id="price-'.$num.'">'.$u['price'].'</span>'; $html .= '<img class="expand-symbol expand" data-expand-id="'.$num.'" src="'.EXPAND_SYMBOL.'"></label><input name="units['.$u['prod_name'].'][price]" type="text" value="'; $html .= (isset($results['units'][$u['prod_name']]['price'])) ? $results['units'][$u['prod_name']]['price'] : ''; $html .= '" style="width: 40px;" id="prod-expand-'.$num.'"><input name="units['.$u['prod_name'].'][note]" type="text" value="'; $html .= (isset($results['units'][$u['prod_name']]['note'])) ? $results['units'][$u['prod_name']]['note'] : ''; $html .= '" style="width: 400px;">'; $html .= '<input name="units['.$u['prod_name'].'][product_id]" type="hidden" value="'; $html .= (isset($results['units'][$u['prod_name']]['product_id'])) ? $results['units'][$u['prod_name']]['product_id'] : $u['id']; $html .= '">'; $html .= '<input name="units['.$u['prod_name'].'][original_price]" type="hidden" value="'.$u['price'].'">'; $html .= '<input name="units['.$u['prod_name'].'][sale_price]" type="hidden" value="'.$u['sp_price'].'">'; $html .= '<input name="units['.$u['prod_name'].'][on_sale]" type="hidden" value="'; $html .= (isOnSale($u['sp_start'], $u['sp_end']) === TRUE) ? 1 : 0; $html .= '">'; $html .= '<div id="expand_'.$num.'" class="item-option-expand">'; foreach(Config::get('expand_options') as $eo => $eo_val) { $html .= '<input type="checkbox" value="'.$eo_val.'" class="expand_value" data-ex-id="'.$num.'">'.$eo.' '; } $html .= '</div></div>';// Close expand and wrap divs $html_array[] = $html; $num++; } $output = uList($html_array, "unit-list"); $html_array=''; $html=''; /*foreach(allUnits("`".PRODUCTS."`.`Bypass Modules`=1") as $b) { $html[] = '<input type="radio" name="bypass" value="'.$b['prod_name'].'"> '.$b['prod_name']; } */ /*$byp = allUnits("`".PRODUCTS."`.`Bypass Modules`=1"); $bypasses[] = ''; foreach($byp as $p) { $bypasses[] = $p['prod_name']; } */ //$results['signature'] = (isset($results['signature'])) ? $results['signature'] : $signature; $results['email_body'] = (Input::val('action|g') == "edit" && Input::notExists('submit|p')) ? $results['body'] : ((isset($results['email_body'])) ? $results['email_body'] : ''); $results['vehicle_sufix'] = (Input::val('action|g') == "add" && empty($results['vehicle_sufix'])) ? trim($car_addition) : $results['vehicle_sufix']; //$results['vehicle'] = (isset($results['vehicle'])) ? str_replace(array(' (standard key)', ' (push-to-start)'), '', $results['vehicle']) : ''; require_once(ROOT.PLUGINS_QUOTES.'admin_vehicle_select.php'); $form_fields = array( array("tag" => array("label"), "text" => "name:", "name" => "name", "class_fields" => TRUE, "type" => "text", "required" => TRUE, "value_results_name" => "name", "admin_notes" => FALSE, "options" => array("input_op" => 'maxlength="45"'), ), array("tag" => array("function"), "text" => "vehicle:", "name" => "vehicle", "class_fields" => TRUE, "type" => "text", "required" => TRUE, "value_results_name" => "vehicle", "admin_notes" => FALSE, "options" => array(), "function" => $vhtml ), array("tag" => array("label"), "text" => "vehicle sufix:", "name" => "vehicle_sufix", "class_fields" => TRUE, "type" => "text", "required" => FALSE, "value_results_name" => "vehicle_sufix", "admin_notes" => FALSE, "options" => array("input_op" => 'maxlength="100"'), ), array("tag" => array("label"), "text" => "email body:", "name" => "email_body", "class_fields" => TRUE, "type" => "textarea", "required" => TRUE, "value_results_name" => "email_body", "admin_notes" => FALSE, "options" => array("input_op" => 'style="width: 600px; height: 200px;"'), ), array("tag" => array("function"), "text" => "available units:", "name" => "", "class_fields" => TRUE, "type" => "text", "required" => FALSE, "value_results_name" => "", "admin_notes" => FALSE, "options" => array(), "function" => $output ), /*array("tag" => array("function"), "text" => "Bypass Used:", "name" => "", "class_fields" => TRUE, "type" => "text", "required" => FALSE, "value_results_name" => "", "admin_notes" => FALSE, "options" => array(), "function" => selectBox('bypass', $bypasses, (isset($results['bypass'])) ? $results['bypass'] : '', 'val', TRUE) ), */ array("tag" => array("label"), "text" => "notes:", "name" => "notes", "class_fields" => TRUE, "type" => "textarea", "required" => FALSE, "value_results_name" => "notes", "admin_notes" => FALSE, "options" => array(), ), /*array("tag" => array("label"), "text" => "signature:", "name" => "signature", "class_fields" => TRUE, "type" => "textarea", "required" => FALSE, "value_results_name" => "signature", "admin_notes" => FALSE, "options" => array("input_op" => 'style="width: 600px;"'), ),*/ "hiddens" => array("email" => (isset($results['email'])) ? $results['email'] : '', "code" => (isset($results['code'])) ? $results['code'] : '', "quote_id" => (isset($results['quote_id'])) ? $results['quote_id'] : Input::val('quote-id|g'), "send_sms" => (isset($results['send_sms'])) ? $results['send_sms'] : '', "phone" => (isset($results['phone'])) ? $results['phone'] : '', "vehicle_make_name" => (isset($results['vehicle_make_name'])) ? $results['vehicle_make_name'] : '', "vehicle_model_name" => (isset($results['vehicle_model_name'])) ? $results['vehicle_model_name'] : ''), "form_button" => array("name" => "submit", "type" => "submit", "value" => "submit", "attributes" => "") ); adminForm($form_fields, (isset($results)) ? $results : '', 'response-form'); ?> </div> <script> $(document).ready(function(){ $('.expand-symbol').on('click', function(){ var num = $(this).data('expand-id'); $('#expand_'+num).slideToggle(); }); $('.expand_value').on('click', function(){ var value = parseInt($(this).val()); var expand_id = $(this).data('ex-id'); var price_input = $('#prod-expand-'+expand_id); if($(price_input).val() == ''){ var price= parseInt($('#price-'+expand_id).text()); } else{ var price = parseInt($(price_input).val()); } if($(this).prop('checked')){ var new_price = price + value; } else{ var new_price = price - value; } $(price_input).val(new_price); }); $('.copy-span').on('click', function(){ var text = $(this).next('span').text() + "\r\n\r\n", old_text = $("textarea[name='email_body']").val(); $("textarea[name='email_body']").val(old_text + text); }); }); </script> <span> Confirmed Cars where factory keyless works while running:<br> 2011 Rogue standard key<br> 2007 Explorer<br> 2004 Sentra<br> 2010 Focus<br> 2003 Murano<br> 2003 Ranger<br> 2005 Altima<br> 1999 Cherokee<br> 2005 Sierra<br> 2010 Mazda 3 Flip-key<br> 2010 Mazda 6 Flip-key<br> 2008 Outback w/Remote key<br> All Toyota Remote Keys<br> All Nissan Push-to-Start and Intellikey style<br> All Fords with remote keys<br> </span><br> <span> Cars that the factory keyless DOES NOT work while running:<br> All Hondas<br> All Hyundai/Kia except select PTS versions<br> Most 2002-older Fords<br> Mazda Intellikey<br> </span> <?php $docs = getDocs("admin_files"); ?> <br> <table cellpadding="6" id="admin_table" class="admin-tbl hide"> <tr> <th>Folder / Files</th> <th>Relative Path</th> </tr> <?php $td = "gray-td"; foreach($docs as $doc => $val) { echo '<tr class="'.$td.'"><td colspan="2">'.FOLDER.' '.$doc; unset($val[0], $val[1]); if(!isset($val[2])) {echo ' - Folder is empty</td></tr>';} else {echo '</td></tr>';} foreach($val as $v) {echo '<tr><td class="indent">'.$v.'</td> <td>admin_files/'.$doc.'/'.$v.'</td> </tr>';} } ?> </table> <?php } } ?>
  11. The QuoteResponse in my mind was a class that deals with anything that had to do with the response of the quote request. I agree with the breaking out the validation, but I haven't been able to figure out a way to do that universally among the classes and still achieve the validation I want. I've looked at validation type classes and didn't feel they offer much of a better solution cause it's still repeating code within the class method to setup everything. Could you do a quick example of break out classes or methods to make the processquote() "better", doesn't have to actually function, just parts you would move out to other areas.
  12. So I'm fairly confident that I understand the idea of having a class with minimal responsibility but I struggle with concept of having tons of little classes instead of a few larger ones that encompass more responsibility. Just seems a bit silly to break it down into several classes when it could be just one. I had 2 function pages that held a few dozen regular functions that all relate to a specific aspect of my site, hence why they were grouped among these 2 pages. I am trying to organize them into classes and make it easier to expand in the future and eliminate duplicate code from the functions, like always setting $db = DB::getInstance(); to be able to use my db class. So now I have 13 new classes with functions that relate to the class. I think that is a good start, but I feel like it's not enough, or not enough in the proper direction of how a class should act. Here is a sample of a new class. Can you take a look at it and give advice on how you might change or extract its responsibility to an additional class/es, or if it's just fie the way it is. There are a few functions in these classes that I'm really not sure how to split apart any more, simply cause they are form processing functions that validate, set errors, return messages, email and do db stuff. But I have classes in those functions that are already doing things separately and the flow of logic would be hard to break apart and maintain the functions goal of form processing quickly and efficiently in one spot. QuoteResponse.class.php <?php class QuoteResponse extends QuoteSystem { public function __construct() { parent::__construct(); } public function verifyReferralCode($ref_code) { return $this->db->query("SELECT COUNT(`id`) FROM `".QUOTE_RESPONSES."` WHERE `id` = {$ref_code}"); } public function checkQuoteExists($q_id) { return $this->db->query("SELECT `id` FROM `".QUOTE_RESPONSES."` WHERE `request_id` = ".$q_id); } // Gets info for the given quote-id and c code for a client view public function getQuote() { $id = (int)Input::val('quote-id|g'); $code = sanitize(Input::val('c|g')); $get = $this->db->prepare("SELECT `".QUOTE_RESPONSES."`.*, `".QUOTE_ITEMS."`.*, `".PRODUCTS."`.*, `".QUOTE_DEPOSITS."`.`id` AS `deposit_id`, `".QUOTE_DEPOSITS."`.`product_id` AS `deposit_prod`, `".QUOTE_DEP_RESP."`.`id` as `dep_resp_id`, `".QUOTE_REQUESTS."`.`cookie_code`, `".QUOTE_REQUESTS."`.`id` as `orig_quote_id`, ".CONCAT_VEHICLE." AS `vehicle`, `".QUOTE_REQUESTS."`.`vehicle_sufix`, `".QUOTE_REQUESTS."`.`name`, `".SCH."`.`schedule_id`, `".SCH."`.`install_time`, `".SCH."`.`cancelled` FROM `".QUOTE_RESPONSES."` INNER JOIN `".QUOTE_ITEMS."` ON `".QUOTE_ITEMS."`.`response_id` = `".QUOTE_RESPONSES."`.`id` INNER JOIN `".PRODUCTS."` ON `".PRODUCTS."`.`id` = `".QUOTE_ITEMS."`.`product_id` INNER JOIN `".QUOTE_REQUESTS."` ON `".QUOTE_REQUESTS."`.`id` = `".QUOTE_RESPONSES."`.`request_id` ".VEHICLE_JOIN." LEFT JOIN `".QUOTE_DEPOSITS."` ON `".QUOTE_DEPOSITS."`.`q_id` = `".QUOTE_RESPONSES."`.`id` LEFT JOIN `".QUOTE_DEP_RESP."` ON `".QUOTE_DEP_RESP."`.`deposit_id` = `".QUOTE_DEPOSITS."`.`id` LEFT JOIN `".SCH."` ON `".SCH."`.`deposit_id` = `".QUOTE_DEPOSITS."`.`id` WHERE `".QUOTE_RESPONSES."`.`id`=$id AND `code`= ?"); $get->execute(array($code)); return $get->fetchAll(); } // Validates the quote public function processQuote() { //diagDiv($_POST); $qi = new QuoteItems; $i = new Input; $resp_id = $i->get('response-id', '', 'int'); $q_id = $i->post('quote_id', '', 'int'); $name = $i->post('name', TRUE); $car_name = $i->post('vehicle_make_name', TRUE); $car_model = $i->post('vehicle_model_name', TRUE); $make_id = $i->post('make_id', '', 'int'); $model_id = $i->post('model_id', '', 'int'); $year = $i->post('year', '', 'int'); $car_sufix = $i->post('vehicle_sufix', TRUE); $ebody = $i->post('email_body', TRUE); $sig = $i->post('signature'); $unit = $i->post('units'); $notes = $i->post('notes', TRUE); $email = $i->post('email', TRUE); $code = $i->post('code', TRUE); $sms = ($i->post('send_sms', '', 'int') == 1) ? TRUE : FALSE; $phone = $i->post('phone', TRUE); //$bypass = (isset($_POST['bypass'])) ? sanitize($_POST['bypass']) : ''; $fields = array('name' => $name, 'vehicle_make_name' => $car_name, 'vehicle_model_name' => $car_model, 'vehicle_sufix' => $car_sufix, 'email_body' => $ebody, 'signature' => $sig, 'units' => $unit, 'notes' => $notes, 'email' => $email, "code" => $code, "quote_id" => $q_id, 'send_sms' => $sms, 'phone' => $phone, 'vehicle_make_id' => $make_id, 'vehicle_model_id' => $model_id, 'vehicle_year_id' => $year); $notes = escape($notes); $required = array("name", "email_body", "email", "make_id", "model_id", "year"); requiredFields($i->all('post'), $required); if(empty($resp_id)) { $check = $this->checkQuoteExists($q_id); if($check->rowCount() > 0) { Errors::set('A Quote has already been made for this request.'); } } if(Errors::has()){} else { nameLength($name, 2, 45); //maxStringLength($car, 100, 'The vehicle cannot exceed 100 characters.'); minStringLength($ebody, 2, 'The email body must be at least 2 characters in length.'); //minStringLength($sig, 2, 'The signature must be at least 2 characters in length.'); validEmail($email); $email_units=''; foreach($unit as $key => $val) { if(!empty($val['price'])) { $diff = $val['original_price'] - $val['sale_price']; $email_units .= $key.' - $'.number_format($val['price'], 2); $email_units .= ($val['on_sale'] == TRUE) ? ' (while on sale, add $'.$diff.' after sale ends)' : ''; $email_units .= ' +tax'; $email_units .= (!empty($val['note'])) ? " (".$val['note'].")\r\n" : "\r\n"; } } if(empty($email_units)) { Errors::set('Please select products for the quote.'); } } if(Errors::has()) { echo Errors::output(); } else { $now = time(); $units_text = "Prices include all parts and labor:\r\n".$email_units; $where = ''; $date_sent = ''; $date_modified = NULL; // INSERT/UPDATE QUOTE_RESPONSES $params = [ 'request_id' => [$q_id, 'INT'], /*'name' => $name,*/ /*'vehicle' => $car,*/ /*'vehicle_sufix' => $car_sufix,*/ 'date_modified' => NULL, 'body' => $ebody, //'signature' => $sig, 'code' => $code, 'notes' => $notes, 'unit_pricing' => $units_text ]; if($i->get('action') == "add") { $params['code'] = randomCode(20); $code = $params['code']; $set = $this->db->insert(QUOTE_RESPONSES, $params); } elseif($i->get('action') == "edit") { $params['date_modified'] = date("Y-m-d H:i:s"); $set = $this->db->update(QUOTE_RESPONSES, $params, '`id` = '.$resp_id, 1); } $last_id = ($i->get('action') == "add") ? $set->lastInsertId() : $resp_id; ///////////// END /////////////////////////////////// // UPDATE REFERRALS if($i->get('action') == "add") { (new QuoteReferral)->setQuoteId($last_id, $q_id); } //////////// END ////////////////////// // Clear QUOTE_ITEMS if($i->get('action') == "edit") { $qi->deleteQuoteItems($resp_id); } /////////// END ////////////////////// // UPDATE QUOTE_REQUESTS with posted vehicle info. $params = [ 'vehicle_make_id' => [$make_id, 'INT'], 'vehicle_model_id' => [$model_id, 'INT'], 'vehicle_year_id' => [$year, 'INT'], 'vehicle_sufix' => $car_sufix ]; (new QuoteRequest)->updateById($params, $q_id); ///////// END ////////////////////////////////////////// // SET new QUOTE_ITEMS foreach($unit as $key => $val) { $params = []; if(!empty($val['price'])) { $note = (!empty($val['note'])) ? sanitize($val['note']) : ''; $unit_price = addSalesTax($val['price'], Config::get('tax_rate')); $add_amt = ($val['on_sale'] == TRUE) ? (int)$val['price'] - (int)$val['sale_price'] : (int)$val['price'] - (int)$val['original_price']; $params = [ 'item' => $key, 'quote_price' => [$val['price'], 'INT'], 'response_id' => [$last_id, 'INT'], 'product_id' => [$val['product_id'], 'INT'], 'item_note' => $note, 'add_amt' => [$add_amt, 'INT'] ]; $qi->insertQuoteItems($params); } } ////////// END /////////////////////////////// if($i->get('action') == "add") { // Build Email to customer and admin // OLD EMAIL FORMAT ////////////////////////////////////////////////////////////////// /*$ebody .= $units_text; $link = "If this link is not clickable please copy and paste it into your browser address bar to confirm you have received your quote and to make your deposit.\r\n"; $link_url = 'http://remotelystartedmn.com/quotes.php?quote-id='.$last_id.'&c='.$code; $sig .= "\r\n\r\n".$link.$link_url.Config::get('quote_signature_part2'); */ ////////////////////////////////////////////////////////////////////////////////////// // OLD Signature storage, now signature is built in the composeQuote() /*$link = "Please visit the link below to see your pricing options. If the link is not clickable please copy and paste it into your browser address bar.\r\n"; $link_url = 'http://remotelystartedmn.com/quotes.php?quote-id='.$last_id.'&c='.$code; $email_link_url = $link_url.'&e=1'; $signature = $link.$email_link_url."\r\n\r\n".$sig.Config::get('quote_signature_part2');*/ $link_url = 'http://remotelystartedmn.com/quotes.php?quote-id='.$last_id.'&c='.$code.'&direct'; $email_link_url = $link_url.'&e=1'; //$body = 'Hello '.$name.','; //$body .= "\r\n".$ebody."\r\n".$sig; // <--- OLD EMAIL FORMAT // //$body .= "\r\n".$ebody."\r\n".$signature.thanksSignature(); $set = $this->db->update(QUOTE_RESPONSES, [/*'signature' => $signature, */'quote_link' => $email_link_url], '`id`= '.$last_id); //$set->execute(array($sig)); // <--- OLD EMAIL FORMAT // //$set->execute(array($signature)); $qid = $i->get('quote-id', '', 'int'); (new QuoteRequest)->updateResponseType($qid); // Attempt to send the quote email $send = $this->composeQuote($last_id); if($send === TRUE) { $message = 'Email Sent'; $sms_response = TRUE; if($sms === TRUE && !empty($phone)) { $args = array('username' => Config::get('ez_sms_username'), 'password' => Config::get('ez_sms_password'), 'subject' => '', 'message' => "Remote start quote is ready! ".$link_url."&t=1 Reply texts won't be received", 'phone' => $phone); $sms_response = sendSMS($args); $message .= '<br>Text Message Sent'; } if($sms_response === TRUE){ echo formComplete($message, TRUE); } else{ echo 'Text Message Failed:<br>'.$sms_response; } } elseif($send === FALSE) { formErrors(array('Something went wrong.')); } /////////////////////////////////////////////// } elseif($i->get('action') == "edit") { echo formComplete('Quote Updated', TRUE); } unset($_SESSION['quote_original_info']); $fields=''; } return $fields; } // Updates the purchase status for each posted public function changePurchase($tbl) { $key=""; foreach(Input::val('bought|p') as $c[$key] => $value) { $id = (int)$c[$key]; $this->db->query("UPDATE `".$tbl."` SET `purchased` = 1 WHERE `id` = '".$id."'"); if(isset($_POST['miles'][$id]) && $_POST['miles'][$id] > 0) { $miles = (float)$_POST['miles'][$id]; (new MilesDriven)->setMiles($id, $miles); } // Send completed email if(Config::get('send_email_when_completed') === TRUE) { $get = $this->db->query(" SELECT `".QUOTE_REQUESTS."`.`name`, `".QUOTE_REQUESTS."`.`email`, `".QUOTE_REQUESTS."`.`gift_date`, `".QUOTE_REQUESTS."`.`gift_name`, `".QUOTE_REQUESTS."`.`gift_email`, ".CONCAT_VEHICLE." AS `vehicle`, `".QUOTE_REQUESTS."`.`vehicle_sufix`, qr1.video, qr1.screen_shot, qr1.description, qr2.video as `specific_video`, qr2.screen_shot as `specific_screen_shot`, qr2.description as `specific_description`, qr3.video as `non_specific_video`, qr3.screen_shot as `non_specific_screen_shot`, qr3.description as `non_specific_description` FROM `".QUOTE_RESPONSES."` INNER JOIN `".QUOTE_REQUESTS."` ON `".QUOTE_REQUESTS."`.`id` = `".QUOTE_RESPONSES."`.`request_id` INNER JOIN `".QUOTE_DEPOSITS."` ON `".QUOTE_DEPOSITS."`.`q_id` = `".QUOTE_RESPONSES."`.`id` INNER JOIN `".PRODUCTS."` ON `".PRODUCTS."`.`id` = `".QUOTE_DEPOSITS."`.`product_id` ".VEHICLE_JOIN." LEFT JOIN `".VIDEOS."` qr1 ON qr1.`id` = `".PRODUCTS."`.`video_id` LEFT JOIN `".VIDEOS."` qr2 ON qr2.`specific_to` = CONCAT(`".QUOTE_REQUESTS."`.`trans`, ' ', `".QUOTE_REQUESTS."`.`key_type`) LEFT JOIN `".VIDEOS."` qr3 ON qr3.`specific_to` = 'All' WHERE `".QUOTE_RESPONSES."`.`id` = $id ")->fetch(); $videos = []; $body2 = ''; if(!empty($get['video']) || !empty($get['specific_video']) || !empty($get['non_specific_video'])) { $videos[] = [ 'video' => $get['video'], 'desc' => $get['description'], 'shot' => $get['screen_shot'] ]; $videos[] = [ 'video' => $get['specific_video'], 'desc' => $get['specific_description'], 'shot' => $get['specific_screen_shot'] ]; $videos[] = [ 'video' => $get['non_specific_video'], 'desc' => $get['non_specific_description'], 'shot' => $get['non_specific_screen_shot'] ]; $count = 0; foreach($videos as $v) { $count = (!empty($v['video'])) ? $count + 1 : $count + 0; } $video_text = ($count == 1) ? 'a video that has' : $count.' videos that have'; $video_text2 = ($count == 1) ? 'this video is' : 'these videos are'; $body2 = "If you are a first time remote start owner, we understand that it can be confusing learning how to use your remote start. We have provided ".$video_text." valuable information on how to use your remote start. Please understand that ".$video_text2." somewhat generalized to your product and even possibly your car, so it's possible that not all apsects of the video will apply. Please try to remember any specifics we discussed about your install while watching the video and understand that the video may not 100% match the information we discussed. ".ucfirst($video_text2)." provided by the manufacturer as a general guide."; } $body = "Thank you very much for your purchase. Our business thrives on referrals from customers like you. We hope we have gained your trust with our services, so much so that we hope you would refer any friends, family or co-workers our way. We do have a little incentive for you, it's as easy as 123.<br><br>1. Give the Referral Code below to anyone you're sending our way.<br>There is a spot at the bottom of the quote request form to put that number.<br>2. The person you referred makes a purchase.<br>3. We contact you for an address and send you a Target Gift Card as a thank you for referring a customer to us.<br><br>Below is a picture of where to put the referral code. You can show anyone that picture so they know what to look for. Your code can be used as many times as you like, season after season. Each referred purchase gains you a gift card."; // Start building the email template $e = new QuoteEmailTemplate; $data = [ 'name' => $get['name'], 'body' => [$body, TRUE], 'body2' => [$body2, TRUE], 'videos' => [$videos, FALSE], 'referral_id' => $id, 'signature' => thanksSignature(TRUE, TRUE) ]; $e->data($data); $e->load('completed'); $send_html = TRUE; $em_body = $e->getHtmlString(); $em_alt_body = $e->getTextString(); if(Config::get('html_emails') === FALSE) { $send_html = FALSE; $em_body = $em_alt_body; $em_alt_body = ''; } $subject = "Thank you for your purchase at ".Settings::get('site_name'); $diff_ok = (!empty($r['gift_date'])) ? determineDateDiff(TODAY, $r['gift_date'], -1) : FALSE; $send_cc = (Config::get('send_gift_cc_email') === TRUE && !empty($r['gift_email']) && $diff_ok === TRUE) ? TRUE : FALSE; // Setup mailer array $em = array(); $em['body'] = $em_body; $em['alt_body'] = $em_alt_body; $em['subject'] = $subject; $em['to'] = $get['email'] /*SECONDARY_EMAIL*/; $em['to_name'] = $get['name']; $em['smtp'] = FALSE; $em['html'] = $send_html; //echo $reminder_body.'<br>'; //print_r($em); buildPhpMailerEmail($em); if($send_cc === TRUE) { $em = array(); $em['body'] = $em_body; $em['alt_body'] = $em_alt_body; $em['subject'] = $subject; $em['to'] = $get['gift_email'] /*SECONDARY_EMAIL*/; $em['to_name'] = $get['gift_name']; $em['smtp'] = FALSE; $em['html'] = $send_html; buildPhpMailerEmail($em); } } } } // Gets all quotes responses in the db public function allQuoteResponses($start) { $get = $this->db->query("SELECT SQL_CALC_FOUND_ROWS * FROM `".QUOTE_RESPONSES."` ORDER BY `id` DESC LIMIT $start, ".Config::get('quote_requests_per_page').""); $reqs = $get->fetchAll(); (!empty($reqs)) ? $reqs[] = $get->foundRows() : ''; $this->results = $reqs; return $this; } // Gets the quoted response for the given quote-id in the url function selectResponse($id, $edit = FALSE) { $id = (int)$id; $sql1 = ", `".QUOTE_REQUESTS."`.`options`, `".QUOTE_REQUESTS."`.`units`, `".QUOTE_REQUESTS."`.`comments`, `".QUOTE_REQUESTS."`.`key_type`, `".QUOTE_REQUESTS."`.`key_id`, `".QUOTE_REQUESTS."`.`trans`, `".QUOTE_REQUESTS."`.`id` AS `quote_id`, `".QUOTE_REQUESTS."`.`engine`, `".QUOTE_REQUESTS."`.`gift_name`, `".QUOTE_REQUESTS."`.`gift_phone`, `".QUOTE_REQUESTS."`.`gift_email`, `".QUOTE_REQUESTS."`.`gift_date`, `".QUOTE_REQUESTS."`.`vehicle_make_id`, `".QUOTE_REQUESTS."`.`vehicle_model_id`, `".QUOTE_REQUESTS."`.`vehicle_year_id`, `".QUOTE_REQUESTS."`.`key_image_upload`"; if($edit === FALSE){ $sql1 = ''; } $sql = "SELECT `".QUOTE_RESPONSES."`.*, `".QUOTE_REQUESTS."`.`email`, ".CONCAT_VEHICLE." AS `vehicle`, `".QUOTE_REQUESTS."`.`name`, `".QUOTE_REQUESTS."`.`vehicle_sufix`, ".VEHICLE_NAME_PARTS." $sql1 FROM `".QUOTE_RESPONSES."` INNER JOIN `".QUOTE_REQUESTS."` ON `".QUOTE_REQUESTS."`.`id` = `".QUOTE_RESPONSES."`.`request_id` ".VEHICLE_JOIN." WHERE `".QUOTE_RESPONSES."`.`id`='$id'"; $get = $this->db->query($sql); return $get->fetch(); } // Re-sends a email quote. public function resendQuote() { $id = (int)Input::val('id|p'); return $this->composeQuote($id); } //Builds a Compose Button for quotes public function composeQuote($id) { $info = $this->selectResponse($id); $signature = Config::get('quote_signature').Config::get('quote_signature_part2').thanksSignature(TRUE); $e = new QuoteEmailTemplate; $data = [ 'name' => $info['name'], 'quote_link' => $info['quote_link'], 'signature' => [$signature, TRUE] ]; $e->data($data); $e->load('quote'); $send_html = TRUE; $em_body = $e->getHtmlString(); $em_alt_body = $e->getTextString(); if(Config::get('html_emails') === FALSE) { $send_html = FALSE; $em_body = $em_alt_body; $em_alt_body = ''; } // Setup mailer array $em['body'] = $em_body; $em['alt_body'] = $em_alt_body; $em['subject'] = 'Remote Start Quote '.$info['name'].' - '.$info['vehicle'].' '.$info['vehicle_sufix']; $em['to'] = $info['email']; $em['to_name'] = $info['name']; $em['smtp'] = FALSE; $em['html'] = $send_html; $em['bcc_to'] = ''; $em['bcc_name'] = ''; return buildPhpMailerEmail($em); ?> <!--<script> $('#send').click(function() { window.open('<?php echo 'https://mail.google.com/mail/?view=cm&fs=1&to='.urlencode($quote['email']).'&su=Remote Start Quote '.urlencode($quote['name']).' - '.urlencode($quote['vehicle']); ?>','_blank'); }); </script>--> <?php } public function getQuoteMenuInfo() { $code = sanitize(Input::val('rsmn_quote_code|c')); $get = $this->db->prepare("SELECT `".QUOTE_RESPONSES."`.*, `".QUOTE_REQUESTS."`.`cookie_code` FROM `".QUOTE_REQUESTS."` INNER JOIN `".QUOTE_RESPONSES."` ON `".QUOTE_RESPONSES."`.`request_id` = `".QUOTE_REQUESTS."`.`id` WHERE `".QUOTE_REQUESTS."`.`cookie_code` = ?"); $get->execute(array($code)); return $get->fetch(); } function updateQuoteRead($id) { $type = ''; $now = time(); if(Input::exists('t|g')) { $type = ", `viewed_by_txt` = 1"; } elseif(Input::exists('e|g')) { $type = ", `viewed_by_email` = 1"; } $this->db->query("UPDATE `".QUOTE_RESPONSES."` SET `date_read_quote` = NOW(), `read_quote` = 1".$type." WHERE `id` = ".$id); } } QuoteSystem.class.php <?php class QuoteSystem { protected $db; public function __construct() { $this->db = DB::getInstance(); } public function results() { return $this->results; } // Updates the response type for each quote posted public function changeResponseType($tbl) { $key=""; foreach(Input::val('iemailed|p') as $c["$key"] => $value) { $this->db->query("UPDATE `".$tbl."` SET `response` = 'Emailed' WHERE `id` = '".(int)$c[$key]."'"); } } // Searches the db for matching results for the given search criteria public function searchQuote($start) { $field = Input::val('tbl_field|g'); $srch = Input::val('searched|g'); $join = "LEFT JOIN `".QUOTE_RESPONSES."` ON `".QUOTE_RESPONSES."`.`request_id` = `".QUOTE_REQUESTS."`.`id` LEFT JOIN `".QUOTE_DEPOSITS."` ON `".QUOTE_DEPOSITS."`.`q_id` = `".QUOTE_RESPONSES."`.`id` LEFT JOIN `".QUOTE_DEP_RESP."` ON `".QUOTE_DEP_RESP."`.`quote_id` = `".QUOTE_RESPONSES."`.`id` LEFT JOIN `".SCH."` ON `".SCH."`.`deposit_id` = `".QUOTE_DEPOSITS."`.`id` ".VEHICLE_JOIN; $orderby = "`".QUOTE_REQUESTS."`.`name` ASC"; switch($field) { case "Name": $where = "WHERE `".QUOTE_REQUESTS."`.`name` LIKE :s "; break; case "Vehicle": $where = "WHERE `".QUOTE_REQUESTS."`.`vehicle` LIKE :s "; break; case "Vehicle Sufix": $where = "WHERE `".QUOTE_REQUESTS."`.`vehicle_sufix` LIKE :s "; break; case "Phone": $where = "WHERE `".QUOTE_REQUESTS."`.`phone` LIKE :s "; break; case "Date": $srch = explode("-", $srch); $srch = $srch[2].'-'.$srch[0].'-'.$srch[1]; $old = strtotime("-4 days", strtotime($srch)); $ahead = strtotime("+5 days", strtotime($srch)); $where = "WHERE `".QUOTE_REQUESTS."`.`date_sent` >= '$old' AND `".QUOTE_REQUESTS."`.`date_sent` <= '$ahead'"; $orderby = "`".QUOTE_REQUESTS."`.`date_sent` ASC"; break; case "Quote Id": $srch = (int)$srch; $where = "WHERE `".QUOTE_RESPONSES."`.`id` = $srch "; break; case "Email": $where = "WHERE `".QUOTE_REQUESTS."`.`email` LIKE :s "; break; case "Schedule": $srch = explode("-", $srch); $srch = $srch[2].'-'.$srch[0].'-'.$srch[1]; $old = date("Y-m-d", strtotime("-1 day", strtotime($srch))); $ahead = date("Y-m-d", strtotime("+2 day", strtotime($srch))); $where = "WHERE `".SCH."`.`install_time` BETWEEN '$old' AND '$ahead'"; $orderby = "`".SCH."`.`install_time` ASC"; break; case "Read": $srch = (int)$srch; $where = "WHERE `".QUOTE_RESPONSES."`.`read_quote` = $srch"; $orderby = "`".QUOTE_RESPONSES."`.`date_sent` DESC"; break; case "WHERE": $srch = str_replace('!gt!', '>', $srch); $srch = str_replace('!lt!', '>', $srch); $where = "WHERE ".$srch; break; } $sql = "SELECT `".QUOTE_REQUESTS."`.`id`, `".QUOTE_REQUESTS."`.`email`, `".QUOTE_REQUESTS."`.`name`, `".QUOTE_REQUESTS."`.`response`, `".QUOTE_REQUESTS."`.`date_sent` AS `request_sent`, `".QUOTE_REQUESTS."`.`vehicle` AS `car_requested`, `".QUOTE_REQUESTS."`.`vehicle_sufix`, `".QUOTE_RESPONSES."`.`quote_active`, `".QUOTE_RESPONSES."`.`id` AS `response_id`, `".QUOTE_RESPONSES."`.`date_sent` AS `quote_date_sent`, `".QUOTE_RESPONSES."`.`purchased`, ".CONCAT_VEHICLE." AS `vehicle`, `".QUOTE_RESPONSES."`.`read_quote` AS `read`, `".SCH."`.`install_time`, `".SCH."`.`cancelled`, `".SCH."`.`schedule_id`, `".SCH."`.`sch_notes`, `".QUOTE_DEP_RESP."`.`id` AS `dep_resp_id`, `".QUOTE_DEPOSITS."`.`part_num` AS `dep_part_num`, `".QUOTE_DEPOSITS."`.`id` AS `deposit_id`, `".QUOTE_DEPOSITS."`.`product_id`, `".QUOTE_DEPOSITS."`.`response` AS `dep_type` "; $sql .= "FROM `".QUOTE_REQUESTS."` "; $sql .= $join .' '. $where; $sql .= " ORDER BY ".$orderby." "; /*$sql .= "LIMIT $start, ".Config::get('quote_requests_per_page');*/ $int_fields = array('Quote Id', 'Date', 'Schedule', 'Read'); $like_fields = array('Name', 'Email', 'Vehicle', 'Vehicle Sufix', 'Phone'); $where_fields = array('WHERE'); if(in_array($field, $like_fields)) { $param = '%'.$srch.'%'; $get = $this->db->prepare($sql); $get->bind(':s', $param); $get->execute() /**/; } elseif(in_array($field, $int_fields)) { $get = $this->db->query($sql) /**/; } elseif(in_array($field, $where_fields)) { $get = $this->db->query($sql) ; } //echo $get->printSql().'<br><br>'; //echo $get->errorReason(); $this->results = $get->fetchAll(); return $this; } } Any advice or guidance is appreciated.
  13. Does your DB wrapper class have a mysql_error() function it can return the error for you? I appears the first query on the download page is failing or the query on the timer page. It's hard to tell cause you have EXPIRED echo out in 2 places in the scripts so I don't know which page the query is failing from.
  14. If that link is what the client clicks on to download the file, then it's what I said, there isn't a $_GET['code'] in that link.
  15. How about a quote items reference table. Just store the quote_id, product_id and quoted_price. All of which you should have the data for when submitting the quote. Then you don't have duplicated table data with the products and you just display the quoted price later if you need to view it.
  16. You would need to show us the code that is making the download link itself. Based on what your download script needs, sounds like it's not getting a "code" in the url, simple guess without the rest of your code. Or this is failing too $rs = $Core->DB->query('SELECT * FROM uploads WHERE id='.intval($row['fid']).' LIMIT 1'); So the browser doesn't know to send it to the download screen popup
  17. Thinking, I believe it won't echo anything out cause with a fatal error, the parser stops immediately when the error happens. So it can't output anything after that point, it can perform some other things, but output is a no go.
  18. Couple things. First these lines $Year = $_POST["Year"]; if ($Year= 2015) Should be this $Year = (int)$_POST["Year"]; // Cast to an integer for security and proper comparison below. if ($Year == 2015) // Missing a = But the bigger issue is that your DB structure looks very flawed. You basically have 2 tables that are identical in what they store but you named the columns slightly different. This is a huge waste of time and goes totally against proper db relationships. It would be way way better to have just one table with a timestamp column that would have a value of whatever year you needed. Then you only need one query that checks just the one column using the DATE() and possibly YEAR() in mysql to find the rows you need.
  19. You're not incrementing $i anywhere. You have a for() but you don't have any code in it to build the links properly. Check out the first link in my signature and got to the code snippets tab, you'll find something helpful there.
  20. You need to actually do the query before you can get a row count from it. Your code is only setting $sql to a string, but you never actually run any query. Plus you can't run a query with $sql cause it's NOT a db object, it's a string. You need to run the query from your pdo object, with whatever var you created that with.
  21. Well this could be fairly easy or complicated depending on how many different words you're talking about and whether you have a direct word-to-word correlation between the 2 languages. There may be some language api out there that has the word pairs already, otherwise you're kind of left to the making it yourself word for word, which would be extremely time consuming depending again on how large a vocabulary you want. Beyond that it becomes easy to actually handle the checking and refreshing a word list. 1. Create an array or words to display and store those in a session var. 2. Output the session array with text boxes for the user to type in the answer. 3. Submit the form and check that the answers match the session array. 4. If the answers match, create a new session array of words and re-output those to the user, and so on. If you are wanting this to happen without refreshing the page, so the answer is validated as the user moves to the next word, you'll need to use javascript and ajax to do the checking live as they type. All of this is really pretty easy stuff and there are tons of tutorials about the similar concepts used to do this, just need to google it or my favorite is to check out phpacademy on youtube.
  22. I'm going to guess it's either cause you can't trigger it that way or because you're using print_r() on the error result. I use 3 error handlers in my cms to db log anything that happens, including fatal errors. This is my error handling function page // Strips the SERVER HOST to main domain name function stripHost() { if(!empty($_SERVER['HTTP_HOST'])) { if(substr($_SERVER['HTTP_HOST'], 0, 4) == "www.") {$server = htmlentities(substr($_SERVER['HTTP_HOST'], 4), ENT_QUOTES);} else {$server = htmlentities($_SERVER['HTTP_HOST'], ENT_QUOTES);} } else{ $server = $_SERVER['SERVER_NAME']; } return $server; } // Determines if the host is your development localhost function isLocalhost() { if(strpos(stripHost(), 'localhost') !== FALSE) { return TRUE; } else{ return FALSE; } } // Attempts to get an accurate IP address from the client function get_ip_address() { $ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'); foreach ($ip_keys as $key) { if (array_key_exists($key, $_SERVER) === true) { foreach (explode(',', $_SERVER[$key]) as $ip) { // trim for safety measures $ip = trim($ip); // attempt to validate IP if (validate_ip($ip)) { return $ip; } } } } return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false; } /** * Ensures an ip address is both a valid IP and does not fall within * a private network range. */ function validate_ip($ip) { if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { return false; } return true; } function checkUserAgent() { $agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : ''; if(!empty($agent)) { $apikey = '92a7f5ba'; $useragent = urlencode($agent); $request = file_get_contents("http://useragentapi.com/api/v2/json/$apikey/$useragent"); $result = json_decode($request, true); return $result; } } // Custom error handler function cmsErrorHandler($code, $message, $file, $line) { $code = (int)$code; $line = (int)$line; $user_agent = checkUserAgent(); $fields = ['platform_type', 'platform_name', 'platform_version', 'browser_name', 'browser_version', 'engine_name', 'engine_version']; if(!empty($user_agent)) { foreach($user_agent as $key => $val) { if(in_array($key, $fields)) { $agent[$key] = $val; } } } $last_page = (isset($_SESSION['last_page_queried'])) ? $_SESSION['last_page_queried'] : ''; $params = [ 'error_type' => [$code, 'INT'], 'error_time' => date("Y-m-d H:i:s"), 'error_string' => $message, 'error_file' => $file, 'error_line' => [$line, 'INT'], 'error_ip' => get_ip_address(), 'queried_page' => $last_page ]; $params = (!empty($agent)) ? array_merge($params, $agent) : $params; DB::getInstance()->insert('cms_errors', $params); } function cmsExceptionErrorHandler($e) { cmsErrorHandler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine()); } // Custom Fatal error handler function cmsFatalErrorShutdownHandler() { $last_error = error_get_last(); if ($last_error['type'] === E_ERROR) { // fatal error cmsErrorHandler(E_ERROR, $last_error['message'], $last_error['file'], $last_error['line']); header('Location: http://'.stripHost().'/500.html'); } } And this is the set handlers if(isLocalhost() === FALSE) { // Setup custom error_handlers set_error_handler('cmsErrorHandler'); set_exception_handler('cmsExceptionErrorHandler'); register_shutdown_function('cmsFatalErrorShutdownHandler'); } One note, the header() in the fatal error function will only work if the error occurs before any output to the browser, typical cause of the buffer. I made a stripped down 500.html page to redirect to if it's able to.
  23. Simple, don't make them text fields in the first place. Then on the processing side when the form is submitted, run a query to gather the missing info from the db.
  24. $id will always only be the value of the last row the while loop gathers cause it's being reset with each loop of the while.
  25. Move the header() down below the closing of the db connection.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.