From ede5d9f3fea43ccf09e7d34ff16feaa61ff54f5b Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Fri, 4 May 2012 17:20:02 +0200 Subject: [PATCH] Initial commit --- LICENSE | 14 + base.php | 41 +++ class.base.php | 154 ++++++++++ class.databaserecord.php | 404 ++++++++++++++++++++++++++ class.localizer.php | 79 +++++ class.templater.php | 132 +++++++++ components/component.errorhandler.php | 72 +++++ components/component.formbuilder.php | 319 ++++++++++++++++++++ components/component.router.php | 62 ++++ config.mysql.sample.php | 19 ++ config.sample.php | 42 +++ include.constants.php | 24 ++ include.datetime.php | 180 ++++++++++++ include.dependencies.php | 101 +++++++ include.exceptions.php | 23 ++ include.memcache.php | 156 ++++++++++ include.misc.php | 120 ++++++++ include.mysql.php | 27 ++ include.session.php | 16 + 19 files changed, 1985 insertions(+) create mode 100644 LICENSE create mode 100644 base.php create mode 100644 class.base.php create mode 100644 class.databaserecord.php create mode 100644 class.localizer.php create mode 100644 class.templater.php create mode 100644 components/component.errorhandler.php create mode 100644 components/component.formbuilder.php create mode 100644 components/component.router.php create mode 100644 config.mysql.sample.php create mode 100644 config.sample.php create mode 100644 include.constants.php create mode 100644 include.datetime.php create mode 100644 include.dependencies.php create mode 100644 include.exceptions.php create mode 100644 include.memcache.php create mode 100644 include.misc.php create mode 100644 include.mysql.php create mode 100644 include.session.php diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/base.php b/base.php new file mode 100644 index 0000000..9dd7062 --- /dev/null +++ b/base.php @@ -0,0 +1,41 @@ +Load($cphp_locale_name); + +setlocale(LC_ALL, $locale->locale); + +require("class.base.php"); +require("class.databaserecord.php"); + +foreach($cphp_components as $component) +{ + require("components/component.{$component}.php"); +} diff --git a/class.base.php b/class.base.php new file mode 100644 index 0000000..fe58777 --- /dev/null +++ b/class.base.php @@ -0,0 +1,154 @@ +$variable_name) && is_numeric($this->$variable_name)) + { + $timestamp = $this->$variable_name; + + if($timestamp > time()) + { + $sTimeAgo = $locale->strings['event-future']; + } + elseif($timestamp == time()) + { + $sTimeAgo = $locale->strings['event-now']; + } + else + { + $date1 = new DateTime("@{$timestamp}", new DateTimeZone("GMT")); + $date2 = new DateTime("now", new DateTimeZone("GMT")); + + $interval = $date1->diff($date2); + $years = (int)$interval->format("%G"); + $months = (int)$interval->format("%m"); + $weeks = (int)$interval->format("%U"); + $days = (int)$interval->format("%d"); + $hours = (int)$interval->format("%H"); + $minutes = (int)$interval->format("%i"); + $seconds = (int)$interval->format("%S"); + + if($years > 1) + { + $sTimeAgo = sprintf($locale->strings['event-years-ago'], $years); + } + elseif($years == 1) + { + $sTimeAgo = $locale->strings['event-1year-ago']; + } + elseif($months > 1) + { + $sTimeAgo = sprintf($locale->strings['event-months-ago'], $months); + } + elseif($months == 1) + { + $sTimeAgo = $locale->strings['event-1month-ago']; + } + elseif($weeks > 1) + { + $sTimeAgo = sprintf($locale->strings['event-weeks-ago'], $weeks); + } + elseif($weeks == 1) + { + $sTimeAgo = $locale->strings['event-1week-ago']; + } + elseif($days > 1) + { + $sTimeAgo = sprintf($locale->strings['event-days-ago'], $days); + } + elseif($days == 1) + { + $sTimeAgo = $locale->strings['event-1day-ago']; + } + elseif($hours > 1) + { + $sTimeAgo = sprintf($locale->strings['event-hours-ago'], $hours); + } + elseif($hours == 1) + { + $sTimeAgo = $locale->strings['event-1hour-ago']; + } + elseif($minutes > 1) + { + $sTimeAgo = sprintf($locale->strings['event-minutes-ago'], $minutes); + } + elseif($minutes == 1) + { + $sTimeAgo = $locale->strings['event-1minute-ago']; + } + elseif($seconds > 1) + { + $sTimeAgo = sprintf($locale->strings['event-seconds-ago'], $seconds); + } + elseif($seconds == 1) + { + $sTimeAgo = $locale->strings['event-1second-ago']; + } + else + { + // If you see this, there's probably something wrong. + $sTimeAgo = $locale->strings['event-past']; + } + + } + + $sDate = local_from_unix($timestamp, $locale->datetime_long); + + return $this->RenderTemplateExternal($template, array( + 'local-time' => $sDate, + 'time-ago' => $sTimeAgo, + 'timestamp' => $timestamp + )); + } + else + { + $classname = get_class($this); + throw new Exception("Property {$classname}.{$property} does not exist or is not of a valid format."); + } + } + + public function RenderTemplateExternal($template, $strings) + { + return $this->DoRenderTemplate($template, $strings); + } + + public function DoRenderTemplate($template, $strings) + { + global $locale; + + try + { + $tpl = new Templater(); + $tpl->Load($template); + $tpl->Localize($locale->strings); + $tpl->Compile($strings); + return $tpl->Render(); + } + catch(Exception $e) + { + $classname = get_class($this); + throw new Exception("Failed to render template {$classname}.{$template}."); + } + } +} diff --git a/class.databaserecord.php b/class.databaserecord.php new file mode 100644 index 0000000..0ee2680 --- /dev/null +++ b/class.databaserecord.php @@ -0,0 +1,404 @@ +ConstructDataset($uDataSource, $uCommunityId); + $this->EventConstructed(); + } + + public function ConstructDataset($uDataSource, $uCommunityId = 0) + { + $bind_datasets = true; + + if(is_numeric($uDataSource)) + { + if($uDataSource != 0) + { + if(!empty($this->fill_query)) + { + $this->sId = (is_numeric($uDataSource)) ? $uDataSource : 0; + + $query = sprintf($this->fill_query, $uDataSource); + if($result = mysql_query_cached($query, $this->query_cache)) + { + $uDataSource = $result->data[0]; + } + else + { + $classname = get_class($this); + throw new NotFoundException("Could not locate {$classname} {$uDataSource} in database."); + } + } + else + { + $classname = get_class($this); + throw new PrototypeException("No fill query defined for {$classname} class."); + } + } + else + { + $bind_datasets = false; + } + } + elseif(is_object($uDataSource)) + { + if(isset($uDataSource->data[0])) + { + $uDataSource = $uDataSource->data[0]; + } + else + { + throw new NotFoundException("No result set present in object."); + } + } + elseif(is_array($uDataSource)) + { + if(isset($uDataSource[0])) + { + $uDataSource = $uDataSource[0]; + } + } + else + { + $classname = get_class($this); + throw new ConstructorException("Invalid type passed on to constructor for object of type {$classname}."); + } + + if($bind_datasets === true) + { + $this->sId = (is_numeric($uDataSource['Id'])) ? $uDataSource['Id'] : 0; + + $this->uData = $uDataSource; + + foreach($this->prototype as $type => $dataset) + { + $this->BindDataset($type, $dataset); + } + + $this->sFound = true; + } + else + { + $this->sFound = false; + } + + if(!empty($uCommunityId) && !empty($this->sCommunityId)) + { + $sCommunityId = (is_numeric($uCommunityId)) ? $uCommunityId : 0; + + if($sCommunityId != $this->sCommunity->sId) + { + $classname = get_class($this); + throw new OwnershipException("{$classname} {$this->sId} does not belong to Community {$sCommunityId}."); + } + } + } + + public function BindDataset($type, $dataset) + { + global $cphp_class_map; + + if(is_array($dataset)) + { + foreach($dataset as $variable_name => $column_name) + { + $original_value = $this->uData[$column_name]; + + switch($type) + { + case "string": + $value = htmlspecialchars(stripslashes($original_value)); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "html": + $value = filter_html(stripslashes($original_value)); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "simplehtml": + $value = filter_html_strict(stripslashes($original_value)); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "nl2br": + $value = nl2br(htmlspecialchars(stripslashes($original_value)), false); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "numeric": + $value = (is_numeric($original_value)) ? $original_value : 0; + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "timestamp": + $value = unix_from_mysql($original_value); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "boolean": + $value = (empty($original_value)) ? false : true; + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "user": + $value = new User($original_value); + $variable_type = CPHP_VARIABLE_SAFE; + break; + case "none": + $value = $original_value; + $variable_type = CPHP_VARIABLE_UNSAFE; + break; + default: + $found = false; + foreach($cphp_class_map as $class_type => $class_name) + { + if($type == $class_type) + { + $value = new $class_name($original_value); + $variable_type = CPHP_VARIABLE_SAFE; + $found = true; + } + } + + if($found == false) + { + $classname = get_class($this); + throw new Exception("Cannot determine type of dataset ({$type}) passed on to {$classname}.BindDataset."); + break; + } + } + + if($variable_type == CPHP_VARIABLE_SAFE) + { + $variable_name_safe = "s" . $variable_name; + $this->$variable_name_safe = $value; + } + + $variable_name_unsafe = "u" . $variable_name; + $this->$variable_name_unsafe = $original_value; + } + } + else + { + $classname = get_class($this); + throw new Exception("Invalid dataset passed on to {$classname}.BindDataset."); + } + } + + public function DoRenderInternalTemplate() + { + if(!empty($this->render_template)) + { + $strings = array(); + foreach($this->prototype_render as $template_var => $object_var) + { + $variable_name = "s" . $object_var; + $strings[$template_var] = $this->$variable_name; + } + return $this->DoRenderTemplate($this->render_template, $strings); + } + else + { + $classname = get_class($this); + throw new Exception("Cannot render template: no template defined for {$classname} class."); + } + } + + public function InsertIntoDatabase() + { + if(!empty($this->verify_query)) + { + if($this->sId == 0) + { + $insert_mode = CPHP_INSERTMODE_INSERT; + } + else + { + $query = sprintf($this->verify_query, $this->sId); + if($result = mysql_query_cached($query)) + { + $insert_mode = CPHP_INSERTMODE_UPDATE; + } + else + { + $insert_mode = CPHP_INSERTMODE_INSERT; + } + } + + $element_list = array(); + + foreach($this->prototype as $type_key => $type_value) + { + foreach($type_value as $element_key => $element_value) + { + switch($type_key) + { + case "none": + case "numeric": + case "boolean": + case "timestamp": + case "string": + $element_list[$element_value] = array( + 'key' => $element_key, + 'type' => $type_key + ); + break; + default: + break; + } + } + } + + $sKeyList = array(); + $sValueList = array(); + + foreach($element_list as $sKey => $value) + { + $variable_name_safe = "s" . $value['key']; + $variable_name_unsafe = "u" . $value['key']; + + if(isset($this->$variable_name_safe) || isset($this->$variable_name_unsafe)) + { + switch($value['type']) + { + case "none": + $sFinalValue = mysql_real_escape_string($this->$variable_name_unsafe); + break; + case "numeric": + $number = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe; + $sFinalValue = (is_numeric($number)) ? $number : 0; + break; + case "boolean": + $bool = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe; + $sFinalValue = ($bool) ? "1" : "0"; + break; + case "timestamp": + $sFinalValue = (isset($this->$variable_name_safe)) ? mysql_from_unix($this->$variable_name_safe) : mysql_from_unix(unix_from_local($this->$variable_name_unsafe)); + break; + case "string": + $sFinalValue = (isset($this->$variable_name_unsafe)) ? mysql_real_escape_string($this->$variable_name_unsafe) : mysql_real_escape_string($this->$variable_name_safe); + break; + case "default": + $sFinalValue = mysql_real_escape_string($this->$variable_name_unsafe); + break; + } + + $sFinalValue = "'{$sFinalValue}'"; + $sKey = "`{$sKey}`"; + + $sKeyList[] = $sKey; + $sValueList[] = $sFinalValue; + } + else + { + $classname = get_class($this); + throw new Exception("Database insertion failed: prototype property {$value['key']} not found in object of type {$classname}."); + } + } + + + if($insert_mode == CPHP_INSERTMODE_INSERT) + { + $sQueryKeys = implode(", ", $sKeyList); + $sQueryValues = implode(", ", $sValueList); + $query = "INSERT INTO {$this->table_name} ({$sQueryKeys}) VALUES ({$sQueryValues})"; + } + elseif($insert_mode == CPHP_INSERTMODE_UPDATE) + { + $sKeyValueList = array(); + + for($i = 0; $i < count($sKeyList); $i++) + { + $sKey = $sKeyList[$i]; + $sValue = $sValueList[$i]; + $sKeyValueList[] = "{$sKey} = {$sValue}"; + } + + $sQueryKeysValues = implode(", ", $sKeyValueList); + $query = "UPDATE {$this->table_name} SET {$sQueryKeysValues} WHERE `Id` = '{$this->sId}'"; + } + + if($result = mysql_query($query)) + { + if($insert_mode == CPHP_INSERTMODE_INSERT) + { + $this->sId = mysql_insert_id(); + } + + $this->PurgeCache(); + + return $result; + } + else + { + $classname = get_class($this); + throw new DatabaseException("Database insertion query failed in object of type {$classname}. Error message: " . mysql_error()); + } + } + else + { + $classname = get_class($this); + throw new Exception("No verification query defined for {$classname} class."); + } + } + + public function RetrieveChildren($type, $field) + { + if(!isset($cphp_class_map[$type])) + { + $classname = get_class($this); + throw new NotFoundException("Non-existent 'type' argument passed on to {$classname}.RetrieveChildren function."); + } + + $parent_type = get_parent_class($cphp_class_map[$type]); + if($parent_type !== "CPHPDatabaseRecordClass") + { + $parent_type = ($parent_type === false) ? "NONE" : $parent_type; + $classname = get_class($this); + throw new TypeException("{$classname}.RetrieveChildren expected 'type' argument of parent-type CPHPDatabaseRecordClass, but got {$parent_type} instead."); + } + + $query = ""; + } + + public function PurgeCache() + { + $query = sprintf($this->fill_query, $this->sId); + $key = md5($query) . md5($query . "x"); + mc_delete($key); + } + + public function RenderTemplate($template = "") + { + if(!empty($template)) + { + $this->render_template = $template; + } + + return $this->DoRenderInternalTemplate(); + } + + // Define events + + protected function EventConstructed() { } +} diff --git a/class.localizer.php b/class.localizer.php new file mode 100644 index 0000000..1c4465d --- /dev/null +++ b/class.localizer.php @@ -0,0 +1,79 @@ +strings = array(); + $this->LoadInternal("english"); + $this->LoadInternal($locale); + } + + public function LoadInternal($locale) + { + global $cphp_locale_path, $cphp_locale_ext; + $lng_contents = file_get_contents("{$cphp_locale_path}/{$locale}.{$cphp_locale_ext}"); + if($lng_contents !== false) + { + $lines = explode("\n", $lng_contents); + foreach($lines as $line) + { + $line = str_replace("\r", "", $line); + if(preg_match("/(.+?[^\\\]);(.+)/", $line, $matches)) + { + $key = trim(str_replace("\;", ";", $matches[1])); + $value = trim(str_replace("\;", ";", $matches[2])); + switch($key) + { + case "_locale": + $this->locale = explode(",", $value); + break; + case "_datetime_short": + $this->datetime_short = $value; + break; + case "_datetime_long": + $this->datetime_long = $value; + break; + case "_date_short": + $this->date_short = $value; + break; + case "_date_long": + $this->date_long = $value; + break; + case "_time": + $this->time = $value; + break; + default: + $this->strings[$key] = $value; + break; + } + } + } + } + else + { + Throw new Exception("Failed to load locale {$locale}."); + } + } +} diff --git a/class.templater.php b/class.templater.php new file mode 100644 index 0000000..24da07e --- /dev/null +++ b/class.templater.php @@ -0,0 +1,132 @@ +basedir . $template . $this->extension); + $template_cache[$template] = $tpl_contents; + } + + if($tpl_contents !== false) + { + $this->tpl = $tpl_contents; + $this->tpl_rendered = $tpl_contents; + } + else + { + Throw new Exception("Failed to load template {$template}."); + } + } + + public function Reset() + { + if(!is_null($this->tpl)) + { + $this->tpl_rendered = $this->tpl; + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Localize($strings) + { + if(!is_null($this->tpl)) + { + preg_match_all("/<%!([a-zA-Z0-9_-]+)>/", $this->tpl_rendered, $strlist); + foreach($strlist[1] as $str) + { + if(isset($strings[$str])) + { + $this->tpl_rendered = str_replace("<%!{$str}>", $strings[$str], $this->tpl_rendered); + } + } + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Compile($strings) + { + if(!is_null($this->tpl)) + { + preg_match_all("/<%\?([a-zA-Z0-9_-]+)>/", $this->tpl_rendered, $strlist); + foreach($strlist[1] as $str) + { + if(isset($strings[$str])) + { + $this->tpl_rendered = str_replace("<%?{$str}>", $strings[$str], $this->tpl_rendered); + } + } + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Render() + { + if(!is_null($this->tpl)) + { + return $this->tpl_rendered; + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Output() + { + if(!is_null($this->tpl)) + { + echo($this->tpl_rendered); + } + else + { + Throw new Exception("No template loaded."); + } + } + + public static function InlineRender($templatename, $localize = array(), $compile = array()) + { + $template = new Templater(); + $template->Load($templatename); + $template->Localize($localize); + $template->Compile($compile); + return $template->Render(); + } +} diff --git a/components/component.errorhandler.php b/components/component.errorhandler.php new file mode 100644 index 0000000..7a53977 --- /dev/null +++ b/components/component.errorhandler.php @@ -0,0 +1,72 @@ +sErrorType = $type; + $this->sLogError = $log; + $this->sTitle = $title; + $this->sMessage = $message; + } + + public function LogError($context, $message) + { + // FIXME placeholder function, error logging has not been implemented yet + } + + public function Render() + { + global $locale; + + $template['error'] = new Templater(); + + switch($this->sErrorType) + { + case CPHP_ERRORHANDLER_TYPE_ERROR: + $template['error']->Load("errorhandler.error"); + break; + case CPHP_ERRORHANDLER_TYPE_INFO: + $template['error']->Load("errorhandler.info"); + break; + case CPHP_ERRORHANDLER_TYPE_WARNING: + $template['error']->Load("errorhandler.warning"); + break; + case CPHP_ERRORHANDLER_TYPE_SUCCESS: + $template['error']->Load("errorhandler.success"); + break; + } + + $template['error']->Localize($locale->strings); + $template['error']->Compile(array( + 'title' => $this->sTitle, + 'message' => $this->sMessage + )); + + return $template['error']->Render(); + } +} +?> diff --git a/components/component.formbuilder.php b/components/component.formbuilder.php new file mode 100644 index 0000000..d3b8d5a --- /dev/null +++ b/components/component.formbuilder.php @@ -0,0 +1,319 @@ +parameters[$key] = $value; + } + + public function RenderParameters($parameters) + { + if(empty($parameters)) + { + return ""; + } + + $rendered = array(); + + foreach($parameters as $key => $value) + { + $value = utf8entities($value); + $rendered[] = "{$key}=\"{$value}\""; + } + + return " " . implode(" ", $rendered); + } + + public function RenderNote() + { + if(!empty($this->note)) + { + return "
{$this->note}
"; + } + else + { + return ""; + } + } +} + +abstract class CPHPFormBuilderContainer extends CPHPFormBuilderBaseClass +{ + public $elements = array(); + + public function AddElement($element) + { + $this->elements[] = $element; + } +} + +class CPHPFormBuilder extends CPHPFormBuilderContainer +{ + public $method = ""; + public $action = ""; + + public function __construct($method, $target) + { + $this->method = strtolower($method); + $this->action = $target; + } + + public function Render() + { + $rendered_elements = ""; + + foreach($this->elements as $element) + { + $rendered_elements .= $element->Render(); + } + + $this->AddParameter("method", $this->method); + $this->AddParameter("action", $this->action); + + $rendered_parameters = $this->RenderParameters($this->parameters); + + return "{$rendered_elements}"; + } +} + +class CPHPFormSection extends CPHPFormBuilderContainer +{ + public $label = ""; + public $fieldset = true; + public $classname = ""; + + public function __construct($fieldset = true, $label = "") + { + if(!empty($label)) + { + $this->label = $label; + } + + $this->fieldset = $fieldset; + } + + public function Render() + { + if(!empty($this->label)) + { + $legend = "{$this->label}"; + } + else + { + $legend = ""; + } + + if($this->fieldset === true) + { + $this->classname = trim("{$this->classname} cphp_fbd_fieldset"); + } + + $rendered_elements = ""; + + foreach($this->elements as $element) + { + $rendered_elements .= $element->Render(); + } + + if($this->fieldset === true) + { + $this->AddParameter("class", $this->classname); + $rendered_parameters = $this->RenderParameters($this->parameters); + return "{$legend}
{$rendered_elements}
"; + } + else + { + return "
{$rendered_elements}
"; + } + } +} + +abstract class CPHPFormInputElement extends CPHPFormBuilderBaseClass +{ + public $id = ""; + public $name = ""; + public $value = ""; + public $label = ""; + + public function __construct($label, $name, $value = "", $note = "", $id = "") + { + global $cphp_formbuilder_increment; + + $this->name = $name; + $this->value = $value; + $this->label = $label; + $this->note = $note; + + if(empty($id)) + { + $this->id = "cphp_fbd_{$cphp_formbuilder_increment}"; + $cphp_formbuilder_increment += 1; + } + else + { + $this->id = $id; + } + } + +} + +abstract class CPHPFormInput extends CPHPFormInputElement +{ + public function Render() + { + $this->AddParameter("id", $this->id); + $this->AddParameter("type", $this->type); + $this->AddParameter("name", $this->name); + $this->AddParameter("value", $this->value); + + $rendered_parameters = $this->RenderParameters($this->parameters); + $rendered_note = $this->RenderNote(); + + return "
{$this->label}{$rendered_note}
"; + } +} + +class CPHPFormTextInput extends CPHPFormInput +{ + public $type = "text"; +} + +class CPHPFormPasswordInput extends CPHPFormInput +{ + public $type = "password"; +} + +class CPHPFormDateInput extends CPHPFormInput +{ + public $type = "date"; +} + +class CPHPFormTimeInput extends CPHPFormInput +{ + public $type = "time"; +} + +class CPHPFormEmailInput extends CPHPFormInput +{ + public $type = "email"; +} + +class CPHPFormUrlInput extends CPHPFormInput +{ + public $type = "url"; +} + +class CPHPFormRangeInput extends CPHPFormInput +{ + public $type = "range"; +} + +class CPHPFormColorInput extends CPHPFormInput +{ + public $type = "color"; +} + +class CPHPFormSearchInput extends CPHPFormInput +{ + public $type = "search"; +} + +class CPHPFormCheckboxGroup extends CPHPFormBuilderContainer +{ + public function __construct($label, $note = "") + { + global $cphp_formbuilder_increment; + + $this->label = $label; + $this->note = $note; + } + + public function Render() + { + $rendered_note = $this->RenderNote(); + + $rendered_elements = ""; + + foreach($this->elements as $element) + { + $rendered_elements .= $element->Render(); + } + + return "
{$this->label}{$rendered_note}
{$rendered_elements}
"; + } +} + +class CPHPFormCheckbox extends CPHPFormInputElement +{ + + public function Render() + { + $this->AddParameter("id", $this->id); + $this->AddParameter("type", "checkbox"); + $this->AddParameter("name", $this->name); + + if($this->value === true) + { + $this->AddParameter("checked", ""); + } + + $rendered_parameters = $this->RenderParameters($this->parameters); + $rendered_note = $this->RenderNote(); + return "
"; + } +} + +class CPHPFormRadioButton extends CPHPFormInput +{ + public $type = "radio"; +} + +class CPHPFormButton extends CPHPFormInputElement +{ + public $type = "button"; + + public function Render() + { + $this->AddParameter("type", $this->type); + $this->AddParameter("name", $this->name); + $this->AddParameter("value", $this->value); + + $rendered_parameters = $this->RenderParameters($this->parameters); + + return "
{$this->label}
"; + } +} + +class CPHPFormSubmitButton extends CPHPFormButton +{ + public $type = "submit"; +} + +class CPHPFormResetButton extends CPHPFormButton +{ + public $type = "reset"; +} + +class CPHPFormSelect extends CPHPFormInputElement +{ + public $options = array(); +} +?> diff --git a/components/component.router.php b/components/component.router.php new file mode 100644 index 0000000..2d54e8a --- /dev/null +++ b/components/component.router.php @@ -0,0 +1,62 @@ +custom_query)) + { + $requestpath = $this->custom_query; + } + else + { + if(!empty($_SERVER['REQUEST_URI'])) + { + $requestpath = trim($_SERVER['REQUEST_URI']); + } + else + { + $requestpath = "/"; + } + } + + $found = false; // Workaround because a break after an include apparently doesn't work in PHP. + + foreach($this->routes as $priority) + { + foreach($priority as $route_regex => $route_destination) + { + if($found === false) + { + $regex = str_replace("/", "\/", $route_regex); + if(preg_match("/{$regex}/i", $requestpath, $matches)) + { + $this->uParameters = $matches; + include($route_destination); + $found = true; + } + } + } + } + } +} +?> diff --git a/config.mysql.sample.php b/config.mysql.sample.php new file mode 100644 index 0000000..ef8c295 --- /dev/null +++ b/config.mysql.sample.php @@ -0,0 +1,19 @@ + diff --git a/config.sample.php b/config.sample.php new file mode 100644 index 0000000..dfcdfa2 --- /dev/null +++ b/config.sample.php @@ -0,0 +1,42 @@ + "ClassA", + 'classb' => "ClassB" +); + +$cphp_locale_name = "english"; +$cphp_locale_path = "locales"; +$cphp_locale_ext = "lng"; + +$cphp_usersettings[CPHP_SETTING_TIMEZONE] = "Europe/Amsterdam"; + +/* These are the memcache settings. You will need to have memcache set + * up on your server to use these. Compression requires zlib. */ +$cphp_memcache_enabled = true; // Whether to user memcache. +$cphp_memcache_server = "localhost"; // The hostname of the memcached +$cphp_memcache_port = 11211; // The port number of memcached +$cphp_memcache_compressed = true; // Whether to compress memcache objects + +$cphp_mysql_enabled = true; + +require("config.mysql.php"); + +$cphp_components = array( + "router", + "errorhandler", + "formbuilder" +); diff --git a/include.constants.php b/include.constants.php new file mode 100644 index 0000000..49265a1 --- /dev/null +++ b/include.constants.php @@ -0,0 +1,24 @@ + '(GMT-12:00) International Date Line West', + 'Pacific/Midway' => '(GMT-11:00) Midway Island', + 'Pacific/Samoa' => '(GMT-11:00) Samoa', + 'Pacific/Honolulu' => '(GMT-10:00) Hawaii', + 'America/Anchorage' => '(GMT-09:00) Alaska', + 'America/Los_Angeles' => '(GMT-08:00) Pacific Time (US & Canada)', + 'America/Tijuana' => '(GMT-08:00) Tijuana, Baja California', + 'America/Denver' => '(GMT-07:00) Mountain Time (US & Canada)', + 'America/Chihuahua' => '(GMT-07:00) Chihuahua', + 'America/Mazatlan' => '(GMT-07:00) Mazatlan', + 'America/Phoenix' => '(GMT-07:00) Arizona', + 'America/Regina' => '(GMT-06:00) Saskatchewan', + 'America/Tegucigalpa' => '(GMT-06:00) Central America', + 'America/Chicago' => '(GMT-06:00) Central Time (US & Canada)', + 'America/Mexico_City' => '(GMT-06:00) Mexico City', + 'America/Monterrey' => '(GMT-06:00) Monterrey', + 'America/New_York' => '(GMT-05:00) Eastern Time (US & Canada)', + 'America/Bogota' => '(GMT-05:00) Bogota', + 'America/Lima' => '(GMT-05:00) Lima', + 'America/Rio_Branco' => '(GMT-05:00) Rio Branco', + 'America/Indiana/Indianapolis' => '(GMT-05:00) Indiana (East)', + 'America/Caracas' => '(GMT-04:30) Caracas', + 'America/Halifax' => '(GMT-04:00) Atlantic Time (Canada)', + 'America/Manaus' => '(GMT-04:00) Manaus', + 'America/Santiago' => '(GMT-04:00) Santiago', + 'America/La_Paz' => '(GMT-04:00) La Paz', + 'America/St_Johns' => '(GMT-03:30) Newfoundland', + 'America/Argentina/Buenos_Aires' => '(GMT-03:00) Georgetown', + 'America/Sao_Paulo' => '(GMT-03:00) Brasilia', + 'America/Godthab' => '(GMT-03:00) Greenland', + 'America/Montevideo' => '(GMT-03:00) Montevideo', + 'Atlantic/South_Georgia' => '(GMT-02:00) Mid-Atlantic', + 'Atlantic/Azores' => '(GMT-01:00) Azores', + 'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.', + 'Europe/Dublin' => '(GMT) Dublin', + 'Europe/Lisbon' => '(GMT) Lisbon', + 'Europe/London' => '(GMT) London', + 'Africa/Monrovia' => '(GMT) Monrovia', + 'Atlantic/Reykjavik' => '(GMT) Reykjavik', + 'Africa/Casablanca' => '(GMT) Casablanca', + 'Europe/Belgrade' => '(GMT+01:00) Belgrade', + 'Europe/Bratislava' => '(GMT+01:00) Bratislava', + 'Europe/Budapest' => '(GMT+01:00) Budapest', + 'Europe/Ljubljana' => '(GMT+01:00) Ljubljana', + 'Europe/Prague' => '(GMT+01:00) Prague', + 'Europe/Sarajevo' => '(GMT+01:00) Sarajevo', + 'Europe/Skopje' => '(GMT+01:00) Skopje', + 'Europe/Warsaw' => '(GMT+01:00) Warsaw', + 'Europe/Zagreb' => '(GMT+01:00) Zagreb', + 'Europe/Brussels' => '(GMT+01:00) Brussels', + 'Europe/Copenhagen' => '(GMT+01:00) Copenhagen', + 'Europe/Madrid' => '(GMT+01:00) Madrid', + 'Europe/Paris' => '(GMT+01:00) Paris', + 'Africa/Algiers' => '(GMT+01:00) West Central Africa', + 'Europe/Amsterdam' => '(GMT+01:00) Amsterdam', + 'Europe/Berlin' => '(GMT+01:00) Berlin', + 'Europe/Rome' => '(GMT+01:00) Rome', + 'Europe/Stockholm' => '(GMT+01:00) Stockholm', + 'Europe/Vienna' => '(GMT+01:00) Vienna', + 'Europe/Minsk' => '(GMT+02:00) Minsk', + 'Africa/Cairo' => '(GMT+02:00) Cairo', + 'Europe/Helsinki' => '(GMT+02:00) Helsinki', + 'Europe/Riga' => '(GMT+02:00) Riga', + 'Europe/Sofia' => '(GMT+02:00) Sofia', + 'Europe/Tallinn' => '(GMT+02:00) Tallinn', + 'Europe/Vilnius' => '(GMT+02:00) Vilnius', + 'Europe/Athens' => '(GMT+02:00) Athens', + 'Europe/Bucharest' => '(GMT+02:00) Bucharest', + 'Europe/Istanbul' => '(GMT+02:00) Istanbul', + 'Asia/Jerusalem' => '(GMT+02:00) Jerusalem', + 'Asia/Amman' => '(GMT+02:00) Amman', + 'Asia/Beirut' => '(GMT+02:00) Beirut', + 'Africa/Windhoek' => '(GMT+02:00) Windhoek', + 'Africa/Harare' => '(GMT+02:00) Harare', + 'Asia/Kuwait' => '(GMT+03:00) Kuwait', + 'Asia/Riyadh' => '(GMT+03:00) Riyadh', + 'Asia/Baghdad' => '(GMT+03:00) Baghdad', + 'Africa/Nairobi' => '(GMT+03:00) Nairobi', + 'Asia/Tbilisi' => '(GMT+03:00) Tbilisi', + 'Europe/Moscow' => '(GMT+03:00) Moscow', + 'Europe/Volgograd' => '(GMT+03:00) Volgograd', + 'Asia/Tehran' => '(GMT+03:30) Tehran', + 'Asia/Muscat' => '(GMT+04:00) Muscat', + 'Asia/Baku' => '(GMT+04:00) Baku', + 'Asia/Yerevan' => '(GMT+04:00) Yerevan', + 'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg', + 'Asia/Karachi' => '(GMT+05:00) Karachi', + 'Asia/Tashkent' => '(GMT+05:00) Tashkent', + 'Asia/Kolkata' => '(GMT+05:30) Calcutta', + 'Asia/Colombo' => '(GMT+05:30) Sri Jayawardenepura', + 'Asia/Katmandu' => '(GMT+05:45) Kathmandu', + 'Asia/Dhaka' => '(GMT+06:00) Dhaka', + 'Asia/Almaty' => '(GMT+06:00) Almaty', + 'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk', + 'Asia/Rangoon' => '(GMT+06:30) Yangon (Rangoon)', + 'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk', + 'Asia/Bangkok' => '(GMT+07:00) Bangkok', + 'Asia/Jakarta' => '(GMT+07:00) Jakarta', + 'Asia/Brunei' => '(GMT+08:00) Beijing', + 'Asia/Chongqing' => '(GMT+08:00) Chongqing', + 'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong', + 'Asia/Urumqi' => '(GMT+08:00) Urumqi', + 'Asia/Irkutsk' => '(GMT+08:00) Irkutsk', + 'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar', + 'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur', + 'Asia/Singapore' => '(GMT+08:00) Singapore', + 'Asia/Taipei' => '(GMT+08:00) Taipei', + 'Australia/Perth' => '(GMT+08:00) Perth', + 'Asia/Seoul' => '(GMT+09:00) Seoul', + 'Asia/Tokyo' => '(GMT+09:00) Tokyo', + 'Asia/Yakutsk' => '(GMT+09:00) Yakutsk', + 'Australia/Darwin' => '(GMT+09:30) Darwin', + 'Australia/Adelaide' => '(GMT+09:30) Adelaide', + 'Australia/Canberra' => '(GMT+10:00) Canberra', + 'Australia/Melbourne' => '(GMT+10:00) Melbourne', + 'Australia/Sydney' => '(GMT+10:00) Sydney', + 'Australia/Brisbane' => '(GMT+10:00) Brisbane', + 'Australia/Hobart' => '(GMT+10:00) Hobart', + 'Asia/Vladivostok' => '(GMT+10:00) Vladivostok', + 'Pacific/Guam' => '(GMT+10:00) Guam', + 'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby', + 'Asia/Magadan' => '(GMT+11:00) Magadan', + 'Pacific/Fiji' => '(GMT+12:00) Fiji', + 'Asia/Kamchatka' => '(GMT+12:00) Kamchatka', + 'Pacific/Auckland' => '(GMT+12:00) Auckland', + 'Pacific/Tongatapu' => '(GMT+13:00) Nukualofa' +); + +function unix_from_local($timestamp) +{ + global $user_preferences; + date_default_timezone_set($user_preferences[CPHP_SETTING_TIMEZONE]); + return strtotime($timestamp); +} + +function unix_from_mysql($timestamp) +{ + date_default_timezone_set("GMT"); + return strtotime($timestamp); +} + +function local_from_unix($timestamp, $format) +{ + global $user_preferences; + date_default_timezone_set($user_preferences[CPHP_SETTING_TIMEZONE]); + return strftime($format, $timestamp); +} + +function gmt_from_unix($timestamp, $format) +{ + date_default_timezone_set("GMT"); + return strftime($format, $timestamp); +} + +function mysql_from_unix($timestamp) +{ + date_default_timezone_set("GMT"); + return date("Y-m-d H:i:s", $timestamp); +} + +function floor_to_day($timestamp) +{ + return floor($timestamp / (60 * 60 * 24)) * (60 * 60 * 24); +} diff --git a/include.dependencies.php b/include.dependencies.php new file mode 100644 index 0000000..80133c1 --- /dev/null +++ b/include.dependencies.php @@ -0,0 +1,101 @@ + $f_min) + { + return true; + } + else + { + return false; + } + } + else + { + if($f_cur > $f_min && $f_cur < $f_max) + { + return true; + } + else + { + return false; + } + } + } + } +} diff --git a/include.exceptions.php b/include.exceptions.php new file mode 100644 index 0000000..229efa2 --- /dev/null +++ b/include.exceptions.php @@ -0,0 +1,23 @@ +connect($cphp_memcache_server, $cphp_memcache_port); + + if($cphp_memcache_established !== false) + { + $cphp_memcache_connected = true; + } + else + { + $cphp_memcache_connected = false; + } +} + +function mc_get($key) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + $get_result = $memcache->get($key); + if($get_result !== false) + { + return $get_result; + } + else + { + return false; + } + } +} + +function mc_set($key, $value, $expiry) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $cphp_memcache_compressed, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + if($cphp_memcache_compressed === true) + { + $flag = MEMCACHE_COMPRESSED; + } + else + { + $flag = false; + } + + $set_result = $memcache->set($key, $value, $flag, $expiry); + return $set_result; + } +} + +function mc_delete($key) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + return $memcache->delete($key); + } +} + +function mysql_query_cached($query, $expiry = 60, $key = "") +{ + if($key == "") + { + $key = md5($query) . md5($query . "x"); + } + + if($res = mc_get($key)) + { + $return_object->source = "memcache"; + $return_object->data = $res; + return $return_object; + } + else + { + if($res = mysql_query($query)) + { + $found = false; + + while($row = mysql_fetch_assoc($res)) + { + $return_object->data[] = $row; + $found = true; + } + + if($found === true) + { + $return_object->source = "database"; + mc_set($key, $return_object->data, $expiry); + return $return_object; + } + else + { + return false; + } + } + else + { + return false; + } + } +} + +function file_get_contents_cached($path, $expiry = 3600) +{ + if($res = mc_get(md5($path) . md5($path . "x"))) + { + $return_object->source = "memcache"; + $return_object->data = $res; + return $return_object; + } + else + { + if($result = file_get_contents($path)) + { + $return_object->source = "disk"; + $return_object->data = $result; + mc_set(md5($path) . md5($path . "x"), $return_object->data, $expiry); + return $return_object; + } + else + { + return false; + } + } +} diff --git a/include.misc.php b/include.misc.php new file mode 100644 index 0000000..06533b7 --- /dev/null +++ b/include.misc.php @@ -0,0 +1,120 @@ + $value){ + $vars[] = "$".$key; + } + + return "global " . join(",", $vars) . ";"; +} + +function utf8entities($utf8) +{ + // Credits to silverbeat@gmx.at (http://www.php.net/manual/en/function.htmlentities.php#96648) + $encodeTags = true; + $result = ''; + for ($i = 0; $i < strlen($utf8); $i++) + { + $char = $utf8[$i]; + $ascii = ord($char); + if ($ascii < 128) + { + $result .= ($encodeTags) ? htmlentities($char) : $char; + } + else if ($ascii < 192) + { + // Do nothing. + } + else if ($ascii < 224) + { + $result .= htmlentities(substr($utf8, $i, 2), ENT_QUOTES, 'UTF-8'); + $i++; + } + else if ($ascii < 240) + { + $ascii1 = ord($utf8[$i+1]); + $ascii2 = ord($utf8[$i+2]); + $unicode = (15 & $ascii) * 4096 + + (63 & $ascii1) * 64 + + (63 & $ascii2); + $result .= "&#$unicode;"; + $i += 2; + } + else if ($ascii < 248) + { + $ascii1 = ord($utf8[$i+1]); + $ascii2 = ord($utf8[$i+2]); + $ascii3 = ord($utf8[$i+3]); + $unicode = (15 & $ascii) * 262144 + + (63 & $ascii1) * 4096 + + (63 & $ascii2) * 64 + + (63 & $ascii3); + $result .= "&#$unicode;"; + $i += 3; + } + } + return $result; +} + +function clean_array($arr) +{ + $result = array(); + foreach($arr as $key => $value) + { + if(!empty($value)) + { + $result[$key] = $value; + } + } + return $result; +} + +function pretty_dump($input) +{ + ob_start(); + + var_dump($input); + + $output = ob_get_contents(); + ob_end_clean(); + + while(preg_match("/^[ ]*[ ]/m", $output) == 1) + { + $output = preg_replace("/^([ ]*)[ ]/m", "$1   ", $output); + } + + $output = nl2br($output); + + echo($output); +} + +/*function is_empty($variable) +{ + return (trim($variable) == ""); +}*/ diff --git a/include.mysql.php b/include.mysql.php new file mode 100644 index 0000000..71880c0 --- /dev/null +++ b/include.mysql.php @@ -0,0 +1,27 @@ +