Also see:
	docs/documentation.py
	docs/structure.py

Architecture

webpage or ajax -> http server |    ___________
[todo] api                     |   |           |
cron                           |-> |           |
command line                   |   |           |
                                   | framework | -> action -> classes, elements, engines, libraries  =>  side effects
                                   |           | -> documents/html/my_doc_file.php -> elements/layouts/my_layout.php (for pages) or json wrapper (for ajax)
                       response <- |           |
                                   |___________|

Components / Code Types

element, engine, action, email, class, library, function

framework-only
	corefile

also static function?, native associative function?, chewitt associative function?

Naming Conventions

files
	multi_word_filename.ext
	
database tables (core)

database tables (subcategory)
	gk_ip_addresses
	
database columns
	nonRelationalField
	relational_field_id
	
php and js
	variable
	multiWordVariable
	numeric_multiWordVariable as a kind of hungarian notation when necessary to clarify the data type
	function
	multiWordFunction
	Class
	MultiWordClass
	
html and css
	class-variable, js-class-variable, or both-class-variable
	id-variable

Syntax / Coding Style Conventions

comments
	
	// comment
	
	//commented-out line of code
	
	/*
		multi-line
		comment
	*/
	
code blocks
	
	/* check that the parameter definition is complete */ if (true) {
		
		line1;
		
		line2;
	}
	
if statements
	
	if ($singleLineIf) $code = foo();
	
	if (!$multiLineIf) {
	
		$code = foo();
	}
	
	if ( (multiCondition($foo)) || (1 === $lineNum) ) {
	
		$code = foo();
	}
	
	if ($singleLineIfWithElses) return 0;
	else if ($foo) return 1;
	else if ($bar) return 20;
	else return 'whoops';
	
	if ($multilineIfWithElses) {
	
	} else if { // we could use "else if" or "elseif", but javascript only has "else if" so we use that in php as well to be consistent
	
	} else {
	
	}
	
foreach statements
	
	foreach ($lines as $lineNumber => $line) {
		
		$code = 'foo';
	}
	
	<? foreach ($lines as $lineNumber => $line): ?>
		
		Foo<br>
		
	<? endforeach ?>
	
function definitions

	function foo($message = null) {
	/*	This is the explanation of this function.
	*/
		
		line1;
		
		line2;
		
		return $bar;
	}
		
function calls
	
	$temp = naiveFunction(4, false);
	
	$temp = associativeFunction(array(
		'numColumns' => 4,
		'disabled' => false,
	));

data types

<temporal data types>
	
	There is a lot to be said about temporal data types due to the wide variety of representations covering machine readable, human readable, dates, times, and contextualized types (isDuring = true, 'Later Today')
	The following is a partial list of the kinds of data fragments we might need to represent:
		isToday
		isDuring
		'Right Now'
		'All Day'
		'Later On'
		'2:39pm'
		'7p'
		'Midnight'
		'6am-11:30p'
		1430
		14.5
		'Friday 8/15/14'
		'Sunday August 17'
		'Today'
		'Tomorrow'
		'Every Monday 7-9pm'
		'Every April 15th'
		2014-08-19
		'Tomorrow at 6pm'
		'6pm Tomorrow'
		
	a chart of all the temporal data types, and collections of temporal data types:
				single		collection
	instant		instant
	time		time
	day			date		dayO
	range		timeo		timeoDefinition
	other		weekDay
				monthDay
	
	date - specifies a calendar date
		represented interchangeably by any of these data types:
			text date (e.g. text_startDate)
				2014-07-04
			numeric date (e.g. numeric_startDate) - specifies midnight on a certain day
				0
				1404532800	(2014-07-05 16:30:00)
				// TODO: change to numeric day, as in number of days since jan 1 1970
			human date (e.g. human_startDate) - human-readable date. there are multiple values for a single date - see /engines/temporal/dateHumanToText
				Friday September 19 2015
				9/11/15
				Sept. 19 2015
				
	dayO - also known as a Day Definition object. describes a date or multiple dates - the set of all dates in which this event occurs (technically, the dates which the event starts)
		represented interchangeably by any of these data types:
			component
				array(
					recursWeekly
					startDate
					startWeekday
					[endWeekday]
				)
				TODO: develop complete data type
			text
				w7				("weekly on day 7" aka every Sunday)
				o2014-10-03		("once on 2014-10-03")
				
	date fragments
		weekDay (formerly weekday) - specifies a day of the week
			represented interchangeably by any of these data types:
				numeric weekday (e.g. numeric_startWeekday) - specifies a day of the week
					1		(monday)
					5		(friday)
					7		(sunday)
				human weekday (e.g. human_nowWeekday)
					Mon
					Monday
					Tues
					Sunday
		monthDay (formerly day) - specifies a day of the month
			numeric day (e.g. numeric_day)
				1
				14
				31
				
	time - specifies a specific instant within a day. beware, some days may have two of the same time - for instance, on daylight savings 1:00am may occur twice
	and
	time interval - specifies an interval of time. can also be thought of as the amount of time passed since midnight to represent the time of day
		represented interchangeably by any of these data types:
			numeric hour (e.g. numeric_startHour, num_duration) - specifies a certain interval or the time since midnight (time of day). like military time but without leading zeros
				30		(12:30am)
				500		(5am)
				530		(5:30am)
				1700	(5pm)
				1730	(5:30pm)
			decimal hour (e.g. decimal_startHour) - specifies a certain time of day (any decimal but .5 is rejected)
				0		(midnight)
				17		(5pm)
				23.5	(11:30pm)
				24?
			numeric interval - time interval in seconds
				0		(midnight)
				43200	(noon)
			time pair
				array('hours', 'minutes')
				array(23, 30)
			human time (e.g. human_startTime) - human-readable time. there are multiple values for a single time - see /engines/temporal/hourNumberToString
				5pm
				5:00pm
				Noon
				12p
				7:30pm
				
	instant (formerly known as dateTime) - specifies one single instant in eternity. 
		represented interchangeably by any of these data types:
			numeric instant (aka dateTime, timestamp, epoch)
				0
				1404505800	(2014-07-04 16:30:00)
			text dateTime aka SQL time (e.g. text_startDateTime] - a specific instant represented in SQL format. possibly beware, some days may have two of the same time - for instance, on daylight savings 1:00am may occur twice
				2014-07-04 16:30:00
			pair instant
				array(
					'text_date' => '2014-08-15',
					'hour' => 1800,
				)
			human - human readable description of one instant in time
				'2:30pm 4/15/2016'
				'11am tomorrow (Friday March 11)'
	
	timeo - also known as a Time Object or a Time Range Object. Contains all temporal info needed to describe one instance of an event, from beginning instant to end instant
		represented interchangeably by any of these data types:
			components
				array(
					startDate as text_date
					startHour as numeric_hour
					[endDate] as text_date
					endHour as numeric_hour
					allDay as bool <-- eventually obsolete
				)
			text
				array(
					start => text_startInstant
					end => text_endInstant
				)
			numeric
				array(
					start => numeric_startInstant
					end => numeric_endInstant
				)
			human - human readable description of one range in time
				'6p-8p Tomorrow'
				'All Day Friday November 28th'
				
	timeoDefinition - also known as Timeo Definition Object or Time Range Definition Object. Describes all necessary temporal info to describe EVERY instance of an event.
		represented interchangeably by any of these data types:
			component
				array(
					recursWeekly as bool
					startDate as text_date
					startWeekday as ?
					startHour as numeric_hour
					[endWeekday] as ?
					endHour as numeric_hour
					allDay as bool <-- eventually obsolete
				)
				TODO: develop complete data type
			human - human readable description of one or more ranges in time
				'6p-8p Tomorrow'
				'Noon-4pm every Friday'
				'All day every Wednesday'
				'8p-11p this Friday and Saturday'
				
	other time & event related types
		
		timeTarget - all the data needed to describe which part of eternity we're targeting, whether it be an instant or a range (specified when we want to return a set of event results)
			array(
				'text_date' => '2014-08-19',
				'isNow' => false, // the date we're looking for is not the current day
			)
			or
			array(
				'text_date' => '2014-08-19',
				'num_hour' => 1000,
				'isNow' => false,
			)
			or
			array(
				'text_date' => '2014-08-15',
				'num_hour' => 1700,
				'isNow' => true, // the date and time we're looking for happens to be the current date and time
			)
			
		timeContext - additional context about a given date, time, or instant. given a timeo and a timeTarget, you can calculate the timeContext
			works like this:
				event									event
					other data								other data
					timeo			then get a				timeo
				event				timeTarget....			timeContext
					other data							event
					timeo									other data
				.										timeo
				.											timeContext
			array(
				isToday => true
				isDuring => true
				isNow => true
				text_time => 'Right Now'
				text_date => 'Today'
			)
			FORMERLY: contextualized timeo - all the fundamentally necessary timeo data, PLUS extra info for logic and rendering
				array(
					startDate
					startHour
					[endDate]
					endHour
					allDay <-- eventually obsolete
					context => array(
						isToday => true
						isDuring => true
						isNow => true
						text_time => 'Right Now'
						text_date => 'Today'
					)
				)
				TODO: eliminate this data type, and have a Time Context or Instant Context type instead. then to contextualize an event we already have the timeo and we add the contextualized data type alongside it
					
		eventContext - a work in progress.
			beforeTarget
			duringTarget
			afterTarget
			
		timeSolution - a set describing all events found during a search. this one is still a little sloppy.
			array(
				'empty'		 => array('Today', 				'Friday 8/15/14'	),
				'2014-08-16' => array('Tomorrow', 			'Saturday 8/16/14'	),
				'2014-08-17' => array('Sunday August 17', 	''					),
				'2014-08-18' => array('Monday August 18', 	''					),
			)
			or
			array(
				'2014-08-19' => array('Tuesday August 19',		''	),
				'2014-08-20' => array('Wednesday August 20', 	''	),
				'2014-08-22' => array('Friday August 22',		''	),				
			)
			or
			array(
				'during' => 	array('Tuesday August 19 at 5pm', 	''			),
				'2014-08-19' => array('', 							'Later On'	),
				'2014-08-20' => array('Wednesday August 20', 		''			),
				'2014-08-21' => array('Thursday August 21',			''			),
			)
			
	potentially ambiguous
		phrase
			today
			tomorrow
			next tuesday
			Thursday July 31
			2014-08-15
			2014-08-15 1930
			2014-08-15 at 7:30pm
		time range - limited usefulness because it can't describe any interval spanning past midnight without being ambiguous
			human time range
				'6-8pm'
				'all day'
				'11:30am to 3:00 pm'
				
<location data types>
	
	locationTarget
		array(
			'type', // city, region, device, point, or text
			'text',
			'numeric' => array(
				'lat' => $lat,
				'lng' => $lng,
			),
			'radius' => array(
				'miles',
				'text',
			),
		);		
																																										city	region	device	text	point
		is this an actual locatable place on the earth? (GPS coords, street address, or intersection - as opposed to a city, a neighborhood, etc.)						n		n		y		y or n	y
		is this location associated with a defined boundary of any kind?																								y		y		n		y or n	n
		is this location the user's current location that follows them around, either on a desktop or handheld device? (as opposed to something the user typed in)		n		n		y		n		n
		
	locationSolution
		array(
		
		
		)

<file data types>
	
	filePNE - Stands for Path + Name + Extension(s), e.g. /var/www/versions/xx/app/cron/daily.php
	
	fileo - a file object. contains a filename and an optional relative path
		array(
			'filename' => 'something.php',
			'path' => array(
				'action',
				'pages',
				'mod',
			),
		)
	TODO: change to array('path', 'name', 'extension')
		
	? - e.g. /sites/chewitt/actions/pages/full/event/edit	
	
	? - edit
	
<stats object>
	
	an array of chewitt.com statistics in the following format:
	
	144 => array( // 144 is the number of days since launch
		'venues' => array(
			'current' => array(
				2 => 120,  //2 is the city id
				3 => 409,
			'old' => array(
				2 => 4,
				3 => 22,
			)
		),
		'users' => array(
			'current' => array(
				2 => 120,
				3 => 409,
			'invited' => array(
				2 => 123,
				3 => 356,
			),
		),
		'events' => array(
			'currentUnique' => array(
				2 => 120,
				3 => 409,
			),
			'currentRecurring' => array(
				2 => 120,
				3 => 409,
			),
			'stale' => array( // recurring events that have been automatically flagged
				2 => 20,
				3 => 49,
			),
			'deleted' => array( // recurring events that were confirmed to no longer apply, and (occasionally) unique events that were cancelled before they happened
				2 => 12,
				3 => 130,
			),
			'past' => array( // unique events that have already occurred
				2 => 430,
				3 => 1187,
			),
		),
	)

<code stats object>

	an array of app and site code statistics in the following format:
	
	24 => array( // 24 is the number of days since launch
		'code' => array(
			'totalLines' => 39750,
			'programLines' => array(
				'app' => 12000,
				'chewitt' => 10000,
				'wsih' => 4000,
			),
			'testLines' => array(
				'app' => 3000
				'chewitt' => 1000,
				'wsih' => 200,
			),
			'files' => array(
				'app' => 160
				'chewitt' => 110,
				'wsih' => 16,
			),
		),
		'actions' => array(
			'pages' => array(
				'chewitt' => 60,
				'wsih' => 4,
			),
			'ajax' => array(
				'chewitt' => 40,
				'wsih' => 3,
			),
		),
	),

<other data types>
	website address
		string
			google.com
			http://www.cjecksphilly.com/specials.php?day=Wednesday
		array - the most precise way to describe a location within our own site
			array()							(chewitt.com homepage)
			array('events', 'search')
			array('event', 39)
		href segments - an array containing both the most-human-friendly and the most-machine-friendly versions
			array('title' => 'google.com', 'url' => 'http://google.com')
			array('title' => 'cjecksphilly.com/specials.php?day=Wednesday', 'url' => 'http://www.cjecksphilly.com/specials.php?day=Wednesday')
			
	request object - everything we need to know to generate a response

<action>

init object is in the format:
	array(
		'access' => array('admin', true),
		'params' => array(
			array('name' => 'id', 'type' => 'non-negative int', 'source' => 'path', 'required' => true, 'default' => null)
		),
		'render' => array(
			'title' => 'User Agent Details',
			'layout' => 'minor',
			'subTitle' => 'User Agent Details',
		),
	);

<engine>

[description]

aka:
	function
	pure
	pure function
	definition
	translator
	transformer
	converter
	scope
	lambda
	mapper
	computation
	self-contained
	standalone
	autonomous
	enclosed
	independent
	discrete
	deterministic
	...

advantages of engines over functions:
	- named parameters
		- only way to do this in native PHP is by passing an associative array, but then we lose type hinting, "required" validation, & default values
	- advanced parameter validation ('type' => 'positive int', 'type' => 'city id', ...)
	- test data is stored in the same place as the code being tested
	- easy to wrap with other code for benchmarking, debugging, etc.
	- [TODO maybe someday] return value validation
advantages over OO:
	- output is predictable based solely on input, not dependent on external state ("referential transparency")
		- cacheable ("memoization")
		- doesn't change external state (no "side effects")
disadvantages:
	- engine name is not included in stack traces, we must remember to add that to the error message manually.
	- engine.php makes a lot of appearances in the call stack
	- (solved by opcode caching) the code for an engine must be re-opened and re-parsed every time it's called, instead of just once for the request
	- engines are invisible to IDEs

Four standard methods:
	Create / add				(REST: post, SQL: insert)
	Read / get / retrieve		(REST: get, SQL: select)
	Update / edit / modify		(REST: ?, SQL: update)
	Delete / remove / destroy	(REST: delete, SQL: delete)
	> Create or update			> (REST: put, SQL: ?)
	> Create if doesn't exist	> (REST: ?, SQL: ?)
Plus:
	Validate - "is this likely to work when I do it for real?" 
Not proper:
	Search - really just objectList->get

<task>

Loading a site from an existing repository

Steps:
	...

Creating a new site from scratch

Steps: