Sometimes you need to modify a system to have it work a certain way for a certain customer. Maybe every time this particular customer buys one widget we actually credit their account with two widgets.

So how do you go about modifying your code to make that happen? You could just write in the code:

if($customer=="greedy_guys") {
	$numWidgets = $numWidgets * 2;
}

Which works fine. But then what if your boss wants an email notification to go out as well when this happens? Then your code becomes:

if($customer=="greedy_guys") {
	$numWidgets = $numWidgets * 2;
	$to = 'myboss@mycompany.com';
	$from = 'thesystem@mycompany.com';
	$subject = 'Greedy Guys got more widgets';
	$body = 'Hello Boss,';
	$body .= '<br><br>Just letting you know that Greedy Guys';
	$body .= 'Got '.$numWidgets.' for the price of '.$numWidgets/2;
	$body .= '<br><br>--<br>The System';
	email_send($to,$from,$subject,$body);
}

So then the boss works out a new deal and now they’re only going to get 2 widgets for the price of 1 if there’s some other situation that occurs, otherwise they get some other complicated formula. So you code becomes:

if($customer=="greedy_guys") {
	$originalNumWidgets = $numWidgets;
	if($thisScenario===true) {
		$numWidgets = $numWidgets * 2;
	} else {
		$numWidgets = $numWidets + round((dateFormat('now','j') % 6),0);
	}
	$to = 'myboss@mycompany.com';
	$from = 'thesystem@mycompany.com';
	$subject = 'Greedy Guys got more widgets';
	$body = 'Hello Boss,';
	$body .= '<br><br>Just letting you know that Greedy Guys';
	$body .= 'Got '.$numWidgets.' for the price of '.$originalNumWidgets;
	$body .= '<br><br>--<br>The System';
	email_send($to,$from,$subject,$body);
}

Now let’s say you’re making all of these changes and then some other changes need to happen on this same page that are critical that have nothing to do with this client but the changes you’ve made for this client haven’t been fully approved yet. What do you do?

Use included files and subcommands.

In our original file, let’s call it “checkout.php”, your code becomes:

if($customer=="greedy_guys") {
	$subcommand = "process_checkout";
	include 'customizations/greedy_guys/greedy.inc.php';
}

In customizations/greedy_guys/greedy.inc.php you have:

if($subcommand=='process_checkout') {
	if($customer=="greedy_guys") {
		$originalNumWidgets = $numWidgets;
		if($thisScenario===true) {
			$numWidgets = $numWidgets * 2;
		} else {
			$numWidgets = $numWidets + round((dateFormat('now','j') % 6),0);
		}
		$to = 'myboss@mycompany.com';
		$from = 'thesystem@mycompany.com';
		$subject = 'Greedy Guys got more widgets';
		$body = 'Hello Boss,';
		$body .= '<br><br>Just letting you know that Greedy Guys';
		$body .= 'Got '.$numWidgets.' for the price of '.$originalNumWidgets;
		$body .= '<br><br>--<br>The System';
		email_send($to,$from,$subject,$body);
	}
}

Now you can go nuts with the customizations for that client and not have it muck up your original checkout page so much.

Important takeaways here: Use included subcommands like this if you need to modify existing page variables on the original system inline and/or have customizations that lend themselves well to this style of coding.

August 20th, 2013

Posted In: Controllers, Syntax

Leave a Comment

When writing code, if you find yourself copy/pasting a chunk of code from one place to another that is something other than “include: ‘header.php'” and “include: ‘footer.php'”, you might want to double-check what you’re doing.

Instead of copy/pasting the code that displays a widget for example, make that code into a function. Call is something like “createWidget()” and then reference that in your code.

In a recent example, I needed to show a notes list on two different view pages. The code was the exact same between the two so I created a function to do it instead. That function looked something like this:

function qt_getNotes($params=array()) {
	$id = $params['id'];
	$query = "SELECT * FROM table WHERE id='".encodeSQL($id)."'";
	$result = getMySQLData($query);
	$out = '';
	while($row = @mysql_fetch_assoc($result)) {
		$out .= 'Author: '.$row['author'].'<br>';
		$out .= $row['body'];
		$out .= '<hr>';
	}
	return $out;
}

if($command=='adminView') {
	echo "Show admin stuff here.";
	echo qt_getNotes(array('id'=>$id));
	echo "Show admin footer here.";
}

if($command=='workerView') {
	echo "Show worker stuff here.";
	echo qt_getNotes(array('id'=>$id));
	echo "Show worker footer here.";
}

This is obviously a pretty simple example in terms of visual sophistication, I just wanted to show how it could be used.

Why did I preface my function with “gt_”? Because this function was designed for use within our “Quality Ticket” area and would not be used outside of that area. Also, I didn’t want to try to double-define any function that may have been previously called “getNotes”.

And why did I use an entire array for passing the $id? Because you’ll likely need to pass other variables to that function at some point in time (like whether or not to show a delete button) and you can now add those as parameters in the array rather than defining additional in-line inputs to the function. Keeps it clean when you have a variable number of possible inputs.

You’ll also notice I used “$out” to store the view components of this rather than just echo’ing it straight onto the page. This comes in handy if you need to store the returned HTML or have it displayed in an email or something like that.

The benefits of using a function like this is that you can change the code once and it effectively is updated in multiple places. You also have your own variable namespace within the function so you can re-use variables like $id, $data, $result, and $row which are commonly used in the body of a page without concern that you’ll overwrite an existing loop you might be in.

The downsides of a function are that they don’t inherit page variables and must be carefully defined once in your system. Variable inheritance is helpful if you have usernames, permissions, or display variables on your page that you would want your function to utilize. To use those variables, you’d need to pass them in your $params array.

August 20th, 2013

Posted In: Functions, Syntax

Leave a Comment

The audit log tells you who changed every value on every item in your system. It tells you when they did it and what page they were on when they did it.

This is used all the time in my daily work. We can see who change any record in the system, what page they made those changes on, and what other values were changed at the same time. We can see a complete history of changes made, and that’s incredibly helpful when you need to figure out, “What Happened?!?”

function writeAuditLog($params) {
	$databaseName = $params['databaseName'];
	$tableName = $params['tableName'];
	$primaryKeyName = $params['primaryKeyName'];
	$primaryKeyValue = $params['primaryKeyValue'];
	$newDataArray = $params['newDataArray'];
	$arbitraryValue = $params['arbitraryValue'];
	
	$id_user = $_SESSION['session_id_user'];
	$page = curPageURL();
	
	if($arbitraryValue!='' || (is_array($newDataArray) && count($newDataArray)>0)) {
		
		$performQueries = true;
		mysql_query("SET NAMES utf8",$GLOBALS['standardDBlink']);
		$query = "UPDATE audit_log SET database_name='".encodeSQL($databaseName)."',
										table_name='".encodeSQL($tableName)."',
										primary_key_value='".encodeSQL($primaryKeyValue)."',
										page_performed_on='".encodeSQL($page)."'";
		if($id_user!='') {
			$query .= ", id_contact_performing_change='".encodeSQL($id_user)."' ";
		}
		if($arbitraryValue!='') {
			$query .= ", change_log='".encodeSQL($arbitraryValue)."'";
		} elseif(is_array($newDataArray) && count($newDataArray)>0) {
			$change_log = '';
			$change_arry = array();
			$subQuery = "SELECT * FROM ".$databaseName.".".$tableName." 
							WHERE `".$primaryKeyName."`='".$primaryKeyValue."'";
			$data = getMySQLData($subQuery, false, true);
			if($data) {
				foreach($newDataArray AS $key=>$new_value) {
					$old_value = mysql_result($data,0,$key);
					if($old_value!=$new_value) {
						$change_log .= $key.": ".$old_value." [ changed to ] ".$new_value."\n";
						$change_arry[$key] = array(
							'orig' => (string)$old_value,
							'changed_to' => (string)$new_value
							);
					}
				}
			}
			if(count($change_arry) > 0) {
				$change_log = serialize($change_arry);
			}
			if($change_log == "") {
				$performQueries = false;
			}
			$query .= ", change_log='".encodeSQL($change_log)."'";
		}
		

		if($performQueries) {
			$insertQuery = "INSERT INTO audit_log (`datetime_created`) VALUES (NOW())";
			$id = insertMySQLData($insertQuery);
			$query .= " WHERE id='".$id."'";
			updateMySQLData($query);
		}
	}
}

August 20th, 2013

Posted In: Functions

Leave a Comment

You’re working on a huge project.  Then the boss says, “Can we extend our system to running some other function on another website?”  You say, sure, why not?  Since we can just do a SVN checkout and tell Apache to use only one subdirectory, with a couple modifications we can have all of the features and functionality of our original system on this smaller subsystem.

Bad move.

Do you really need all of the functionality from your giant day-to-day system in your offshoot?  Does it need to share the SVN repository as your main project?  What happens when you need to make significant URL, IP, or system structure modifications?  Will the two branches work nicely with each other?

My suggestion: have your sub-system use APIs to talk to the big system.  Much cleaner.  The subsystem can live on its own, wherever it wants to on whatever hardware or architecture it needs to.  It can then make requests and pass data back and forth with your parent system in a similar way to how a client would.  This means that the upgrade paths of these two systems can diverge from each other and nothing’s going to break.  Need to introduce some fancy load balancing on one and not the other?  Go for it.  Need to move the child off to cloud-based hosting due to new business requirements?  No problem.

A little extra time spent separating distinct systems pays for itself in flexibility later.

August 20th, 2013

Posted In: Systems

Leave a Comment

This sounds like a pretty terrible topic, doesn’t it?  Stress Testing.  Sounds like it might be an interviewing method for new engineers.

Stress Testing is actually a great way to see if your servers can handle sudden jumps in traffic or sustained volumes of traffic (think of something going viral).  I learned today that a small wordpress site I set up earlier could easily handle about 80 simultaneous active users before it’s response times started getting too high and it went into a downward spiral of responsiveness.  I also learned that I could increase the number of CPUs and memory allocated to the virtual machine and it could handle significantly more simultaneous users.  This tells me that if the company running the WordPress site wants to start up a viral campaign such that 10,000 people are going to be hitting the site within 10 minutes, I better make some significant investments in load balancing, additional hardware, and software necessary to make that happen.  If however they don’t foresee any huge increases in traffic, then we can leave everything where it is and keep our costs down.

Do be careful running stress tests, and if at all possible, run them on dedicated hardware that will not affect production machines.  Your stress test could very easily overwhelm the machine you’re testing and if you don’t have good control on aborting the test, you’ve basically taken yourself offline due to a self-induced overload attack.

August 20th, 2013

Posted In: Systems

Leave a Comment

As promised earlier, here’s the save function. This is an almost magical function. It makes every write you’ll almost ever do exceedingly simple.

function save() {
	$this->dataChecks();
	$this->id = objectSave($this->tableName, $this->id, $this->data, $this->databaseName, array('writeAudit'=>true));
	$this->data['id'] = $this->id;
	$this->postSaveFunctions();
}

OK, so that magical save function just basically calls other functions. What’s the big deal? Each of those functions, particularly objectSave() make life easier.

I’ll take them in order, starting with dataChecks(). This function is defined on a per-class basis in a way that meets the needs of the class. For most of my classes, I include a datetime_created field in my MySQL table, so I like to set that value in my dataCheck function. I also take care of filling in any missing fields or special calculations that are needed. The example below shows how I’d set the datetime_created and set an id_client value if it’s missing and id_company was set.

function dataChecks() {
	if($this->data['datetime_created'] == "" && $this->id==''){
		$this->data['datetime_created'] = dateFormat("now","mysql");
	}
	
	
	if($this->data['id_client']=='' && $this->data['id_company']!='') {
		$companyObj = new company($this->data['id_company']);
		$this->setIDclient($companyObj->getIDclient());
	}
}

I’ll go over the dateFormat function at another time. It’s one of those functions that makes me love PHP and is really simple to create.

The next function is the real meat of this post: objectSave(). objectSave() has been an evolution of various needs over time and if I were to design it from scratch today, I’d write it slightly differently. (First thing, pass all data via one $parameters array rather than the listed parameters that it has now.) You’ll also see in this function a function for writeAuditLog(). That’s a function that is worth it’s own posting later as well. And, since this was written for a particular system, it has some database names and table names hard-coded. That, ideally, should be abstracted. Overall though, this function is called many thousands (perhaps hundreds of thousands?) of times a day and saves us countless time and effort.

function objectSave($tableName, $id=NULL, $dataArray, $databaseName='dtrm', $extraParams=array()) {
	
	$writeAudit = false;
	if($extraParams['writeAudit']===true) {
		$writeAudit = true;
	}
	
	if($id==NULL) {
		if($dataArray['id']!=NULL) {
			$id = $dataArray['id'];
		}
	}
	
	if($id==NULL) {
		mysql_query("SET NAMES utf8",$GLOBALS['standardDBlink']);
		$preferredID = $extraParams['preferredID'];
		$query = "INSERT INTO ".$databaseName.".".$tableName." (`id`) VALUES ('".$preferredID."')";
		$q_insert = mysql_query($query);showMySQLError(mysql_error($GLOBALS['standardDBlink']),$query);
		$sqlError = mysql_error($GLOBALS['standardDBlink']);
		if($sqlError!='') {
			$query2 = "INSERT INTO dtrm.badQueryLog (`query`, `page`, `datetime_created`, `error_text`) 
						VALUES ('".encodeSQL($q_insert)."', '".encodeSQL(curPageURL())."',NOW(), 
								'".encodeSQL($sqlError)."')";
			insertMySQLData($query2);
		}
		$id = mysql_insert_id();
		
		if($writeAudit===true) {
			$subParams = array();
			$subParams['databaseName']=$databaseName;
			$subParams['tableName']=$tableName;
			$subParams['primaryKeyName']='id';
			$subParams['primaryKeyValue']=$id;
			$subParams['arbitraryValue']="New Record";
			writeAuditLog($subParams);
		}
	}

	if($writeAudit===true) {
		$subParams = array();
		$subParams['databaseName']=$databaseName;
		$subParams['tableName']=$tableName;
		$subParams['primaryKeyName']='id';
		$subParams['primaryKeyValue']=$id;
		$subParams['newDataArray']=$dataArray;
		writeAuditLog($subParams);
	}
	
	mysql_query("SET NAMES utf8",$GLOBALS['standardDBlink']);
	
	$query = "UPDATE ".$databaseName.".".$tableName." SET ";
	foreach ($dataArray AS $key=>$val) {
		if($key!='id') {
			$query .= "`".$key."`=";
			if($val==='' || $val===NULL) {
				$query .= "NULL, ";
			} else {
				$query .= "'".mysql_real_escape_string($val)."', ";
			}
		}
	}
	$query = trim($query, ", ");
	$query .= " WHERE id=".$id;
	$update_q = mysql_query($query);showMySQLError(mysql_error($GLOBALS['standardDBlink']),$query);
	$sqlError = mysql_error($GLOBALS['standardDBlink']);
	if($sqlError!='') {
		$query2 = "INSERT INTO dtrm.badQueryLog (`query`, `page`, `datetime_created`, `error_text`) 
					VALUES ('".encodeSQL($update_q)."', '".encodeSQL(curPageURL())."',NOW(), 
							'".encodeSQL($sqlError)."')";
		insertMySQLData($query2);
	}
	
	return $id;
	
}

The above function will take the $data array from the class structure that has already been defined and write those fields, correctly, to a MySQL table. That saves infinite time trying to match up fields in code to MySQL insert and update statements. It also handles returning the $id value whether it stays the same or is created as a result of performing the save. Plus, it logs any errors that happen so you can easily see what you’re doing wrong if you make typos in your code. Oh, and it handles NULL values correctly so you don’t end up with blank or ‘0’ values in your table.

The last function in our save function is postSaveFunctions(). This function isn’t used nearly as much as the others listed here, but it can be really handy if you need to have some code execute after you have a primary key identified or otherwise need to have data written before executing the code. I often create a postSaveTriggers array within an object if I am going to need to perform postSaveFunctions so that in other places in the class I can add items to the postSaveTriggers array and then have the class execute them automatically later when it is saved.

function doPostSaveTriggers() {
	$triggersPerformed = array();
	foreach($this->postSaveTriggers AS $triggerName) {

		// skip the trigger if it has already been performed
		if(in_array($triggerName,$triggersPerformed)) {
			continue;
		}
		
		if($triggerName=="human_audit_created") {
			// do stuff here
		}

		if($triggerName=="hire_nostart_payoutEmail") {
			// do stuff here
		}

	}
	$this->postSaveTriggers = array();
}

I want to make sure to make one point clear: the save(), dataChecks(), and postSaveFunctions() functions all all class-specific. The objectSave() function is a single piece of code that should be included via a common file for use everywhere in your system.

August 20th, 2013

Posted In: Functions

Leave a Comment

If you’re writing a complex piece of logic, make it easier for yourself later. I’m going to provide two code examples below and I’d like you to choose which one you’re rather work with.

Hint: There’s generally no need to nest if statements more than 1 or 2 levels deep. Use additional variables to guide your code through how to evaluate itself.

Version 1:

function isCandidateProfileVisible($params=array()) {
	
	if($this->profileVisibleData['showLinkToApplicant']===NULL) {
			
		
		$isDTstaff = $_SESSION['client']['isDTstaff'];
		$id_company = $_SESSION['client']['id_company'];
		
		$id_user = $_SESSION['client']['id_contact'];
		if($id_user=='') {
			$id_user = $_SESSION['session_id_user'];
		}
		
		if($params['isDTstaff']===true) {
			$isDTstaff = true;
		}
		
		$showLinkToApplicant = false;
		$howAccessGranted = NULL;
		
		if($isDTstaff) {
			$showLinkToApplicant = true;
			$howAccessGranted = "DT Staff";
		} else {
			if(strtolower($this->getOwner())=="client") {
				$showLinkToApplicant = true;
				$howAccessGranted = "owner=client";
			} else {
				if($this->getActivityStage()>=2) {
					$showLinkToApplicant = true;
					$howAccessGranted = "getActivityStage";
				} else {
					$currentEmployee = strtolower($this->getCurrentEmployee());
					if($currentEmployee=='yes' || $currentEmployee=='alumni') {
						$showLinkToApplicant = true;
						$howAccessGranted = "current/alumni employee";
					} else {
						$accessObj = $params['accessObject'];
						if(is_object($accessObj) && $accessObj->id!='') {
							$viewApps = $accessObj->getViewApps();
						} else {
							$query = "SELECT viewApps FROM access 
										WHERE id_company='".$id_company."' 
											AND id_contact='".$_SESSION['client']['id_contact']."'";
							$viewApps = getMySQLValue($query,true);
						}
						if(strtolower($viewApps)=="all") {
							$showLinkToApplicant = true;
							$howAccessGranted = "viewApps=all";
						} else {
							$jobObj = $params['jobObj'];
							$jobviewapps = false;
							
							$id_job = $params['id_job'];
							if(!is_object($jobObj) && $id_job!='') {
								$jobObj = new job($id_job);
							}
							
							if($id_job=='' && is_object($jobObj)) {
								$id_job = $jobObj->id;
							}
							
					
							$jobAccessObj = $params['jobAccessObj'];
							if(is_object($jobAccessObj) && $jobAccessObj->id!='') {
								$jobviewapps = $jobAccessObj->getViewApps();
							} else if($id_job!='') {
								$id_user = $_SESSION['session_id_user'];
								$query = "SELECT viewapps FROM jobaccess 
											WHERE id_job='".$id_job."' 
											AND id_contact='".$id_user."'";
								$jobviewapps = getMySQLValue($query,true);
							}
							
							if($jobviewapps!==false && strtolower($jobviewapps)=="all") {
								$showLinkToApplicant = true;
								$howAccessGranted = "jobviewapps=all";
							} else {
								$id_most_recent_job = $this->getMostRecentIDjob();
								if($id_most_recent_job>0) {
									$query = "SELECT Status_ActiveOrPending FROM jobs 
												WHERE id='".$id_most_recent_job."'";
									$Status_ActiveOrPending = getMySQLValue($query,true);
									if($Status_ActiveOrPending!='Yes') {
										$showLinkToApplicant = true;
										$howAccessGranted = "most recent job (".$id_most_recent_job.") ";
										$howAccessGranted .= "is not active or pending";
									} else {
										$query = "SELECT viewapps FROM jobaccess 
													WHERE id_job='".$id_most_recent_job."' 
														AND id_contact='".$id_user."'";
										$jobviewapps = getMySQLValue($query,true);
										if(strtolower($jobviewapps)=="all") {
											$showLinkToApplicant = true;
											$howAccessGranted = "jobviewapps=all";
										} else {
											if(is_object($jobObj) && $jobObj->id>0) {
				
												if(	strtolower($jobObj->getFlagAppAccessClient())=="view" 
													|| strtolower($jobObj->getFlagAppAccessClient())=="edit") {
													
													$showLinkToApplicant = true;
													$howAccessGranted = "getFlagAppAccessClient=";
													$howAccessGranted .= $jobObj->getFlagAppAccessClient()." on ".$jobObj->id;
												} else {
													$query = "SELECT r.id
																FROM responses AS r 
																LEFT JOIN jobs AS j ON j.id=r.id_job 
																WHERE r.id_applicant='".$this->id."'
																	AND 
																		(
																			j.flag_masterlist='client'
																			OR
																			j.title='Future Opportunities'
																		)
																LIMIT 1";
													$id_self_service_response = getMySQLValue($query,true);
													if($id_self_service_response) {
														$showLinkToApplicant = true;
														$howAccessGranted = "self service job found via response record: ";
														$howAccessGranted .= $id_self_service_response;
													} else {
														if($this->getOwner()=='') {
															$showLinkToApplicant = true;
															$howAccessGranted = "owner=NULL";
														} else {
															$query = "SELECT f.id
																		FROM flags AS f 
																		LEFT JOIN jobs AS j ON j.id=f.id_job 
																		WHERE f.id_applicant='".$this->id."'
																			AND 
																				(
																					j.flag_masterlist='client'
																					OR
																					j.title='Future Opportunities'
																				)
																		LIMIT 1";
															$id_self_service_response = getMySQLValue($query,true);
															if($id_self_service_response) {
																$showLinkToApplicant = true;
																$howAccessGranted = "self service job found via flag record: ";
																$howAccessGranted .= $id_self_service_response;
															} else {
																if($this->getIDreferrer()=='15') {
																	$showLinkToApplicant = true;
																	$howAccessGranted = "Candidate referrer is 'Our Corporate Website'";
																} else {
																	$query = "SELECT r.id
																				FROM responses AS r 
																				WHERE r.id_applicant='".$this->id."'
																					AND id_referrer='15'
																				LIMIT 1";
																	$id_website_application = getMySQLValue($query,true);
																	if($id_website_application) {
																		$showLinkToApplicant = true;
																		$howAccessGranted = "'our corporate website' referrer via response record: ";
																		$howAccessGranted .= $id_website_application;
																	} else {
																		$query = "SELECT id FROM activity 
																					WHERE id_applicant='".$this->id."'
																						AND activity_type='access'";
																		$id_access_activity = getMySQLValue($query,true);
																		if($id_access_activity) {
																			$showLinkToApplicant = true;
																			$howAccessGranted = "access activity record found: ".$id_access_activity;
																		} else {
																			$howAccessGranted = "Not Granted";
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		$this->profileVisibleData['showLinkToApplicant'] = $showLinkToApplicant;
		$this->profileVisibleData['howAccessGranted'] = $howAccessGranted;
	
	}
	
	
	if($params['returnKind']=="" || $params['returnKind']=="boolean") {
		return $this->profileVisibleData['showLinkToApplicant'];
	} else if($params['returnKind']=="howAccessGranted" || $params['returnKind']=="debug") {
		return $this->profileVisibleData['howAccessGranted'];
	}
}

Version 2:

function isCandidateProfileVisible($params=array()) {
	
	if($this->profileVisibleData['showLinkToApplicant']===NULL) {
			
		
		$isDTstaff = $_SESSION['client']['isDTstaff'];
		$id_company = $_SESSION['client']['id_company'];
		
		$id_user = $_SESSION['client']['id_contact'];
		if($id_user=='') {
			$id_user = $_SESSION['session_id_user'];
		}
		
		if($params['isDTstaff']===true) {
			$isDTstaff = true;
		}
		
		$showLinkToApplicant = false;
		$howAccessGranted = NULL;
		
		$useInternalDTrules = false;
		if($isDTstaff && $this->getIDclient()=='9786') {
			$useInternalDTrules = true;
		}
		

		if(!$showLinkToApplicant && $isDTstaff) {
			$showLinkToApplicant = true;
			$howAccessGranted = "DT Staff";
		}

		if(!$showLinkToApplicant && strtolower($this->getOwner())=="client") {
			$showLinkToApplicant = true;
			$howAccessGranted = "owner=client";
		}
		
		if(!$showLinkToApplicant && $this->getActivityStage()>=2) {
			$showLinkToApplicant = true;
			$howAccessGranted = "getActivityStage";
		}
		
		if(!$showLinkToApplicant) {
			$currentEmployee = strtolower($this->getCurrentEmployee());
			if($currentEmployee=='yes' || $currentEmployee=='alumni') {
				$showLinkToApplicant = true;
				$howAccessGranted = "current/alumni employee";
			}
		}

		if(!$showLinkToApplicant) {
			$accessObj = $params['accessObject'];
			if(is_object($accessObj) && $accessObj->id!='') {
				$viewApps = $accessObj->getViewApps();
			} else {
				$query = "SELECT viewApps FROM access 
							WHERE id_company='".$id_company."' 
								AND id_contact='".$_SESSION['client']['id_contact']."'";
				$viewApps = getMySQLValue($query,true);
			}

		}

		if(!$showLinkToApplicant && strtolower($viewApps)=="all") {
			$showLinkToApplicant = true;
			$howAccessGranted = "viewApps=all";
		}
		
		// special rules for DT persons viewing DT candidates (internal jobs, etc.)
		if($useInternalDTrules) {
			// the above rules don't apply to this situation so we should override any previous data
			$showLinkToApplicant = false;
			$howAccessGranted = NULL;
		}
		

		if(!$showLinkToApplicant) {
			$jobObj = $params['jobObj'];
			$jobviewapps = false;
			
			$id_job = $params['id_job'];
			if(!is_object($jobObj) && $id_job!='') {
				$jobObj = new job($id_job);
			}
			
			if($id_job=='' && is_object($jobObj)) {
				$id_job = $jobObj->id;
			}
			
	
			$jobAccessObj = $params['jobAccessObj'];
			if(is_object($jobAccessObj) && $jobAccessObj->id!='') {
				$jobviewapps = $jobAccessObj->getViewApps();
			} else if($id_job!='') {
				$id_user = $_SESSION['session_id_user'];
				$query = "SELECT viewapps FROM jobaccess 
							WHERE id_job='".$id_job."' 
							AND id_contact='".$id_user."'";
				$jobviewapps = getMySQLValue($query,true);
			}
				
	
			if($jobviewapps!==false && !$showLinkToApplicant && strtolower($jobviewapps)=="all") {
				$showLinkToApplicant = true;
				$howAccessGranted = "jobviewapps=all";
			}
			
			
			
			if(!$showLinkToApplicant) {
				$id_most_recent_job = $this->getMostRecentIDjob();
				if($id_most_recent_job>0) {
					$query = "SELECT Status_ActiveOrPending FROM jobs 
								WHERE id='".$id_most_recent_job."'";
					$Status_ActiveOrPending = getMySQLValue($query,true);
					if($Status_ActiveOrPending!='Yes') {
						$showLinkToApplicant = true;
						$howAccessGranted = "most recent job (".$id_most_recent_job.") ";
						$howAccessGranted .= "is not active or pending";
					} else {
						$query = "SELECT viewapps FROM jobaccess 
									WHERE id_job='".$id_most_recent_job."' 
										AND id_contact='".$id_user."'";
						$jobviewapps = getMySQLValue($query,true);
						if(strtolower($jobviewapps)=="all") {
							$showLinkToApplicant = true;
							$howAccessGranted = "jobviewapps=all";
						}
					}
				}
			}
			
			
			if(!$showLinkToApplicant && is_object($jobObj) && $jobObj->id>0) {
				
				if(	strtolower($jobObj->getFlagAppAccessClient())=="view" 
					|| strtolower($jobObj->getFlagAppAccessClient())=="edit") {
					
					$showLinkToApplicant = true;
					$howAccessGranted = "getFlagAppAccessClient=";
					$howAccessGranted .= $jobObj->getFlagAppAccessClient()." on ".$jobObj->id;
				}
			}
		}
		
		
		if(!$showLinkToApplicant) {
			// check to see if the app has applied to any self-service jobs
			$query = "SELECT r.id
						FROM responses AS r 
						LEFT JOIN jobs AS j ON j.id=r.id_job 
						WHERE r.id_applicant='".$this->id."'
							AND 
								(
									j.flag_masterlist='client'
									OR
									j.title='Future Opportunities'
								)
						LIMIT 1";
			$id_self_service_response = getMySQLValue($query,true);
			if($id_self_service_response) {
				$showLinkToApplicant = true;
				$howAccessGranted = "self service job found via response record: ";
				$howAccessGranted .= $id_self_service_response;
				if($this->getIDclient()=='104093') {
					$subcommand="correct_hm_access";
					require config_include_path_constant.'client/reports/104093/dr.inc.php';
				}
			}
		}
		
		if(!$showLinkToApplicant && $this->getOwner()=='') {
			$showLinkToApplicant = true;
			$howAccessGranted = "owner=NULL";
		}
		
		if(!$showLinkToApplicant) {
			// check to see if the app has been attached to any self-service jobs
			$query = "SELECT f.id
						FROM flags AS f 
						LEFT JOIN jobs AS j ON j.id=f.id_job 
						WHERE f.id_applicant='".$this->id."'
							AND 
								(
									j.flag_masterlist='client'
									OR
									j.title='Future Opportunities'
								)
						LIMIT 1";
			$id_self_service_response = getMySQLValue($query,true);
			if($id_self_service_response) {
				$showLinkToApplicant = true;
				$howAccessGranted = "self service job found via flag record: ";
				$howAccessGranted .= $id_self_service_response;
				if($this->getIDclient()=='104093') {
					$subcommand="correct_hm_access";
					require config_include_path_constant.'client/reports/104093/dr.inc.php';
				}
			}
		}
		
		/*
			2013-06-03: Jay says that all candidates that come from the "Our Corporate Website" 
			should be visible by the client.
		*/
		if(!$showLinkToApplicant) {
			if($this->getIDreferrer()=='15') {
				$showLinkToApplicant = true;
				$howAccessGranted = "Candidate referrer is 'Our Corporate Website'";
			}
		}
		
		if(!$showLinkToApplicant) {
			// check to see if the app has applied to any self-service jobs
			$query = "SELECT r.id
						FROM responses AS r 
						WHERE r.id_applicant='".$this->id."'
							AND id_referrer='15'
						LIMIT 1";
			$id_website_application = getMySQLValue($query,true);
			if($id_website_application) {
				$showLinkToApplicant = true;
				$howAccessGranted = "'our corporate website' referrer via response record: ";
				$howAccessGranted .= $id_website_application;
			}
		}
		
		if(!$showLinkToApplicant) {
			// check to see if any activity "access" records have been created
			// this may need to be modified later to check for job-specific
			// restrictions and/or contact-specific restrictions
			$query = "SELECT id FROM activity 
						WHERE id_applicant='".$this->id."'
							AND activity_type='access'";
			$id_access_activity = getMySQLValue($query,true);
			if($id_access_activity) {
				$showLinkToApplicant = true;
				$howAccessGranted = "access activity record found: ".$id_access_activity;
			}
			
		}
		
			
		
		if($howAccessGranted=='') {
			$howAccessGranted = "Not Granted";
		}
		
		$this->profileVisibleData['showLinkToApplicant'] = $showLinkToApplicant;
		$this->profileVisibleData['howAccessGranted'] = $howAccessGranted;
	
	}
	
	
	if($params['returnKind']=="" || $params['returnKind']=="boolean") {
		return $this->profileVisibleData['showLinkToApplicant'];
	} else if($params['returnKind']=="howAccessGranted" || $params['returnKind']=="debug") {
		return $this->profileVisibleData['howAccessGranted'];
	}
}

August 12th, 2013

Posted In: Controllers, Syntax

Leave a Comment

When naming files or variables, use underscores or at least alternating cases as appropriate.  Do not just omit all spaces and capitalization, it makes it terrible to work on later.  Also, remember that computers have lots of memory these days and using an extra couple characters in variable name can make life so much easier down the road.

Examples filenames:

adcostperrecruiter.php vs ad_cost_per_recruiter.php
or
clientcontacthitlist.lasso vs client_contact_hitlist.lasso
or
clientjqrefquestionsnext.lasso vs client_jq_refQuestions_next.lasso

Example variables:

$cltid; // I think this means “client id”
$coname; // I think this means “company name”
$cname; // I think this means “contact name”
vs
$hideTitleInfo;
$useAjax;
$autoDisplayTabs;

Just think about it this way – if you come back to your own code 6 months later, will you be able to read what you wrote?

August 12th, 2013

Posted In: Basics

Leave a Comment

If you’re at all successful in your job and work for a company that looks towards the future and wants to do more, you’re going to end up with more projects than you know what to do with.

I find it most helpful to not store all that project data in my email program.  No matter how good your email program is, it is not a project management system.  I subscribe to the concept that I should “clear” all of my email whenever possible.  For me, that means I have them all marked as read.  This is the fastest way for me to recognize things that I still need to do something with in one way or another and those that have been handled.  Some people actually go so far as to delete emails once they’re done with them but I often find that I need to reference emails days, months, or even years later.  Some people also actually file those emails into separate folders or tags but I would spend all day doing that.

So what do I do with all this project data?  Use a project management system.  If you’re working in a team it will be important to share critical pieces of that project with your team members.  There’s lots of project management software out there, and I’ve used a few of them here and there.  For my day-to-day work at DT, we use a system I created called “Kirkland”.  It does everything we need because we made it ourselves.

Side note: since I’m a programmer, I see the world through a programmer / engineer’s viewpoint.  If I look around and don’t find the tool or system I want, I make it myself, hence why we have our own project management system at DT.

Your project management system should at minimum if used by only yourself:

  • Be easy to use
  • Support multiple updates per project
  • Support categories or tags, or clients, or some way to group projects
  • Support sorting and/or prioritization
  • Have statuses and filter by them

In addition to the items listed above, if you’re working with a group of people your software will need to:

  • Support multiple users
  • Have at least one user assigned to a project, an “owner”
  • Support some kind of communication method to encourage people to write their updates in the software

Why is all of this important?  If you have so many projects you don’t know what’s going on and/or you loose project details because they get lost in email, you’re an ineffective programmer.  Keep your stuff in order and you’ll be more sane and therefore will get more productive work done which will make you feel better.

August 12th, 2013

Posted In: How to Work

Leave a Comment

When programming, use the right tools for the job. Use tools you’re not only comfortable with but also help you get work done in a more efficient way.

I highly recommend a solid code-writing program. Whether it’s TextWrangler, BBEdit, Notepad++, Coda, Eclipse or something else, find a tool you like and use it. It should support the ability to use your cursor to select chunks of code, syntax highlighting, be able to properly handle tabs and not make them into spaces, the ability to SSH onto remote servers and work directly with code stored there and have multiple windows or tabs open at once. Features beyond that are entirely up to your personal taste.

You should have some kind of SSH command-line tool. Mac OS comes with Terminal but I prefer iTerm myself. All flavors of linux have a terminal built in as the very core. Windows? Not sure, I don’t do any programming there.

A FTP / SFTP browser is helpful but not all that necessary for most plain-jane programming work.

Why use these good tools? Does a carpenter use a pipe wrench to put in nails? No, duh. By the same token, would he use a hammer made from wood? No. Modern tools help us be more efficient and focus more time on what we’re trying to work on rather than the how of how we’re going to work on it.

August 12th, 2013

Posted In: How to Work

Leave a Comment

« Previous PageNext Page »