From 8450c53a61810e4f71bc5d71c75c1b98437bb548 Mon Sep 17 00:00:00 2001 From: alcexhim Date: Sat, 17 May 2014 20:15:00 -0400 Subject: [PATCH] Replace with current Objectify codebase --- PHP/.gitignore | 21 + .../Include/Objects/000-Objectify.inc.php | 51 ++ PHP/Common/Include/Objects/DataCenter.inc.php | 140 ++++ PHP/Common/Include/Objects/DataType.inc.php | 191 +++++ PHP/Common/Include/Objects/Language.inc.php | 55 ++ PHP/Common/Include/Objects/Module.inc.php | 113 +++ PHP/Common/Include/Objects/ModulePage.inc.php | 78 ++ .../Objects/MultipleInstanceProperty.inc.php | 41 ++ .../Include/Objects/PaymentPlan.inc.php | 56 ++ .../Objects/SingleInstanceProperty.inc.php | 31 + PHP/Common/Include/Objects/Tenant.inc.php | 455 ++++++++++++ .../Include/Objects/TenantObject.inc.php | 529 ++++++++++++++ .../Objects/TenantObjectInstance.inc.php | 220 ++++++ .../Objects/TenantObjectMethod.inc.php | 328 +++++++++ .../Objects/TenantObjectProperty.inc.php | 132 ++++ .../Include/Objects/TenantProperty.inc.php | 127 ++++ .../Objects/TenantQueryParameter.inc.php | 15 + .../Objects/TenantStringTableEntry.inc.php | 7 + PHP/Common/Include/Objects/TenantType.inc.php | 56 ++ PHP/Manager/Images/Logo.png | Bin 0 -> 89930 bytes PHP/Manager/Images/Logo.xcf | Bin 0 -> 183959 bytes .../Include/MasterPages/000-WebPage.inc.php | 23 + .../Include/Modules/000-Default/Main.inc.php | 665 ++++++++++++++++++ .../Modules/001-Setup/DefaultTenant.inc.php | 41 ++ .../Include/Modules/001-Setup/Main.inc.php | 351 +++++++++ .../001-Setup/Tables/000-DataTypes.inc.php | 324 +++++++++ .../001-Setup/Tables/000-Languages.inc.php | 20 + .../001-Setup/Tables/000-Modules.inc.php | 168 +++++ .../001-Setup/Tables/001-Tenants.inc.php | 78 ++ .../Tables/002-TenantObjects.inc.php | 197 ++++++ .../001-Setup/Tables/DataCenters.inc.php | 26 + .../001-Setup/Tables/DebugMessages.inc.php | 51 ++ .../001-Setup/Tables/Languages.inc.php | 213 ++++++ .../001-Setup/Tables/PaymentPlans.inc.php | 24 + .../Tables/SecurityPermissions.inc.php | 126 ++++ .../Tables/TenantDataCenters.inc.php | 23 + .../001-Setup/Tables/TenantTypes.inc.php | 29 + .../Modules/001-Setup/Tables/Users.inc.php | 17 + .../Include/Pages/000-LoginPage.inc.php | 48 ++ .../Include/Pages/000-MainPage.inc.php | 116 +++ .../Pages/001-TenantPropertiesPage.inc.php | 104 +++ .../Pages/002-ConfirmOperationPage.inc.php | 39 + .../Pages/003-TenantManagementPage.inc.php | 125 ++++ .../004-TenantModuleManagementPage.inc.php | 95 +++ .../Include/Pages/005-ModuleMainPage.inc.php | 41 ++ .../Pages/006-ModuleManagementPage.inc.php | 84 +++ .../Pages/007-DataCenterMainPage.inc.php | 43 ++ .../008-DataCenterManagementPage.inc.php | 48 ++ .../009-TenantObjectManagementPage.inc.php | 224 ++++++ ...0-TenantObjectMethodManagementPage.inc.php | 96 +++ ...011-TenantObjectInstanceBrowsePage.inc.php | 75 ++ .../Pages/012-DataTypeModifyPage.inc.php | 252 +++++++ PHP/Manager/Include/Pages/Default.wfx | 29 - PHP/Manager/Include/UUID.inc.php | 81 +++ PHP/Manager/index.php | 1 + PHP/TODO.txt | 62 ++ PHP/{Website => Tenant}/.htaccess | 0 .../Include/Modules/000-Default/Main.inc.php | 347 +++++++++ .../000-Default/ResourceBundle.inc.php | 192 +++++ .../Include/Pages/DataFormatModifyPage.html | 49 -- .../Include/Pages/DataFormatModifyPage.wfx | 29 - .../Include/Pages/EnumerationModifyPage.wfx | 36 - PHP/{Website => Tenant}/index.php | 6 + PHP/{Website => Tenant}/lessc.php | 0 PHP/Website/Include/Configuration.inc.php | 0 .../Include/MasterPages/000-WebPage.inc.php | 8 - .../Include/Modules/000-Default/Main.inc.php | 19 - .../Include/Pages/000-MainPage.inc.php | 15 - 68 files changed, 7101 insertions(+), 185 deletions(-) create mode 100644 PHP/.gitignore create mode 100644 PHP/Common/Include/Objects/000-Objectify.inc.php create mode 100644 PHP/Common/Include/Objects/DataCenter.inc.php create mode 100644 PHP/Common/Include/Objects/DataType.inc.php create mode 100644 PHP/Common/Include/Objects/Language.inc.php create mode 100644 PHP/Common/Include/Objects/Module.inc.php create mode 100644 PHP/Common/Include/Objects/ModulePage.inc.php create mode 100644 PHP/Common/Include/Objects/MultipleInstanceProperty.inc.php create mode 100644 PHP/Common/Include/Objects/PaymentPlan.inc.php create mode 100644 PHP/Common/Include/Objects/SingleInstanceProperty.inc.php create mode 100644 PHP/Common/Include/Objects/Tenant.inc.php create mode 100644 PHP/Common/Include/Objects/TenantObject.inc.php create mode 100644 PHP/Common/Include/Objects/TenantObjectInstance.inc.php create mode 100644 PHP/Common/Include/Objects/TenantObjectMethod.inc.php create mode 100644 PHP/Common/Include/Objects/TenantObjectProperty.inc.php create mode 100644 PHP/Common/Include/Objects/TenantProperty.inc.php create mode 100644 PHP/Common/Include/Objects/TenantQueryParameter.inc.php create mode 100644 PHP/Common/Include/Objects/TenantStringTableEntry.inc.php create mode 100644 PHP/Common/Include/Objects/TenantType.inc.php create mode 100644 PHP/Manager/Images/Logo.png create mode 100644 PHP/Manager/Images/Logo.xcf create mode 100644 PHP/Manager/Include/MasterPages/000-WebPage.inc.php create mode 100644 PHP/Manager/Include/Modules/000-Default/Main.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/DefaultTenant.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Main.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/000-DataTypes.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/000-Languages.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/000-Modules.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/001-Tenants.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/002-TenantObjects.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/DataCenters.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/DebugMessages.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/Languages.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/PaymentPlans.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/SecurityPermissions.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/TenantDataCenters.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/TenantTypes.inc.php create mode 100644 PHP/Manager/Include/Modules/001-Setup/Tables/Users.inc.php create mode 100644 PHP/Manager/Include/Pages/000-LoginPage.inc.php create mode 100644 PHP/Manager/Include/Pages/000-MainPage.inc.php create mode 100644 PHP/Manager/Include/Pages/001-TenantPropertiesPage.inc.php create mode 100644 PHP/Manager/Include/Pages/002-ConfirmOperationPage.inc.php create mode 100644 PHP/Manager/Include/Pages/003-TenantManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/004-TenantModuleManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/005-ModuleMainPage.inc.php create mode 100644 PHP/Manager/Include/Pages/006-ModuleManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/007-DataCenterMainPage.inc.php create mode 100644 PHP/Manager/Include/Pages/008-DataCenterManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/009-TenantObjectManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/010-TenantObjectMethodManagementPage.inc.php create mode 100644 PHP/Manager/Include/Pages/011-TenantObjectInstanceBrowsePage.inc.php create mode 100644 PHP/Manager/Include/Pages/012-DataTypeModifyPage.inc.php delete mode 100644 PHP/Manager/Include/Pages/Default.wfx create mode 100644 PHP/Manager/Include/UUID.inc.php create mode 100644 PHP/TODO.txt rename PHP/{Website => Tenant}/.htaccess (100%) create mode 100644 PHP/Tenant/Include/Modules/000-Default/Main.inc.php create mode 100644 PHP/Tenant/Include/Modules/000-Default/ResourceBundle.inc.php delete mode 100644 PHP/Tenant/Include/Pages/DataFormatModifyPage.html delete mode 100644 PHP/Tenant/Include/Pages/DataFormatModifyPage.wfx delete mode 100644 PHP/Tenant/Include/Pages/EnumerationModifyPage.wfx rename PHP/{Website => Tenant}/index.php (86%) rename PHP/{Website => Tenant}/lessc.php (100%) delete mode 100644 PHP/Website/Include/Configuration.inc.php delete mode 100644 PHP/Website/Include/MasterPages/000-WebPage.inc.php delete mode 100644 PHP/Website/Include/Modules/000-Default/Main.inc.php delete mode 100644 PHP/Website/Include/Pages/000-MainPage.inc.php diff --git a/PHP/.gitignore b/PHP/.gitignore new file mode 100644 index 00000000..6a3db272 --- /dev/null +++ b/PHP/.gitignore @@ -0,0 +1,21 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ +# +# disallow local configuration files and backup files +Tenant/Include/Configuration.* +Manager/Include/Configuration.* +# but include the configuration template files +!Tenant/Include/Configuration.inc.php.template +!Manager/Include/Configuration.inc.php.template +# disallow all resource bundles (which could contain proprietary content) +Tenant/Resources/* +# but allow common resource files that ship with ObjectFX +!Tenant/Resources/Common +# as well as a readme file that describes how to use resource bundles +!Tenant/Resources/Readme.txt +# and don't pull in sandbox stuff (which is really only for testing locally) +Sandbox/* \ No newline at end of file diff --git a/PHP/Common/Include/Objects/000-Objectify.inc.php b/PHP/Common/Include/Objects/000-Objectify.inc.php new file mode 100644 index 00000000..3c1efd09 --- /dev/null +++ b/PHP/Common/Include/Objects/000-Objectify.inc.php @@ -0,0 +1,51 @@ +ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($message) . "', "; + $query .= $severity . ", "; + $query .= "NOW(), "; + $query .= "'" . $MySQL->real_escape_string($_SERVER["REMOTE_ADDR"]) . "'"; + $query .= ")"; + $MySQL->query($query); + + $msgid = $MySQL->insert_id; + + foreach ($bt as $bti) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "DebugMessageBacktraces (bt_MessageID, bt_FileName, bt_LineNumber) VALUES ("; + $query .= $msgid . ", "; + $query .= "'" . $MySQL->real_escape_string($bti["file"]) . "', "; + $query .= $bti["line"]; + $query .= ")"; + $MySQL->query($query); + } + + foreach ($params as $key => $value) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "DebugMessageParameters (mp_MessageID, mp_Name, mp_Value) VALUES ("; + $query .= $msgid . ", "; + $query .= "'" . $MySQL->real_escape_string($key) . "', "; + $query .= "'" . $MySQL->real_escape_string($value) . "'"; + $query .= ")"; + $MySQL->query($query); + } + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/DataCenter.inc.php b/PHP/Common/Include/Objects/DataCenter.inc.php new file mode 100644 index 00000000..aee27388 --- /dev/null +++ b/PHP/Common/Include/Objects/DataCenter.inc.php @@ -0,0 +1,140 @@ +Items = array(); + } + + public function Add($item) + { + $this->Items[] = $item; + } + public function Contains($item) + { + foreach ($this->Items as $itm) + { + if ($itm->ID == $item->ID) return true; + } + return false; + } + public function Get($item) + { + foreach ($this->Items as $itm) + { + if ($itm->ID == $item->ID) return $item; + } + return null; + } + } + class DataCenter + { + public $ID; + public $Title; + public $Description; + public $HostName; + + public static function Create($title, $hostname, $description = null) + { + $item = new DataCenter(); + $item->Title = $title; + $item->HostName = $hostname; + $item->Description = $description; + if ($item->Update()) + { + return $item; + } + return null; + } + + public static function GetByAssoc($values) + { + $item = new DataCenter(); + $item->ID = $values["datacenter_ID"]; + $item->Title = $values["datacenter_Title"]; + $item->Description = $values["datacenter_Description"]; + $item->HostName = $values["datacenter_HostName"]; + return $item; + } + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DataCenters"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = DataCenter::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DataCenters WHERE datacenter_ID = " . $id; + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return DataCenter::GetByAssoc($values); + } + + public function Update() + { + global $MySQL; + if ($this->ID != null) + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "DataCenters SET "; + $query .= "datacenter_Title = '" . $MySQL->real_escape_string($this->Title) . "', "; + $query .= "datacenter_Description = '" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "datacenter_HostName = '" . $MySQL->real_escape_string($this->HostName) . "'"; + $query .= " WHERE datacenter_ID = " . $this->ID; + } + else + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "DataCenters (datacenter_Title, datacenter_Description, datacenter_HostName) VALUES ("; + $query .= "'" . $MySQL->real_escape_string($this->Title) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->HostName) . "'"; + $query .= ")"; + } + $result = $MySQL->query($query); + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + return ($MySQL->errno == 0); + } + + public function Delete() + { + global $MySQL; + if ($this->ID == null) return false; + + $query = "DELETE FROM " . System::$Configuration["Database.TablePrefix"] . "DataCenters WHERE datacenter_ID = " . $this->ID; + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + + return true; + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + echo("\"Title\":\"" . \JH\Utilities::JavaScriptEncode($this->Title, "\"") . "\","); + echo("\"Description\":\"" . \JH\Utilities::JavaScriptEncode($this->Description, "\"") . "\","); + echo("\"HostName\":\"" . \JH\Utilities::JavaScriptEncode($this->HostName, "\"") . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/DataType.inc.php b/PHP/Common/Include/Objects/DataType.inc.php new file mode 100644 index 00000000..f8f35e8c --- /dev/null +++ b/PHP/Common/Include/Objects/DataType.inc.php @@ -0,0 +1,191 @@ +ID = $values["datatype_ID"]; + $item->Name = $values["datatype_Name"]; + $item->Description = $values["datatype_Description"]; + + $item->EncoderCodeBlob = $values["datatype_EncoderCodeBlob"]; + $item->DecoderCodeBlob = $values["datatype_DecoderCodeBlob"]; + $item->ColumnRendererCodeBlob = $values["datatype_ColumnRendererCodeBlob"]; + $item->EditorRendererCodeBlob = $values["datatype_EditorRendererCodeBlob"]; + return $item; + } + + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DataTypes"; + if (is_numeric($max)) + { + $query .= " LIMIT " . $max; + } + $result = $MySQL->query($query); + $retval = array(); + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = DataType::GetByAssoc($values); + } + return $retval; + } + + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DataTypes WHERE datatype_ID = " . $id; + + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return DataType::GetByAssoc($values); + } + + public static function GetByName($name) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DataTypes WHERE datatype_Name = '" . $MySQL->real_escape_string($name) . "'"; + + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) + { + Objectify::Log("No data type with the specified name was found.", array + ( + "DataType" => $name + )); + return null; + } + + $values = $result->fetch_assoc(); + return DataType::GetByAssoc($values); + } + + public function Update() + { + global $MySQL; + if ($this->ID == null) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "DataTypes (datatype_Name, datatype_Description, datatype_EncoderCodeBlob, datatype_DecoderCodeBlob, datatype_ColumnRendererCodeBlob, datatype_EditorRendererCodeBlob) VALUES ("; + $query .= "'" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= ($this->EncoderCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->EncoderCodeBlob) . "'") : "NULL") . ", "; + $query .= ($this->DecoderCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->DecoderCodeBlob) . "'") : "NULL") . ", "; + $query .= ($this->ColumnRendererCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->ColumnRendererCodeBlob) . "'") : "NULL") . ", "; + $query .= ($this->EditorRendererCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->EditorRendererCodeBlob) . "'") : "NULL"); + $query .= ")"; + } + else + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "DataTypes SET "; + $query .= "datatype_Name = '" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "datatype_Description = '" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "datatype_EncoderCodeBlob = '" . ($this->EncoderCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->EncoderCodeBlob) . "'") : "NULL") . "', "; + $query .= "datatype_DecoderCodeBlob = '" . ($this->DecoderCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->DecoderCodeBlob) . "'") : "NULL") . "', "; + $query .= "datatype_ColumnRendererCodeBlob = '" . ($this->ColumnRendererCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->ColumnRendererCodeBlob) . "'") : "NULL") . "', "; + $query .= "datatype_EditorRendererCodeBlob = '" . ($this->EditorRendererCodeBlob != null ? ("'" . $MySQL->real_escape_string($this->EditorRendererCodeBlob) . "'") : "NULL") . "'"; + $query .= " WHERE datatype_ID = " . $this->ID; + } + + $MySQL->query($query); + if ($MySQL->errno != 0) + { + echo($MySQL->error); + die(); + return false; + } + + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + return true; + } + + public function Encode($value) + { + if ($this->EncoderCodeBlob == null) return $value; + $q = ''; + $q .= 'use Objectify\Objects\MultipleInstanceProperty; '; + $q .= 'use Objectify\Objects\SingleInstanceProperty; '; + $q .= 'use Objectify\Objects\TenantObject; '; + $q .= 'use Objectify\Objects\TenantObjectInstance; '; + $q .= '$x = function($input) { ' . $this->EncoderCodeBlob . ' };'; + // trigger_error("calling EncoderCodeBlob on DataType '" . $this->Name . "'", E_USER_NOTICE); + eval($q); + return $x($value); + } + public function Decode($value) + { + if ($this->DecoderCodeBlob == null) return $value; + $q = ''; + $q .= 'use Objectify\Objects\MultipleInstanceProperty; '; + $q .= 'use Objectify\Objects\SingleInstanceProperty; '; + $q .= 'use Objectify\Objects\TenantObject; '; + $q .= 'use Objectify\Objects\TenantObjectInstance; '; + $q .= '$x = function($input) { ' . $this->DecoderCodeBlob . ' };'; + // trigger_error("calling DecoderCodeBlob on DataType '" . $this->Name . "'", E_USER_NOTICE); + eval($q); + return $x($value); + } + + public function RenderColumn($value) + { + if ($this->ColumnRendererCodeBlob == null) return; + $q = ''; + $q .= 'use Objectify\Objects\MultipleInstanceProperty; '; + $q .= 'use Objectify\Objects\SingleInstanceProperty; '; + $q .= 'use Objectify\Objects\TenantObject; '; + $q .= 'use Objectify\Objects\TenantObjectInstance; '; + $q .= '$x = function($input) { ' . $this->ColumnRendererCodeBlob . ' };'; + // trigger_error("calling ColumnRendererCodeBlob on DataType '" . $this->Name . "'", E_USER_NOTICE); + eval($q); + $x($value); + } + public function RenderEditor($value, $name) + { + if ($this->EditorRendererCodeBlob == null) return; + + $q = ''; + $q .= 'use Objectify\Objects\MultipleInstanceProperty; '; + $q .= 'use Objectify\Objects\SingleInstanceProperty; '; + $q .= 'use Objectify\Objects\TenantObject; '; + $q .= 'use Objectify\Objects\TenantObjectInstance; '; + $q .= '$x = function($input, $name) { ' . $this->EditorRendererCodeBlob . ' };'; + // trigger_error("calling EditorRendererCodeBlob on DataType '" . $this->Name . "'", E_USER_NOTICE); + + eval($q); + + // if $x is not set, then there must have been an error in parsing so stop rendering + if (!isset($x)) return; + + $x($value, $name); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/Language.inc.php b/PHP/Common/Include/Objects/Language.inc.php new file mode 100644 index 00000000..334d1ad2 --- /dev/null +++ b/PHP/Common/Include/Objects/Language.inc.php @@ -0,0 +1,55 @@ +ID = $values["language_ID"]; + $item->Name = $values["language_Name"]; + return $item; + } + public static function Get() + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Languages"; + $result = $MySQL->query($query); + $retval = array(); + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $item = Language::GetByAssoc($values); + if ($item != null) $retval[] = $item; + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Languages WHERE language_ID = " . $id; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count < 1) return null; + + $values = $result->fetch_assoc(); + return Language::GetByAssoc($values); + } + public static function GetCurrent() + { + return Language::GetByID(1); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/Module.inc.php b/PHP/Common/Include/Objects/Module.inc.php new file mode 100644 index 00000000..1c29f217 --- /dev/null +++ b/PHP/Common/Include/Objects/Module.inc.php @@ -0,0 +1,113 @@ +ID = $values["module_ID"]; + $item->Title = $values["module_Title"]; + $item->Description = $values["module_Description"]; + $item->Enabled = $values["module_Enabled"]; + return $item; + } + public static function Get($max = null, $tenant = null) + { + global $MySQL; + + $query = "SELECT module_ID, module_Title, module_Description"; + if ($tenant != null) + { + $query .= ", (tenantmodule_ModuleID = module_ID) AS module_Enabled"; + } + else + { + $query .= ", 1 AS module_Enabled"; + } + $query .= " FROM " . System::$Configuration["Database.TablePrefix"] . "Modules"; + if ($tenant != null) + { + $query .= ", " . System::$Configuration["Database.TablePrefix"] . "TenantModules"; + $query .= " WHERE tenantmodule_ModuleID = module_ID AND tenantmodule_TenantID = " . $tenant->ID; + } + + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = Module::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id, $forAllTenants = false) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT module_ID, module_Title, module_Description FROM " . System::$Configuration["Database.TablePrefix"] . "Modules WHERE module_ID = " . $id; + if (!$forAllTenants) + { + $query = "SELECT module_ID, module_Title, module_Description FROM " . System::$Configuration["Database.TablePrefix"] . "Modules, " . System::$Configuration["Database.TablePrefix"] . "TenantModules WHERE tenantmodule_ModuleID = module_ID AND tenantmodule_TenantID = " . $CurrentTenant->ID . " AND module_ID = " . $id; + } + + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return Module::GetByAssoc($values); + } + + public function Update() + { + global $MySQL; + + if (is_numeric($this->ID)) + { + // id is set, so update + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "Modules SET "; + $query .= "module_Title = '" . $MySQL->real_escape_string($this->Title) . "', "; + $query .= "module_Description = '" . $MySQL->real_escape_string($this->Description) . "'"; + $query .= " WHERE module_ID = " . $this->ID; + } + else + { + // id is not set, so insert + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "Modules (module_Title, module_Description) VALUES ("; + $query .= "'" . $MySQL->real_escape_string($this->Title) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "'"; + $query .= ")"; + } + + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + + if (!is_numeric($this->ID)) + { + // id is not set, so set it + $this->ID = $MySQL->insert_id; + } + return true; + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + echo("\"Title\":\"" . \JH\Utilities::JavaScriptDecode($this->Title, "\"") . "\","); + echo("\"Description\":\"" . \JH\Utilities::JavaScriptDecode($this->Description, "\"") . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/ModulePage.inc.php b/PHP/Common/Include/Objects/ModulePage.inc.php new file mode 100644 index 00000000..225fbf14 --- /dev/null +++ b/PHP/Common/Include/Objects/ModulePage.inc.php @@ -0,0 +1,78 @@ +ID = $values["modulepage_ID"]; + $item->Module = Module::GetByID($values["modulepage_ModuleID"]); + $item->ParentPage = ModulePage::GetByID($values["modulepage_ParentPageID"]); + $item->URL = $values["modulepage_URL"]; + $item->Content = $values["modulepage_Content"]; + return $item; + } + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "ModulePages"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = ModulePage::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Modules WHERE module_ID = " . $id; + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return ModulePage::GetByAssoc($values); + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + if ($this->Module == null) + { + echo("\"Module\":null,"); + } + else + { + echo("\"Module\":" . $this->Module->ToJSON() . ","); + } + if ($this->ParentPage == null) + { + echo("\"ParentPage\":null,"); + } + else + { + echo("\"ParentPage\":" . $this->ParentPage->ToJSON() . ","); + } + echo("\"URL\":\"" . \JH\Utilities::JavaScriptDecode($this->URL, "\"") . "\","); + echo("\"Content\":\"" . \JH\Utilities::JavaScriptDecode($this->Content, "\"") . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/MultipleInstanceProperty.inc.php b/PHP/Common/Include/Objects/MultipleInstanceProperty.inc.php new file mode 100644 index 00000000..8f3c0ed7 --- /dev/null +++ b/PHP/Common/Include/Objects/MultipleInstanceProperty.inc.php @@ -0,0 +1,41 @@ +mvarInstances; + } + public function AddInstance($value) + { + if ($value == null) return false; + foreach ($this->ValidObjects as $obj) + { + if ($obj->ID != $value->ParentObject->ID) return false; + } + $this->mvarInstances[] = $value; + return true; + } + public function ClearInstances() + { + $this->mvarInstances = array(); + } + public function CountInstances() + { + return count($this->mvarInstances); + } + + public $ValidObjects; + + public function __construct($instances = null, $validObjects = null) + { + if ($instances == null) $instances = array(); + $this->mvarInstances = $instances; + + if ($validObjects == null) $validObjects = array(); + $this->ValidObjects = $validObjects; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/PaymentPlan.inc.php b/PHP/Common/Include/Objects/PaymentPlan.inc.php new file mode 100644 index 00000000..d32da618 --- /dev/null +++ b/PHP/Common/Include/Objects/PaymentPlan.inc.php @@ -0,0 +1,56 @@ +ID = $values["paymentplan_ID"]; + $item->URL = $values["paymentplan_Title"]; + $item->Description = $values["paymentplan_Description"]; + return $item; + } + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "PaymentPlans"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = PaymentPlan::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "PaymentPlans WHERE paymentplan_ID = " . $id; + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return PaymentPlan::GetByAssoc($values); + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + echo("\"Title\":\"" . \JH\Utilities::JavaScriptDecode($this->Title, "\"") . "\","); + echo("\"Description\":\"" . \JH\Utilities::JavaScriptDecode($this->Description, "\"") . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/SingleInstanceProperty.inc.php b/PHP/Common/Include/Objects/SingleInstanceProperty.inc.php new file mode 100644 index 00000000..12258fb1 --- /dev/null +++ b/PHP/Common/Include/Objects/SingleInstanceProperty.inc.php @@ -0,0 +1,31 @@ +mvarInstance; + } + public function SetInstance($value) + { + foreach ($this->ValidObjects as $obj) + { + if ($obj->ID != $value->ParentObject->ID) return false; + } + $this->mvarInstance = $value; + return true; + } + + public $ValidObjects; + + public function __construct($instance = null, $validObjects = null) + { + $this->mvarInstance = $instance; + + if ($validObjects == null) $validObjects = array(); + $this->ValidObjects = $validObjects; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/Tenant.inc.php b/PHP/Common/Include/Objects/Tenant.inc.php new file mode 100644 index 00000000..2db9cbdb --- /dev/null +++ b/PHP/Common/Include/Objects/Tenant.inc.php @@ -0,0 +1,455 @@ +DataCenters = new DataCenterCollection(); + } + + public function IsExpired() + { + $date = date_create(); + if ($this->BeginTimestamp == null) + { + $dateBegin = null; + } + else + { + $dateBegin = date_create($this->BeginTimestamp); + } + if ($this->EndTimestamp == null) + { + $dateEnd = null; + } + else + { + $dateEnd = date_create($this->EndTimestamp); + } + + return (!(($dateBegin == null || $dateBegin <= $date) && ($dateEnd == null || $dateEnd >= $date))); + } + + public static function Create($url, $description = null, $status = TenantStatus::Enabled, $type = null, $paymentPlan = null, $beginTimestamp = null, $endTimestamp = null, $dataCenters = null) + { + $item = new Tenant(); + $item->URL = $url; + $item->Description = $description; + $item->Status = $status; + $item->Type = $type; + $item->PaymentPlan = $paymentPlan; + $item->BeginTimestamp = $beginTimestamp; + $item->EndTimestamp = $endTimestamp; + + if ($dataCenters == null) $dataCenters = array(); + foreach ($dataCenters as $datacenter) + { + $item->DataCenters->Add($datacenter); + } + + if ($item->Update()) + { + return $item; + } + return null; + } + + public static function GetByAssoc($values) + { + $item = new Tenant(); + $item->ID = $values["tenant_ID"]; + $item->URL = $values["tenant_URL"]; + $item->Description = $values["tenant_Description"]; + switch ($values["tenant_Status"]) + { + case 1: + { + $item->Status = TenantStatus::Enabled; + break; + } + case 0: + { + $item->Status = TenantStatus::Disabled; + break; + } + } + $item->Type = TenantType::GetByID($values["tenant_TypeID"]); + $item->PaymentPlan = PaymentPlan::GetByID($values["tenant_PaymentPlanID"]); + $item->BeginTimestamp = $values["tenant_BeginTimestamp"]; + $item->EndTimestamp = $values["tenant_EndTimestamp"]; + + + // get the data centers associated with this tenant + global $MySQL; + $query = "SELECT " . System::$Configuration["Database.TablePrefix"] . "DataCenters.* FROM " . System::$Configuration["Database.TablePrefix"] . "DataCenters, " . System::$Configuration["Database.TablePrefix"] . "TenantDataCenters WHERE " . System::$Configuration["Database.TablePrefix"] . "TenantDataCenters.tdc_TenantID = " . $item->ID . " AND " . System::$Configuration["Database.TablePrefix"] . "TenantDataCenters.tdc_DataCenterID = " . System::$Configuration["Database.TablePrefix"] . "DataCenters.datacenter_ID"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = DataCenter::GetByAssoc($values); + } + $item->DataCenters->Items = $retval; + + return $item; + } + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Tenants"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = Tenant::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Tenants WHERE tenant_ID = " . $id; + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return Tenant::GetByAssoc($values); + } + public static function GetByURL($url) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "Tenants WHERE tenant_URL = '" . $MySQL->real_escape_string($url) . "'"; + $result = $MySQL->query($query); + if ($result === false) + { + echo("Initialization Failure

Initialization Failure

A fatal error occurred when attempting to initialize the Objectify runtime. Please make sure Objectify has been installed correctly on the server.

The Objectify runtime cannot be loaded (1001). Please contact the Web site administrator to inform them of this problem.


System information

Tenant:" . $url . "
Server: " . $_SERVER["HTTP_HOST"] . "
"); + die(); + return null; + } + + $count = $result->num_rows; + if ($count == 0) + { + echo("Initialization Failure

Initialization Failure

A fatal error occurred when attempting to initialize the Objectify runtime. Please make sure Objectify has been installed correctly on the server.

The Objectify runtime cannot find the requested tenant (1002). Please contact the Web site administrator to inform them of this problem.


System information

Tenant:" . $url . "
Server: " . $_SERVER["HTTP_HOST"] . "
"); + die(); + return null; + } + + $values = $result->fetch_assoc(); + return Tenant::GetByAssoc($values); + } + + public static function GetCurrent() + { + if (System::$TenantName == "") return null; + return Tenant::GetByURL(System::$TenantName); + } + + public function Update() + { + global $MySQL; + if ($this->ID != null) + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "Tenants SET "; + $query .= "tenant_URL = '" . $MySQL->real_escape_string($this->URL) . "', "; + $query .= "tenant_Description = '" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "tenant_Status = " . ($this->Status == TenantStatus::Enabled ? "1" : "0") . ", "; + $query .= "tenant_TypeID = " . ($this->Type != null ? $this->Type->ID : "NULL") . ", "; + $query .= "tenant_PaymentPlanID = " . ($this->PaymentPlan != null ? $this->PaymentPlan->ID : "NULL") . ", "; + $query .= "tenant_BeginTimestamp = " . ($this->BeginTimestamp != null ? ("'" . $this->BeginTimestamp . "'") : "NULL") . ", "; + $query .= "tenant_EndTimestamp = " . ($this->EndTimestamp != null ? ("'" . $this->EndTimestamp . "'") : "NULL"); + $query .= " WHERE tenant_ID = " . $this->ID; + } + else + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "Tenants (tenant_URL, tenant_Description, tenant_Status, tenant_TypeID, tenant_PaymentPlanID, tenant_BeginTimestamp, tenant_EndTimestamp) VALUES ("; + $query .= "'" . $MySQL->real_escape_string($this->URL) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= ($this->Status == TenantStatus::Enabled ? "1" : "0") . ", "; + $query .= ($this->Type != null ? $this->Type->ID : "NULL") . ", "; + $query .= ($this->PaymentPlan != null ? $this->PaymentPlan->ID : "NULL") . ", "; + $query .= ($this->BeginTimestamp != null ? ("'" . $this->BeginTimestamp . "'") : "NULL") . ", "; + $query .= ($this->EndTimestamp != null ? ("'" . $this->EndTimestamp . "'") : "NULL"); + $query .= ")"; + } + + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + + // clearing the data centers + $query = "DELETE FROM " . System::$Configuration["Database.TablePrefix"] . "TenantDataCenters WHERE tdc_TenantID = " . $this->ID; + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + + // inserting the data centers + foreach ($this->DataCenters->Items as $item) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantDataCenters (tdc_TenantID, tdc_DataCenterID) VALUES ("; + $query .= $this->ID . ", "; + $query .= $item->ID; + $query .= ")"; + + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + } + + return true; + } + + public function Delete() + { + global $MySQL; + if ($this->ID == null) return false; + + // Relationships should cause all associated tenant data to be deleted. + $query = "DELETE FROM " . System::$Configuration["Database.TablePrefix"] . "Tenants WHERE tenant_ID = " . $this->ID; + $result = $MySQL->query($query); + if ($MySQL->errno != 0) return false; + + return true; + } + + /// + /// Determines if an Objectify object with the specified name exists on the current tenant. + /// + public function HasObject($name) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjects WHERE (object_TenantID IS NULL OR object_TenantID = " . $this->ID . ") AND object_Name = '" . $MySQL->real_escape_string($name) . "'"; + + $result = $MySQL->query($query); + $count = $result->num_rows; + return ($count != 0); + } + + /// + /// Gets an Objectify object from the current tenant. + /// + public function GetObject($name) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjects WHERE (object_TenantID IS NULL OR object_TenantID = " . $this->ID . ") AND object_Name = '" . $MySQL->real_escape_string($name) . "'"; + + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) + { + Objectify::Log("No object with the specified name was found.", array + ( + "Tenant" => $this->URL, + "Object" => $name + )); + return null; + } + $values = $result->fetch_assoc(); + $object = TenantObject::GetByAssoc($values); + return $object; + } + + public function CreateObject($name, $titles = null, $descriptions = null, $properties = null, $parentObject = null, $instances = null) + { + global $MySQL; + if ($titles == null) $titles = array($name); + if ($descriptions == null) $descriptions = array(); + if ($properties == null) $properties = array(); + if ($instances == null) $instances = array(); + + // do not create the object if the object with the same name already exists + if ($this->HasObject($name)) + { + $bt = debug_backtrace(); + trigger_error("Object '" . $name . "' already exists on tenant '" . $this->URL . "' in " . $bt[0]["file"] . "::" . $bt[0]["function"] . " on line " . $bt[0]["line"] . "; ", E_USER_WARNING); + return $this->GetObject($name); + } + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjects (object_TenantID, object_ModuleID, object_ParentObjectID, object_Name) VALUES ("; + $query .= $this->ID . ", "; + $query .= "NULL" . ", "; + $query .= ($parentObject == null ? "NULL" : $parentObject->ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($name) . "', "; + $query .= ")"; + + $result = $MySQL->query($query); + if ($result === false) return false; + + $id = $MySQL->insert_id; + $object = TenantObject::GetByID($id); + + $object->SetTitles($titles); + $object->SetDescriptions($descriptions); + + foreach ($properties as $property) + { + $object->CreateInstanceProperty($property); + } + + foreach ($instances as $instance) + { + $object->CreateInstance($instance); + } + + return $object; + } + + public function CreateEnumeration($name, $description = null, $choices = null) + { + global $MySQL; + if ($choices == null) $choices = array(); + + $item = new TenantEnumeration($name, $description, $choices); + $item->Tenant = $this; + $item->Choices = $choices; + $item->Update(); + + return $item; + } + + public function GetProperties() + { + global $MySQL; + + $retval = array(); + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantProperties WHERE (property_TenantID = " . $this->ID . " OR property_TenantID IS NULL)"; + $result = $MySQL->query($query); + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantProperty::GetByAssoc($values); + } + return $retval; + } + + public function CreateProperty($property) + { + return TenantProperty::Create($property, $this); + } + + public function GetProperty($propertyName) + { + global $MySQL; + + $retval = array(); + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantProperties WHERE (property_TenantID = " . $this->ID . " OR property_TenantID IS NULL) AND property_Name = '" . $MySQL->real_escape_string($propertyName) . "'"; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to obtain a reference to a property on the tenant.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return null; + } + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantProperty::GetByAssoc($values); + } + + public function GetPropertyValue($property, $defaultValue = null) + { + global $MySQL; + + // if we passed in a string to this property (because it's easier) then let's get a reference to that property + if (is_string($property)) + { + $propname = $property; + $property = $this->GetProperty($property); + } + + $query = "SELECT (CASE WHEN (propval_Value IS NULL) THEN property_DefaultValue ELSE propval_Value END) FROM " . System::$Configuration["Database.TablePrefix"] . "TenantPropertyValues, " . System::$Configuration["Database.TablePrefix"] . "TenantProperties WHERE " . System::$Configuration["Database.TablePrefix"] . "TenantProperties.property_ID = " . $property->ID . " AND " . System::$Configuration["Database.TablePrefix"] . "TenantProperties.property_ID = " . System::$Configuration["Database.TablePrefix"] . "TenantPropertyValues.propval_PropertyID"; + + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to look up a value of a property on the tenant.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query, + "Property" => ($property == null ? ($propname == null ? "(null)" : $propname) : (is_string($property) ? $property : $property->Name)) + )); + return null; + } + + $count = $result->num_rows; + if ($count == 0) + { + Objectify::Log("The property has no defined values on the specified tenant.", array + ( + "Property" => ($property == null ? ($propname == null ? "(null)" : $propname) : (is_string($property) ? $property : $property->Name)) + ), LogMessageSeverity::Warning); + if ($defaultValue != null) return $defaultValue; + return $property->DefaultValue; + } + + $values = $result->fetch_array(); + return $property->Decode($values[0]); + } + public function SetPropertyValue($property, $value) + { + global $MySQL; + + // if we passed in a string to this property (because it's easier) then let's get a reference to that property + if (is_string($property)) + { + $propname = $property; + $property = $this->GetProperty($property); + } + + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "TenantPropertyValues SET propval_Value = '" . $MySQL->real_escape_string($property->Encode($value)) . "' WHERE propval_PropertyID = " . $property->ID; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to update the value of a property on the tenant.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query, + "Property" => ($property == null ? ($propname == null ? "(null)" : $propname) : (is_string($property) ? $property : $property->Name)) + )); + } + return ($MySQL->errno == 0); + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + echo("\"URL\":\"" . $this->URL . "\","); + echo("\"Description\":\"" . $this->Description . "\""); + echo("\"Status\":\"" . $this->Status . "\""); + echo("\"Type\":" . $this->Type->ToJSON() . ""); + echo("\"PaymentPlan\":" . $this->PaymentPlan->ToJSON() . ""); + echo("\"BeginTimestamp\":\"" . $this->BeginTimestamp . "\""); + echo("\"EndTimestamp\":\"" . $this->EndTimestamp . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantObject.inc.php b/PHP/Common/Include/Objects/TenantObject.inc.php new file mode 100644 index 00000000..03d04107 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantObject.inc.php @@ -0,0 +1,529 @@ +ID = $values["object_ID"]; + $item->Tenant = Tenant::GetByID($values["object_TenantID"]); + $item->Module = Module::GetByID($values["object_ModuleID"]); + $item->ParentObject = TenantObject::GetByID($values["object_ParentObjectID"]); + $item->Name = $values["object_Name"]; + $item->Description = $values["object_Description"]; + return $item; + } + + public static function Get($max = null, $tenant = null) + { + global $MySQL; + + $retval = array(); + if ($tenant == null) $tenant = Tenant::GetCurrent(); + if ($tenant == null) return $retval; + + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjects WHERE object_TenantID = " . $tenant->ID; + if (is_numeric($max)) $query .= " LIMIT " . $max; + + $result = $MySQL->query($query); + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObject::GetByAssoc($values); + } + return $retval; + } + + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjects WHERE object_ID = " . $id; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantObject::GetByAssoc($values); + } + + /// + /// Creates an instance of this Objectify object with the specified properties. + /// + public function CreateInstance($properties) + { + if (!is_array($properties)) return false; + + $inst = new TenantObjectInstance($this); + $inst->Update(); + + foreach ($properties as $instprop) + { + $inst->SetPropertyValue($instprop->Property, $instprop->Value); + } + return $inst; + } + + public function GetPropertyValue($property, $defaultValue = null) + { + global $MySQL; + + if (is_string($property)) + { + $property = $this->GetProperty($property); + } + if ($property == null) return $defaultValue; + + $query = "SELECT propval_Value FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectPropertyValues WHERE propval_PropertyID = " . $property->ID; + + $result = $MySQL->query($query); + if ($result === false) return $defaultValue; + + $count = $result->num_rows; + if ($count == 0) return $defaultValue; + + $values = $result->fetch_array(); + return $property->DataType->Decode($values[0]); + } + public function SetPropertyValue($property, $value) + { + global $MySQL; + + if (is_string($property)) + { + $property = $this->GetProperty($property); + } + if ($property == null) return false; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectPropertyValues (propval_PropertyID, propval_Value) VALUES ("; + $query .= $property->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($property->DataType->Encode($value)) . "'"; + $query .= ")"; + $query .= " ON DUPLICATE KEY UPDATE "; + $query .= "propval_PropertyID = values(propval_PropertyID), "; + $query .= "propval_Value = values(propval_Value)"; + + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to update a property value for the specified object.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return false; + } + + return true; + } + + + public function CreateInstanceProperty($property) + { + global $MySQL; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceProperties (property_ObjectID, property_Name, property_Description, property_DataTypeID, property_DefaultValue, property_IsRequired) VALUES ("; + $query .= $this->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($property->Name) . "', "; + $query .= "'" . $MySQL->real_escape_string($property->Description) . "', "; + $query .= ($property->DataType == null ? "NULL" : $property->DataType->ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($property->Encode($property->DefaultValue)) . "', "; + $query .= ($property->Required ? "1" : "0"); + $query .= ")"; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to create an instance property for the specified tenant object.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return false; + } + } + + + public function CreateMethod($name, $parameters, $codeblob, $description = null, $namespaceReferences = null) + { + global $MySQL; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods (method_ObjectID, method_Name, method_Description, method_CodeBlob) VALUES ("; + $query .= $this->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($name) . "', "; + $query .= ($description == null ? "NULL" : ("'" . $MySQL->real_escape_string($description) . "'")) . ", "; + $query .= "'" . $MySQL->real_escape_string($codeblob) . "'"; + $query .= ")"; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to create a static method for the specified tenant object.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return false; + } + + $method = TenantObjectMethod::GetByID($MySQL->insert_id); + + if (is_array($namespaceReferences)) + { + foreach ($namespaceReferences as $ref) + { + $method->AddNamespaceReference($ref); + } + } + return $method; + } + public function CreateInstanceMethod($name, $parameters, $codeblob, $description = null, $namespaceReferences = null) + { + global $MySQL; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethods (method_ObjectID, method_Name, method_Description, method_CodeBlob) VALUES ("; + $query .= $this->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($name) . "', "; + $query .= ($description == null ? "NULL" : ("'" . $MySQL->real_escape_string($description) . "'")) . ", "; + $query .= "'" . $MySQL->real_escape_string($codeblob) . "'"; + $query .= ")"; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to create an instance method for the specified tenant object.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return false; + } + + $method = TenantObjectInstanceMethod::GetByID($MySQL->insert_id); + + if (is_array($namespaceReferences)) + { + foreach ($namespaceReferences as $ref) + { + $method->AddNamespaceReference($ref); + } + } + return $method; + } + + public function GetProperty($propertyName) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectProperties WHERE property_ObjectID = " . $this->ID . " AND property_Name = '" . $MySQL->real_escape_string($propertyName) . "'"; + $result = $MySQL->query($query); + if ($result === false) return null; + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantObjectProperty::GetByAssoc($values); + } + public function GetProperties($max = null) + { + global $MySQL; + + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectProperties WHERE property_ObjectID = " . $this->ID; + if (is_numeric($max)) $query .= " LIMIT " . $max; + + $result = $MySQL->query($query); + $retval = array(); + + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectProperty::GetByAssoc($values); + } + return $retval; + } + public function GetInstanceProperty($propertyName) + { + global $MySQL; + + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceProperties WHERE property_ObjectID = " . $this->ID . " AND property_Name = '" . $MySQL->real_escape_string($propertyName) . "'"; + + $result = $MySQL->query($query); + if ($result === false) return null; + $count = $result->num_rows; + if ($count == 0) + { + Objectify::Log("Could not fetch the specified instance property on the object.", array + ( + "Object" => $this->Name, + "Property" => $propertyName + )); + return null; + } + + $values = $result->fetch_assoc(); + + return TenantObjectInstanceProperty::GetByAssoc($values); + } + public function GetInstanceProperties($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceProperties WHERE property_ObjectID = " . $this->ID; + + $result = $MySQL->query($query); + $retval = array(); + + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectInstanceProperty::GetByAssoc($values); + } + return $retval; + } + + public function GetMethod($name) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods WHERE method_ObjectID = " . $this->ID . " AND method_Name = '" . $MySQL->real_escape_string($name) . "'"; + $result = $MySQL->query($query); + + if ($result === false) return null; + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantObjectMethod::GetByAssoc($values); + } + public function GetMethods($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods WHERE method_ObjectID = " . $this->ID; + if (is_numeric($max)) $query .= " LIMIT " . $max; + $result = $MySQL->query($query); + + $retval = array(); + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectMethod::GetByAssoc($values); + } + return $retval; + } + + public function GetInstanceMethod($name) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethods WHERE method_ObjectID = " . $this->ID . " AND method_Name = '" . $MySQL->real_escape_string($name) . "'"; + $result = $MySQL->query($query); + if ($result === false) return null; + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + + return TenantObjectInstanceMethod::GetByAssoc($values); + } + public function GetInstanceMethods($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethods WHERE method_ObjectID = " . $this->ID; + if (is_numeric($max)) $query .= " LIMIT " . $max; + $result = $MySQL->query($query); + + $retval = array(); + if ($result === false) return $retval; + + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectInstanceMethod::GetByAssoc($values); + } + return $retval; + } + + public function CountInstances($max = null) + { + global $MySQL; + $query = "SELECT COUNT(instance_ID) FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances WHERE instance_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + + if ($result === false) return 0; + $count = $result->num_rows; + if ($count == 0) return 0; + + $values = $result->fetch_array(); + return $values[0]; + } + + public function GetInstance($parameters) + { + if (!is_array($parameters)) + { + Objectify::Log("No parameters were specified by which to extract a single instance of the object.", array + ( + "Object" => $this->Name, + "Property" => $propertyName + )); + return null; + } + + global $MySQL; + + $query = "SELECT " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances.* FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances, " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceProperties, " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstancePropertyValues"; + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to obtain an instance of an object on the tenant.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query + )); + return null; + } + + $count = $result->num_rows; + if ($count == 0) + { + Objectify::Log("Could not obtain an instance of the object with the specified parameters.", array + ( + "Object" => $this->Name, + "Query" => $query + )); + return null; + } + + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $inst = TenantObjectInstance::GetByAssoc($values); + $found = true; + foreach ($parameters as $parameter) + { + if ($inst->GetPropertyValue($this->GetInstanceProperty($parameter->Name)) != $parameter->Value) + { + $found = false; + break; + } + } + if ($found) return $inst; + } + return null; + } + + public function GetInstances($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances WHERE instance_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + $retval = array(); + + if ($result === false) return $retval; + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectInstance::GetByAssoc($values); + } + return $retval; + } + + public function GetTitleOrName($language = null) + { + $title = $this->GetTitle($language); + if ($title == null) return $this->Name; + return $title; + } + + public function GetTitle($language = null) + { + if ($language == null) return Language::GetCurrent(); + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectTitles WHERE entry_LanguageID = " . $language->ID . " AND entry_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return $values["entry_Value"]; + } + public function SetTitle($language, $value) + { + if ($language == null) return Language::GetCurrent(); + + global $MySQL; + $query = "SELECT COUNT(*) FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectDescriptions WHERE entry_LanguageID = " . $language->ID . " AND entry_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + if ($result === false) return false; + + $values = $result->fetch_array(); + if (is_numeric($values[0]) && $values[0] > 0) + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "TenantObjectDescriptions SET entry_Value = '" . $MySQL->real_escape_string($value) . "' WHERE entry_LanguageID = " . $language->ID . " AND entry_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + if ($result === false) return false; + } + else + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectDescriptions (entry_LanguageID, entry_ObjectID, entry_Value) VALUES (" . $language->ID . ", " . $this->ID . ", '" . $MySQL->real_escape_string($value) . "')"; + $result = $MySQL->query($query); + if ($result === false) return false; + } + return true; + } + public function SetTitles($items) + { + foreach ($items as $item) + { + $object->SetTitle($item->Language, $item->Value); + } + } + public function GetDescription($language = null) + { + if ($language == null) return Language::GetCurrent(); + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectDescriptions WHERE entry_LanguageID = " . $language->ID . " AND entry_ObjectID = " . $this->ID; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return $values["entry_Value"]; + } + public function SetDescription($language, $value) + { + } + public function SetDescriptions($items) + { + foreach ($items as $item) + { + $object->SetDescription($item->Language, $item->Value); + } + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantObjectInstance.inc.php b/PHP/Common/Include/Objects/TenantObjectInstance.inc.php new file mode 100644 index 00000000..97af074e --- /dev/null +++ b/PHP/Common/Include/Objects/TenantObjectInstance.inc.php @@ -0,0 +1,220 @@ +ParentObject = $parentObject; + } + + public static function GetByAssoc($values) + { + $item = new TenantObjectInstance(TenantObject::GetByID($values["instance_ObjectID"])); + $item->ID = $values["instance_ID"]; + return $item; + } + + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances WHERE instance_ID = " . $id; + $result = $MySQL->query($query); + if ($result === false) return null; + + $values = $result->fetch_assoc(); + return TenantObjectInstance::GetByAssoc($values); + } + + public function GetPropertyValue($property, $defaultValue = null) + { + global $MySQL; + + if (is_string($property)) + { + $property = $this->ParentObject->GetInstanceProperty($property); + } + if ($property == null) return $defaultValue; + + $query = "SELECT propval_Value FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstancePropertyValues WHERE propval_InstanceID = " . $this->ID . " AND propval_PropertyID = " . $property->ID; + + $result = $MySQL->query($query); + if ($result === false) return $defaultValue; + + $count = $result->num_rows; + if ($count == 0) return $defaultValue; + + $values = $result->fetch_array(); + return $property->Decode($values[0]); + } + public function SetPropertyValue($property, $value) + { + global $MySQL; + + if (is_string($property)) + { + $property = $this->ParentObject->GetInstanceProperty($property); + } + if ($property == null) return false; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstancePropertyValues (propval_InstanceID, propval_PropertyID, propval_Value) VALUES ("; + $query .= $this->ID . ", "; + $query .= $property->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($property->Encode($value)) . "'"; + $query .= ")"; + $query .= " ON DUPLICATE KEY UPDATE "; + $query .= "propval_PropertyID = values(propval_PropertyID), "; + $query .= "propval_Value = values(propval_Value)"; + + $result = $MySQL->query($query); + if ($result === false) return false; + + return true; + } + public function HasPropertyValue($property) + { + global $MySQL; + + if ($property == null) return false; + + $query = "SELECT COUNT(propval_Value) FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstancePropertyValues WHERE propval_InstanceID = " . $this->ID . " AND propval_PropertyID = " . $property->ID; + + $result = $MySQL->query($query); + if ($result === false) return false; + + $count = $result->num_rows; + if ($count == 0) return false; + + $values = $result->fetch_array(); + return ($values[0] > 0); + } + + public function Update() + { + global $MySQL; + if ($this->ID == null) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances (instance_ObjectID) VALUES ("; + $query .= $this->ParentObject->ID; + $query .= ")"; + } + else + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstances SET "; + $query .= "instance_ObjectID = " . $this->ParentObject->ID; + $query .= " WHERE instance_ID = " . $this->ID; + } + $result = $MySQL->query($query); + if ($result === false) return false; + + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + return true; + } + + public function ToString() + { + return $this->GetPropertyValue("Name"); + } + } + class TenantObjectInstanceProperty + { + public $ID; + public $ParentObject; + public $Name; + public $DataType; + public $DefaultValue; + public $Required; + + /// + /// Determines whether this TenantObjectInstanceProperty is visible when rendered as a column in a ListView. + /// + public $ColumnVisible; + + public function RenderColumn($value = null) + { + if ($this->DataType == null || $this->DataType->ColumnRendererCodeBlob == null) + { + ?> + + DataType->RenderColumn($this->DefaultValue); + } + else + { + $this->DataType->RenderColumn($value); + } + } + } + + public function Encode($value) + { + if ($this->DataType == null) return $value; + return $this->DataType->Encode($value); + } + public function Decode($value) + { + if ($this->DataType == null) return $value; + return $this->DataType->Decode($value); + } + + public function __construct($name = null, $dataType = null, $defaultValue = null, $required = false) + { + $this->Name = $name; + $this->DataType = $dataType; + $this->DefaultValue = $defaultValue; + $this->Required = $required; + } + + public static function GetByAssoc($values) + { + $item = new TenantObjectInstanceProperty(); + $item->ID = $values["property_ID"]; + $item->ParentObject = TenantObject::GetByID($values["property_ObjectID"]); + $item->Name = $values["property_Name"]; + $item->Description = $values["property_Description"]; + $item->DataType = DataType::GetByID($values["property_DataTypeID"]); + if ($item->DataType != null) + { + $item->DefaultValue = $item->DataType->Decode($values["property_DefaultValue"]); + } + $item->Required = ($values["property_IsRequired"] == 1); + $item->ColumnVisible = ($values["property_ColumnVisible"] == 1); + return $item; + } + } + class TenantObjectInstancePropertyValue + { + public $Property; + public $Value; + + public function __construct($property, $value = null) + { + $this->Property = $property; + $this->Value = $value; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantObjectMethod.inc.php b/PHP/Common/Include/Objects/TenantObjectMethod.inc.php new file mode 100644 index 00000000..75121963 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantObjectMethod.inc.php @@ -0,0 +1,328 @@ +ID = $values["method_ID"]; + $item->ParentObject = TenantObject::GetByID($values["method_ObjectID"]); + $item->Name = $values["method_Name"]; + $item->Description = $values["method_Description"]; + $item->CodeBlob = $values["method_CodeBlob"]; + return $item; + } + + public function AddNamespaceReference($value) + { + global $MySQL; + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethodNamespaceReferences (ns_MethodID, ns_Value) VALUES ("; + $query .= $this->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($value) . "'"; + $query .= ")"; + + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to add a namespace reference to the specified object method.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query, + "Method" => $this->Name, + "Object" => $this->ParentObject == null ? "(null)" : $this->ParentObject->Name + )); + return false; + } + return true; + } + public function RemoveNamespaceReference($value) + { + global $MySQL; + $query = "DELETE FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethodNamespaceReferences WHERE "; + $query .= "ns_MethodID = " . $this->ID . " AND "; + $query .= "ns_Value = '" . $MySQL->real_escape_string($value) . "'"; + + $result = $MySQL->query($query); + if ($result === false) return false; + return true; + } + public function GetNamespaceReferences() + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethodNamespaceReferences WHERE ns_MethodID = " . $this->ID; + $retval = array(); + $result = $MySQL->query($query); + if ($result === false) return $retval; + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectMethodNamespaceReference::GetByAssoc($values); + } + return $retval; + } + + public function Update() + { + global $MySQL; + + if ($this->ID == null) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods (method_ObjectID, method_Name, method_Description, method_CodeBlob) VALUES ("; + $query .= ($this->Tenant == null ? "NULL" : $this->Tenant->ID) . ", "; + $query .= ($this->ParentObject == null ? "NULL" : $this->ParentObject->ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->CodeBlob) . "'"; + $query .= ")"; + } + else + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods SET "; + $query .= "method_ObjectID = " . ($this->ParentObject == null ? "NULL" : $this->ParentObject->ID) . ", "; + $query .= "method_Name = '" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "method_Description = '" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "method_CodeBlob = '" . $MySQL->real_escape_string($this->CodeBlob) . "'"; + $query .= " WHERE method_ID = " . $this->ID; + } + + $result = $MySQL->query($query); + if ($result === false) return false; + + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + return true; + } + + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectMethods WHERE method_ID = " . $id; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantObjectMethod::GetByAssoc($values); + } + + public function Execute($parameters = null) + { + if ($parameters == null) $parameters = array(); + + $func = ""; + $nses = $this->GetNamespaceReferences(); + foreach ($nses as $ns) + { + $func .= "use " . $ns->Value . ";\n"; + } + + $func .= "\$x = function(\$thisObject"; + $count = count($parameters); + if ($count > 0) $func .= ", "; + + for ($i = 0; $i < $count; $i++) + { + $parameter = $parameters[$i]; + $func .= "\$" . $parameter->ParameterName; + if ($i < $count - 1) + { + $func .= ", "; + } + } + $func .= "){"; + $func .= $this->CodeBlob; + $func .= "}; return \$x("; + $func .= "Objectify\\Objects\\TenantObject::GetByID(" . $this->ParentObject->ID . ")"; + if ($count > 0) $func .= ", "; + + for ($i = 0; $i < $count; $i++) + { + $parameter = $parameters[$i]; + if (is_string($parameter->Value)) + { + $func .= ("'" . $parameter->Value . "'"); + } + else + { + $func .= $parameter->Value; + } + if ($i < $count - 1) + { + $func .= ", "; + } + } + $func .= ");"; + + return eval($func); + } + } + class TenantObjectInstanceMethod + { + public $ID; + public $ParentObject; + public $Name; + public $Description; + public $CodeBlob; + + public static function GetByAssoc($values) + { + $item = new TenantObjectInstanceMethod(); + $item->ID = $values["method_ID"]; + $item->ParentObject = TenantObject::GetByID($values["method_ObjectID"]); + $item->Name = $values["method_Name"]; + $item->Description = $values["method_Description"]; + $item->CodeBlob = $values["method_CodeBlob"]; + return $item; + } + + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethods WHERE method_ID = " . $id; + $result = $MySQL->query($query); + if ($result === false) return null; + + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantObjectInstanceMethod::GetByAssoc($values); + } + + public function AddNamespaceReference($value) + { + global $MySQL; + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethodNamespaceReferences (ns_MethodID, ns_Value) VALUES ("; + $query .= $this->ID . ", "; + $query .= "'" . $MySQL->real_escape_string($value) . "'"; + $query .= ")"; + + $result = $MySQL->query($query); + if ($result === false) return false; + return true; + } + public function RemoveNamespaceReference($value) + { + global $MySQL; + $query = "DELETE FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethodNamespaceReferences WHERE "; + $query .= "ns_MethodID = " . $this->ID . " AND "; + $query .= "ns_Value = '" . $MySQL->real_escape_string($value) . "'"; + + $result = $MySQL->query($query); + if ($result === false) return false; + return true; + } + public function GetNamespaceReferences() + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantObjectInstanceMethodNamespaceReferences WHERE ns_MethodID = " . $this->ID; + $retval = array(); + $result = $MySQL->query($query); + if ($result === false) return $retval; + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantObjectMethodNamespaceReference::GetByAssoc($values); + } + return $retval; + } + + public function Execute($parameters) + { + if ($parameters == null) $parameters = array(); + + $func = ""; + $nses = $this->GetNamespaceReferences(); + foreach ($nses as $ns) + { + $func .= "use " . $ns->Value . ";\n"; + } + + $func .= "\$x = function("; + $count = count($parameters); + for ($i = 0; $i < $count; $i++) + { + $parameter = $parameters[$i]; + $func .= "\$" . $parameter->ParameterName; + if ($i < $count - 1) + { + $func .= ", "; + } + } + $func .= "){"; + $func .= $this->CodeBlob; + $func .= "}; return \$x("; + for ($i = 0; $i < $count; $i++) + { + $parameter = $parameters[$i]; + if (is_string($parameter->Value)) + { + $func .= ("'" . $parameter->Value . "'"); + } + else + { + $func .= $parameter->Value; + } + if ($i < $count - 1) + { + $func .= ", "; + } + } + $func .= ");"; + return eval($func); + } + } + class TenantObjectMethodParameter + { + public $Name; + public $DefaultValue; + + public function __construct($name, $defaultValue = null) + { + $this->Name = $name; + $this->DefaultValue = $defaultValue; + } + } + class TenantObjectMethodParameterValue + { + public $ParameterName; + public $Value; + + public function __construct($parameterName, $value = null) + { + $this->ParameterName = $parameterName; + $this->Value = $value; + } + } + class TenantObjectMethodNamespaceReference + { + public $ID; + public $Value; + + public static function GetByAssoc($values) + { + $item = new TenantObjectMethodNamespaceReference(); + $item->ID = $values["ns_ID"]; + $item->Value = $values["ns_Value"]; + return $item; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantObjectProperty.inc.php b/PHP/Common/Include/Objects/TenantObjectProperty.inc.php new file mode 100644 index 00000000..bafdca96 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantObjectProperty.inc.php @@ -0,0 +1,132 @@ +DataType == null || $this->DataType->ColumnRendererCodeBlob == null) + { + ?> + + DataType->RenderColumn($this->DefaultValue); + } + else + { + $this->DataType->RenderColumn($value); + } + } + } + + public function __construct($name, $description = null, $dataType = null, $defaultValue = null, $required = false, $enumeration = null, $requireChoiceFromEnumeration = false) + { + $this->Name = $name; + $this->Description = $description; + $this->DataType = $dataType; + $this->DefaultValue = $defaultValue; + $this->Required = $required; + $this->Enumeration = $enumeration; + $this->RequireChoiceFromEnumeration = $requireChoiceFromEnumeration; + } + + public static function GetByAssoc($values) + { + $item = new TenantObjectProperty(); + $item->ID = $values["property_ID"]; + $item->Tenant = Tenant::GetByID($values["property_TenantID"]); + $item->ParentObject = TenantObject::GetByID($values["property_ObjectID"]); + $item->Name = $values["property_Name"]; + $item->Description = $values["property_Description"]; + $item->DataType = DataType::GetByID($values["property_DataTypeID"]); + $item->DefaultValue = $values["property_DefaultValue"]; + $item->Required = ($values["property_IsRequired"] == 1); + $item->Enumeration = TenantEnumeration::GetByID($values["property_EnumerationID"]); + $item->RequireChoiceFromEnumeration = ($values["property_RequireChoiceFromEnumeration"] == 1); + return $item; + } + + public function Update() + { + global $MySQL; + + if ($this->ID == null) + { + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantObjectProperties (property_TenantID, property_ObjectID, property_Name, property_Description, property_DataTypeID, property_DefaultValue, property_IsRequired) VALUES ("; + $query .= ($this->Tenant == null ? "NULL" : $this->Tenant->ID) . ", "; + $query .= ($this->ParentObject == null ? "NULL" : $this->ParentObject->ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "'" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= ($this->DataType == null ? "NULL" : $this->DataType->ID) . ", "; + $query .= $this->DefaultValue == null ? "NULL" : ("'" . $this->DefaultValue . "'") . ", "; + $query .= ($this->Required ? "1" : "0") . ", "; + } + else + { + $query = "UPDATE " . System::$Configuration["Database.TablePrefix"] . "TenantObjectProperties SET "; + $query .= "property_TenantID = " . ($this->Tenant == null ? "NULL" : $this->Tenant->ID) . ", "; + $query .= "property_ObjectID = " . ($this->ParentObject == null ? "NULL" : $this->ParentObject->ID) . ", "; + $query .= "property_Name = '" . $MySQL->real_escape_string($this->Name) . "', "; + $query .= "property_Description = '" . $MySQL->real_escape_string($this->Description) . "', "; + $query .= "property_DataTypeID = " . ($this->DataType == null ? "NULL" : $this->DataType->ID) . ", "; + $query .= "property_DefaultValue = " . $this->DefaultValue == null ? "NULL" : ("'" . $this->DefaultValue . "'") . ", "; + $query .= "property_IsRequired = " . ($this->Required ? "1" : "0") . ", "; + $query .= " WHERE property_ID = " . $this->ID; + } + + $result = $MySQL->query($query); + if ($result === false) return false; + + if ($this->ID == null) + { + $this->ID = $MySQL->insert_id; + } + + return true; + } + } + class TenantObjectPropertyValue + { + public $Property; + public $Value; + + public function __construct($property, $value) + { + $this->Property = $property; + $this->Value = $value; + } + + public function Update() + { + + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantProperty.inc.php b/PHP/Common/Include/Objects/TenantProperty.inc.php new file mode 100644 index 00000000..068ba509 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantProperty.inc.php @@ -0,0 +1,127 @@ +Name = $name; + $this->DataType = $dataType; + $this->Description = $description; + $this->DefaultValue = $defaultValue; + } + + public function Decode($value) + { + if ($this->DataType == null) return $value; + return $this->DataType->Decode($value); + } + public function Encode($value) + { + if ($this->DataType == null) return $value; + return $this->DataType->Encode($value); + } + + public function RenderColumn($value = null) + { + if ($this->DataType == null || $this->DataType->ColumnRendererCodeBlob == null) + { + if ($value == null) + { + echo($this->DefaultValue); + } + else + { + echo($value); + } + } + else + { + if ($value == null) + { + $this->DataType->RenderColumn($this->DefaultValue); + } + else + { + $this->DataType->RenderColumn($value); + } + } + } + public function RenderEditor($value = null, $name = null) + { + if ($name == null) $name = "Property_" . $this->ID; + if ($this->DataType == null || $this->DataType->ColumnRendererCodeBlob == null) + { + ?> + + DataType->RenderEditor($this->DefaultValue, $name); + } + else + { + $this->DataType->RenderEditor($value, $name); + } + } + } + + public static function GetByAssoc($values) + { + $item = new TenantProperty(); + $item->ID = $values["property_ID"]; + $item->Tenant = Tenant::GetByID($values["property_TenantID"]); + $item->Name = $values["property_Name"]; + $item->Description = $values["property_Description"]; + $item->DataType = DataType::GetByID($values["property_DataTypeID"]); + $item->DefaultValue = $item->DataType->Decode($values["property_DefaultValue"]); + return $item; + } + + public static function Create($property, $tenant = null) + { + global $MySQL; + + $query = "INSERT INTO " . System::$Configuration["Database.TablePrefix"] . "TenantProperties (property_TenantID, property_Name, property_Description, property_DataTypeID, property_DefaultValue) VALUES ("; + $query .= ($tenant == null ? "NULL" : $tenant->ID) . ", "; + $query .= "'" . $MySQL->real_escape_string($property->Name) . "', "; + $query .= "'" . $MySQL->real_escape_string($property->Description) . "', "; + $query .= ($property->DataType == null ? "NULL" : $property->DataType->ID) . ", "; + $query .= ($property->DefaultValue == null ? "NULL" : "'" . $MySQL->real_escape_string($property->DataType->Encode($property->DefaultValue)) . "'"); + $query .= ")"; + + $result = $MySQL->query($query); + if ($result === false) + { + Objectify::Log("Database error when trying to create a property on the tenant.", array + ( + "DatabaseError" => $MySQL->error . " (" . $MySQL->errno . ")", + "Query" => $query, + "Property" => ($property == null ? ($propname == null ? "(null)" : $propname) : (is_string($property) ? $property : "#" . $property->ID)) + )); + return false; + } + return true; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantQueryParameter.inc.php b/PHP/Common/Include/Objects/TenantQueryParameter.inc.php new file mode 100644 index 00000000..6fc15147 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantQueryParameter.inc.php @@ -0,0 +1,15 @@ +Name = $name; + $this->Value = $value; + } + } +?> \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantStringTableEntry.inc.php b/PHP/Common/Include/Objects/TenantStringTableEntry.inc.php new file mode 100644 index 00000000..536bfeb8 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantStringTableEntry.inc.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/PHP/Common/Include/Objects/TenantType.inc.php b/PHP/Common/Include/Objects/TenantType.inc.php new file mode 100644 index 00000000..9c123333 --- /dev/null +++ b/PHP/Common/Include/Objects/TenantType.inc.php @@ -0,0 +1,56 @@ +ID = $values["tenanttype_ID"]; + $item->URL = $values["tenanttype_Title"]; + $item->Description = $values["tenanttype_Description"]; + return $item; + } + public static function Get($max = null) + { + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantTypes"; + $result = $MySQL->query($query); + $count = $result->num_rows; + $retval = array(); + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + $retval[] = TenantType::GetByAssoc($values); + } + return $retval; + } + public static function GetByID($id) + { + if (!is_numeric($id)) return null; + + global $MySQL; + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "TenantTypes WHERE tenanttype_ID = " . $id; + $result = $MySQL->query($query); + $count = $result->num_rows; + if ($count == 0) return null; + + $values = $result->fetch_assoc(); + return TenantType::GetByAssoc($values); + } + + public function ToJSON() + { + echo("{"); + echo("\"ID\":" . $this->ID . ","); + echo("\"Title\":\"" . \JH\Utilities::JavaScriptDecode($this->Title, "\"") . "\","); + echo("\"Description\":\"" . \JH\Utilities::JavaScriptDecode($this->Description, "\"") . "\""); + echo("}"); + } + } +?> \ No newline at end of file diff --git a/PHP/Manager/Images/Logo.png b/PHP/Manager/Images/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d0d8cabd4734c3722cfc4db7aeee59c2c70d985d GIT binary patch literal 89930 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 literal 0 HcmV?d00001 diff --git a/PHP/Manager/Images/Logo.xcf b/PHP/Manager/Images/Logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..e06b4be30a46cf7748d831fe62ae9762fd8dde10 GIT binary patch literal 183959 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[] = new WebStyleSheet("http://static.alcehosting.net/dropins/WebFramework/StyleSheets/Workday/Main.css"); + } + + protected function BeforeContent() + { + ?> + + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/000-Default/Main.inc.php b/PHP/Manager/Include/Modules/000-Default/Main.inc.php new file mode 100644 index 00000000..9c4773d2 --- /dev/null +++ b/PHP/Manager/Include/Modules/000-Default/Main.inc.php @@ -0,0 +1,665 @@ +query($query); + if ($result->num_rows < 1) return false; + return true; + } + + function CheckCredentials($admun, $admpw) + { + return ($admun == System::GetConfigurationValue("Administration.UserName") && $admpw == System::GetConfigurationValue("Administration.Password")); + } + function IsAdministrator() + { + if (!isset($_SESSION["admun"]) || !isset($_SESSION["admpw"])) return false; + + $admun = $_SESSION["admun"]; + $admpw = $_SESSION["admpw"]; + + return CheckCredentials($admun, $admpw); + } + + System::$BeforeLaunchEventHandler = function($path) + { + if (!IsConfigured() && (!($path[0] == "setup"))) + { + System::Redirect("~/setup"); + return true; + } + + if (!IsAdministrator() && (!($path[0] == "account" && $path[1] == "login.page")) && (!($path[0] == "setup")) && (!($path[0] == "favicon.ico"))) + { + $path1 = implode("/", $path); + $_SESSION["LoginRedirectURL"] = "~/" . $path1; + + System::Redirect("~/account/login.page"); + return true; + } + return true; + }; + + System::$Modules[] = new Module("net.Objectify.TenantManager.Default", array + ( + new ModulePage("", function($path) + { + $page = new WebPage(); + $page->BeginContent(); + + $btng = new ButtonGroup("btng1"); + $btng->Items[] = new ButtonGroupButton("btnDataCenters", "Data Centers", null, "~/Images/Buttons/DataCenters.png", "~/datacenter"); + $btng->Items[] = new ButtonGroupButton("btnDataTypes", "Data Types", null, "~/Images/Buttons/DataTypes.png", "~/datatype"); + $btng->Items[] = new ButtonGroupButton("btnTenantTypes", "Tenant Types", null, "~/Images/Buttons/TenantTypes.png", "~/tenanttype"); + $btng->Items[] = new ButtonGroupButton("btnTenants", "Tenants", null, "~/Images/Buttons/Tenants.png", "~/tenant"); + $btng->Items[] = new ButtonGroupButton("btnModules", "Modules", null, "~/Images/Buttons/Modules.png", "~/module"); + $btng->Render(); + + $page->EndContent(); + }), + new ModulePage("debug", function($path) + { + global $MySQL; + + $page = new WebPage(); + $page->BeginContent(); + if (is_numeric($path[0])) + { + if ($_SERVER["REQUEST_METHOD"] == "POST" && $_POST["action"] == "delete") + { + $query = "DELETE FROM " . System::GetConfigurationValue("Database.TablePrefix") . "DebugMessages WHERE message_ID = " . $path[0]; + $result = $MySQL->query($query); + System::Redirect("~/debug"); + } + else + { + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DebugMessages WHERE message_ID = " . $path[0]; + $result = $MySQL->query($query); + $values = $result->fetch_assoc(); + + echo("

Error Details

"); + echo("

" . $values["message_Content"] . "

"); + + echo("

Parameters

"); + echo(""); + $query1 = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DebugMessageParameters WHERE mp_MessageID = " . $values["message_ID"]; + $result1 = $MySQL->query($query1); + $count1 = $result1->num_rows; + echo(""); + echo(""); + echo(""); + echo(""); + for ($j = 0; $j < $count1; $j++) + { + $values1 = $result1->fetch_assoc(); + echo(""); + echo(""); + echo(""); + echo(""); + } + echo("
NameValue
"); + echo($values1["mp_Name"]); + echo(""); + echo($values1["mp_Value"]); + echo("
"); + + echo("

Backtrace

"); + echo(""); + $query1 = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DebugMessageBacktraces WHERE bt_MessageID = " . $values["message_ID"]; + $result1 = $MySQL->query($query1); + $count1 = $result1->num_rows; + echo(""); + echo(""); + echo(""); + echo(""); + for ($j = 0; $j < $count1; $j++) + { + $values1 = $result1->fetch_assoc(); + echo(""); + echo(""); + echo(""); + echo(""); + } + echo("
File nameLine number
"); + echo($values1["bt_FileName"]); + echo(""); + echo($values1["bt_LineNumber"]); + echo("
"); + echo("
"); + echo("
"); + echo(""); + echo(""); + echo("Back to Messages"); + echo("
"); + echo("
"); + } + } + else + { + if ($_SERVER["REQUEST_METHOD"] == "POST" && $_POST["action"] == "delete") + { + $query = "DELETE FROM " . System::GetConfigurationValue("Database.TablePrefix") . "DebugMessages"; + $result = $MySQL->query($query); + System::Redirect("~/debug"); + } + else + { + echo("
"); + echo(""); + echo(""); + echo("
"); + + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + + $query = "SELECT * FROM " . System::$Configuration["Database.TablePrefix"] . "DebugMessages"; + $result = $MySQL->query($query); + $count = $result->num_rows; + for ($i = 0; $i < $count; $i++) + { + $values = $result->fetch_assoc(); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + echo(""); + } + echo("
TenantSeverityMessageTimestampIP Address
"); + $tenant = Tenant::GetByID($values["message_TenantID"]); + if ($tenant != null) + { + echo("URL . "/") . "\">" . $tenant->URL . ""); + } + echo(""); + switch ($values["message_SeverityID"]) + { + } + echo(""); + echo(""); + echo($values["message_Content"]); + echo(""); + echo(""); + echo($values["message_Timestamp"]); + echo(""); + echo($values["message_IPAddress"]); + echo("
"); + } + } + $page->EndContent(); + return true; + }), + new ModulePage("account", array + ( + new ModulePage("login.page", function($path) + { + $page = new LoginPage(); + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + if (isset($_POST["user_LoginID"]) && isset($_POST["user_Password"])) + { + $admun = $_POST["user_LoginID"]; + $admpw = $_POST["user_Password"]; + + if (CheckCredentials($admun, $admpw)) + { + $_SESSION["admun"] = $admun; + $_SESSION["admpw"] = $admpw; + + if (isset($_SESSION["LoginRedirectURL"])) + { + System::Redirect($_SESSION["LoginRedirectURL"]); + } + else + { + System::Redirect("~/"); + } + return true; + } + else + { + $page->InvalidCredentials = true; + } + } + } + $page->Render(); + return true; + }), + new ModulePage("logout.page", function($path) + { + $_SESSION["admun"] = null; + $_SESSION["admpw"] = null; + System::Redirect("~/"); + return true; + }) + )), + new ModulePage("tenant", array + ( + new ModulePage("", function($path) + { + $page = new MainPage(); + $page->Render(); + return true; + }), + new ModulePage("create", function($path) + { + if ($_SERVER["REQUEST_METHOD"] === "POST") + { + $tenant_URL = $_POST["tenant_URL"]; + $tenant_Description = $_POST["tenant_Description"]; + + $tenant_DataCenters = array(); + foreach ($_POST as $key => $value) + { + if (substr($key, 0, strlen("tenant_DataCenter_")) == "tenant_DataCenter_") + { + $id = substr($key, strlen("tenant_DataCenter_") + 1); + $tenant_DataCenters[] = DataCenter::GetByID($id); + } + } + + $tenant_Status = ($_POST["tenant_Status"] == 1 ? TenantStatus::Enabled : TenantStatus::Disabled); + $tenant_Type = TenantType::GetByID($_POST["tenant_TypeID"]); + $tenant_PaymentPlan = PaymentPlan::GetByID($_POST["tenant_PaymentPlanID"]); + $tenant_BeginTimestamp = ($_POST["tenant_BeginTimestampValid"] == "1" ? null : $_POST["tenant_BeginTimestamp"]); + $tenant_EndTimestamp = ($_POST["tenant_EndTimestampValid"] == "1" ? null : $_POST["tenant_EndTimestamp"]); + + $retval = Tenant::Create($tenant_URL, $tenant_Description, $tenant_Status, $tenant_Type, $tenant_PaymentPlan, $tenant_BeginTimestamp, $tenant_EndTimestamp, $tenant_DataCenters); + + if ($retval == null) + { + global $MySQL; + echo($MySQL->error . " (" . $MySQL->errno . ")"); + } + else + { + System::Redirect("~/tenant"); + } + } + else + { + $page = new TenantPropertiesPage(); + $page->Render(); + return true; + } + }), + new ModulePage("modify", function($path) + { + if ($_SERVER["REQUEST_METHOD"] === "POST") + { + $tenant_URL = $_POST["tenant_URL"]; + + $tenant = Tenant::GetByURL($path[0]); + + $tenant->URL = $_POST["tenant_URL"]; + $tenant->Description = $_POST["tenant_Description"]; + $tenant->Status = ($_POST["tenant_Status"] == 1 ? TenantStatus::Enabled : TenantStatus::Disabled); + $tenant->Type = TenantType::GetByID($_POST["tenant_TypeID"]); + $tenant->PaymentPlan = PaymentPlan::GetByID($_POST["tenant_PaymentPlanID"]); + $tenant->BeginTimestamp = ($_POST["tenant_BeginTimestampValid"] == "1" ? null : $_POST["tenant_BeginTimestamp"]); + $tenant->EndTimestamp = ($_POST["tenant_EndTimestampValid"] == "1" ? null : $_POST["tenant_EndTimestamp"]); + + $retval = $tenant->Update(); + + if (!$retval) + { + global $MySQL; + echo($MySQL->error . " (" . $MySQL->errno . ")"); + } + else + { + System::Redirect("~/tenant"); + } + return true; + } + else + { + $page = new TenantPropertiesPage(); + $page->Tenant = Tenant::GetByURL($path[0]); + $page->Render(); + return true; + } + }), + new ModulePage("clone", function($path) + { + if ($_SERVER["REQUEST_METHOD"] === "POST") + { + $tenant_URL = $_POST["tenant_URL"]; + $tenant_Description = $_POST["tenant_Description"]; + $tenant_Status = ($_POST["tenant_Status"] == 1 ? TenantStatus::Enabled : TenantStatus::Disabled); + $tenant_Type = TenantType::GetByID($_POST["tenant_TypeID"]); + $tenant_PaymentPlan = PaymentPlan::GetByID($_POST["tenant_PaymentPlanID"]); + $tenant_BeginTimestamp = ($_POST["tenant_BeginTimestampValid"] == "1" ? null : $_POST["tenant_BeginTimestamp"]); + $tenant_EndTimestamp = ($_POST["tenant_EndTimestampValid"] == "1" ? null : $_POST["tenant_EndTimestamp"]); + + $retval = Tenant::Create($tenant_URL, $tenant_Description, $tenant_Status, $tenant_Type, $tenant_PaymentPlan, $tenant_BeginTimestamp, $tenant_EndTimestamp); + + if ($retval == null) + { + global $MySQL; + echo($MySQL->error . " (" . $MySQL->errno . ")"); + } + else + { + System::Redirect("~/tenant"); + } + } + else + { + $page = new TenantPropertiesPage(); + $page->Tenant = Tenant::GetByURL($path[0]); + $page->Render(); + return true; + } + }), + new ModulePage("delete", function($path) + { + if ($_SERVER["REQUEST_METHOD"] === "POST") + { + if ($_POST["Confirm"] == "1") + { + $tenant = Tenant::GetByURL($path[0]); + if ($tenant->Delete()) + { + System::Redirect("~/tenant"); + } + else + { + global $MySQL; + echo($MySQL->error . " (" . $MySQL->errno . ")"); + } + } + } + else + { + $page = new ConfirmOperationPage(); + $page->ReturnButtonURL = "~/tenant"; + $page->Message = "Are you sure you want to delete the tenant '" . $path[0] . "'? This action cannot be undone, and will destroy any and all data associated with that tenant."; + $page->Render(); + return true; + } + }), + new ModulePage("manage", function($path) + { + if ($path[1] == "") + { + $tenant = Tenant::GetByURL($path[0]); + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $properties = $tenant->GetProperties(); + foreach ($properties as $property) + { + $tenant->SetPropertyValue($property, $_POST["Property_" . $property->ID]); + } + System::Redirect("~/tenant/manage/" . $path[0]); + return true; + } + else + { + $page = new TenantManagementPage(); + $page->Tenant = $tenant; + $page->Render(); + return true; + } + } + else + { + switch ($path[1]) + { + case "modules": + { + $page = new TenantModuleManagementPage(); + $page->Tenant = Tenant::GetByURL($path[0]); + $page->Module = \Objectify\Objects\Module::GetByID($path[2]); + $page->Render(); + break; + } + case "objects": + { + if ($path[2] == "") + { + // $page = new TenantObjectBrowsePage(); + // $page->CurrentTenant = Tenant::GetByURL($path[0]); + // $page->Render(); + } + else + { + switch ($path[3]) + { + case "instances": + { + switch ($path[4]) + { + case "": + { + $tenant = Tenant::GetByURL($path[0]); + $object = TenantObject::GetByID($path[2]); + + $page = new TenantObjectInstanceBrowsePage(); + $page->CurrentTenant = $tenant; + $page->CurrentObject = $object; + $page->Render(); + break; + } + } + } + case "methods": + { + switch ($path[4]) + { + case "static": + { + $tenant = Tenant::GetByURL($path[0]); + $object = TenantObject::GetByID($path[2]); + $method = TenantObjectMethod::GetByID($path[5]); + + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $method->CodeBlob = $_POST["method_CodeBlob"]; + $method->Update(); + + System::Redirect("~/tenant/manage/" . $tenant->URL . "/objects/" . $object->ID); + return true; + } + + $page = new TenantObjectMethodManagementPage(); + $page->CurrentTenant = $tenant; + $page->CurrentObject = $object; + $page->CurrentMethod = $method; + $page->Render(); + break; + } + case "instance": + { + $page = new TenantObjectMethodManagementPage(); + $page->CurrentTenant = Tenant::GetByURL($path[0]); + $page->CurrentObject = TenantObject::GetByID($path[2]); + $page->CurrentMethod = TenantObjectInstanceMethod::GetByID($path[5]); + $page->Render(); + break; + } + } + break; + } + case "": + { + $tenant = Tenant::GetByURL($path[0]); + $object = TenantObject::GetByID($path[2]); + + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $count = $_POST["InstanceProperty_NewPropertyCount"]; + for ($i = $count; $i > 0; $i--) + { + $name = $_POST["InstanceProperty_" . $i . "_Name"]; + $dataType = DataType::GetByID($_POST["InstanceProperty_" . $i . "_DataTypeID"]); + $defaultValue = $_POST["InstanceProperty_" . $i . "_DefaultValue"]; + + $object->CreateInstanceProperty(new TenantObjectInstanceProperty($name, $dataType, $defaultValue)); + } + + System::Redirect("~/tenant/manage/" . $tenant->URL . "/objects/" . $object->ID); + return true; + } + else + { + $page = new TenantObjectManagementPage(); + $page->CurrentTenant = $tenant; + $page->CurrentObject = $object; + $page->Render(); + } + break; + } + } + } + break; + } + } + } + return true; + }), + new ModulePage("launch", function($path) + { + $tenant = Tenant::GetByURL($path[0]); + header("Location: http://" . $tenant->DataCenters->Items[0]->HostName . "/" . $tenant->URL); + }) + )), + new ModulePage("module", array + ( + new ModulePage("", function($path) + { + $page = new ModuleMainPage(); + $page->Render(); + return true; + }), + new ModulePage("modify", function($path) + { + $module = \Objectify\Objects\Module::GetByID($path[0], true); + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $module->Title = $_POST["module_Title"]; + $module->Description = $_POST["module_Description"]; + $module->Update(); + + System::Redirect("~/module/modify/" . $path[0]); + } + else + { + $page = new ModuleManagementPage(); + $page->Module = $module; + $page->Render(); + } + return true; + }) + )), + new ModulePage("datacenter", array + ( + new ModulePage("", function($path) + { + $page = new DataCenterMainPage(); + $page->Render(); + return true; + }), + new ModulePage("create", function($path) + { + $datacenter = new DataCenter(); + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $datacenter->Title = $_POST["datacenter_Title"]; + $datacenter->Description = $_POST["datacenter_Description"]; + $datacenter->HostName = $_POST["datacenter_HostName"]; + $datacenter->Update(); + + System::Redirect("~/datacenter"); + } + else + { + $page = new DataCenterManagementPage(); + $page->DataCenter = null; + $page->Render(); + } + return true; + }), + new ModulePage("modify", function($path) + { + $datacenter = DataCenter::GetByID($path[0]); + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + $datacenter->Title = $_POST["datacenter_Title"]; + $datacenter->Description = $_POST["datacenter_Description"]; + $datacenter->HostName = $_POST["datacenter_HostName"]; + $datacenter->Update(); + + System::Redirect("~/datacenter/modify/" . $path[0]); + } + else + { + $page = new DataCenterManagementPage(); + $page->DataCenter = $datacenter; + $page->Render(); + } + return true; + }) + )) + )); +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/DefaultTenant.inc.php b/PHP/Manager/Include/Modules/001-Setup/DefaultTenant.inc.php new file mode 100644 index 00000000..7de4a4f7 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/DefaultTenant.inc.php @@ -0,0 +1,41 @@ +CreateProperty(new TenantProperty("ApplicationTitle", DataType::GetByName("Text"), "The title of your application. This is displayed in various areas around the site.", "My Application")); + $tenant->CreateProperty(new TenantProperty("ApplicationDescription", DataType::GetByName("Text"), "A short description of your application. This will appear in search results and other areas that use the HTML META description attribute.", "A versatile, modern, data-driven Web application powered by Objectify.")); + + // Install the resource bundles + $objResourceBundle = $tenant->GetObject("ResourceBundle"); + $instRBCommon = $objResourceBundle->CreateInstance(array + ( + new TenantObjectInstancePropertyValue("Name", "Common") + )); + $instRBDefault = $objResourceBundle->CreateInstance(array + ( + new TenantObjectInstancePropertyValue("Name", "Default") + )); + + $tenant->CreateProperty(new TenantProperty + ( + "ResourceBundles", DataType::GetByName("MultipleInstance"), "The resource bundles that are loaded with this tenant.", new MultipleInstanceProperty + ( + array($instRBDefault), + array($objResourceBundle) + ) + )); + +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Main.inc.php b/PHP/Manager/Include/Modules/001-Setup/Main.inc.php new file mode 100644 index 00000000..9703f790 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Main.inc.php @@ -0,0 +1,351 @@ + + + + + + + + + + + + +" . $FileName); + if ($f === false) return false; + + fwrite($f, " $value) + { + $skip = false; + foreach ($preinstalledKeys as $pikey) + { + if ($key == $pikey) + { + $skip = true; + break; + } + } + if ($skip) continue; + fwrite($f, "\tSystem::\$Configuration[\"" . $key . "\"] = " . VariableToString($value) . ";\n"); + } + fwrite($f, "?>\n"); + fclose($f); + return true; + } + ?> +
+ " style="height: 200px;" /> +
+

+ is configuring your initial instance. This would be a good time for a coffee break... +

+ +Items[0]->Code . ": " . DataFX::$Errors->Items[0]->Message); + Message(DataFX::$Errors->Items[0]->Query); + return true; + } + + // create the Users table + /* + $tables = array + ( + new Table("MarketResourceBankDetails", "bankdetail_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ResourceTypeID", "INT", null, null, false), + new Column("Name", "VARCHAR", 50, null, false), + new Column("TitleSingular", "VARCHAR", 100, null, false), + new Column("TitlePlural", "VARCHAR", 100, null, false) + )), + new Table("Tasks", "task_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("TenantID", "INT", null, null, false), + new Column("Title", "VARCHAR", 100, null, false), + new Column("URL", "LONGTEXT", null, null, false) + )), + new Table("Themes", "theme_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("TenantID", "INT", null, null, false), + new Column("Name", "VARCHAR", 100, null, false), + new Column("Title", "VARCHAR", 100, null, false), + new Column("CreationUserID", "INT", null, null, false), + new Column("CreationTimestamp", "DATETIME", null, null, false) + )), + new Table("UserEquippedItems", "equippeditem_", array + ( + new Column("UserID", "INT", null, null, false), + new Column("ItemID", "INT", null, null, false) + )), + new Table("UserInventoryFolders", "inventoryitem_", array + ( + new Column("ID", "INT", null, null, false), + new Column("Title", "VARCHAR", 100, null, false), + new Column("ParentFolderID", "INT", null, null, true) + )), + new Table("UserInventoryItems", "inventoryitem_", array + ( + new Column("UserID", "INT", null, null, false), + new Column("ItemID", "INT", null, null, false), + new Column("ParentFolderID", "INT", null, null, true) + )), + new Table("UserProfileContents", "content_", array + ( + // posts by the user on their profile. can be scrolled back and forth like a journal. supports HTML! + new Column("ID", "INT", null, null, false, true, true), + new Column("TenantID", "INT", null, null, false), + new Column("CreationUserID", "INT", null, null, false), + new Column("CreationTimestamp", "DATETIME", null, null, false), + new Column("Content", "LONGTEXT", null, null, false) + )), + new Table("UserProfileContentFeedbacks", "feedback_", array + ( + // likes and dislikes for user profile contents + new Column("ContentID", "INT", null, null, false), + new Column("FeedbackTypeID", "INT", null, null, false), + new Column("Comments", "VARCHAR", 200, null, false), + new Column("CreationUserID", "INT", null, null, false), + new Column("CreationTimestamp", "DATETIME", null, null, false) + )) + ); + */ + + $tables = array(); + + $tablefilepath = dirname(__FILE__) . "/Tables/*.inc.php"; + $tablefiles = glob($tablefilepath); + foreach ($tablefiles as $tablefile) + { + require($tablefile); + } + + foreach ($tables as $table) + { + if ($table->Exists()) + { + Message("Table '" . $table->Name . "' already exists, skipping creation"); + } + else + { + $retval = $table->Create(); + if ($retval) + { + Success("Created table '" . $table->Name . "'"); + } + else + { + Failure("Could not create table '" . $table->Name . "'"); + Message("Database returned error " . DataFX::$Errors->Items[0]->Code . ": " . DataFX::$Errors->Items[0]->Message); + Message(DataFX::$Errors->Items[0]->Query); + } + } + } + + $tenant = Tenant::Create($_POST["Application_DefaultTenant"], "The default tenant for " . System::$Configuration["Application.Name"] . "."); + $tablefilepath = dirname(__FILE__) . "/TenantObjects/*.inc.php"; + $tablefiles = glob($tablefilepath); + foreach ($tablefiles as $tablefile) + { + require($tablefile); + } + + require(dirname(__FILE__) . "/DefaultTenant.inc.php"); +?> +
+ BeginContent(); +?> +
+ " style="height: 200px;" /> +
+

+ Please provide some information about your server to create the initial tenant. Other + tenants may be created and removed at any time by entering the Administrator Control Panel. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
" /> +
" />
" />
" style="width: 100%;" />

+
+EndContent(); + return true; + }, + function($path) + { + $enabled = false; + if (isset(System::$Configuration["Setup.Enabled"])) + { + $enabled = (System::$Configuration["Setup.Enabled"] == "true"); + } + if (!$enabled) + { + $page = new \WebFX\WebPage(); + $page->Title = "Configuration Error"; + $page->BeginContent(); + echo("
This Objectify installation has not been configured. Please contact the server administrator.
"); + $page->EndContent(); + return false; + } + }) + )); +?> diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/000-DataTypes.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/000-DataTypes.inc.php new file mode 100644 index 00000000..5ed59ae0 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/000-DataTypes.inc.php @@ -0,0 +1,324 @@ +" . $input . ""); +EOD +), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' + echo(""); +EOD +) + )), + new Record(array + ( + new RecordColumn("Name", "CodeBlob"), + new RecordColumn("Description", "Allows you to enter script code with a special text editor."), + new RecordColumn("EncoderCodeBlob", null), + new RecordColumn("DecoderCodeBlob", null), + new RecordColumn("ColumnRendererCodeBlob", <<<'EOD' + echo("
" . $input . "
"); +EOD +), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' + echo(""); +EOD +) + )), + new Record(array + ( + new RecordColumn("Name", "Number"), + new RecordColumn("Description", "Stores numeric data."), + new RecordColumn("EncoderCodeBlob", null), + new RecordColumn("DecoderCodeBlob", null), + new RecordColumn("ColumnRendererCodeBlob", null), + new RecordColumn("EditorRendererCodeBlob", null) + )), + new Record(array + ( + new RecordColumn("Name", "Boolean"), + new RecordColumn("Description", "Stores a true/false or yes/no value."), + new RecordColumn("EncoderCodeBlob", null), + new RecordColumn("DecoderCodeBlob", null), + new RecordColumn("ColumnRendererCodeBlob", <<<'EOD' +echo(""); +EOD +), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' +echo(""); +EOD +) + )), + new Record(array + ( + new RecordColumn("Name", "Measurement"), + new RecordColumn("Description", "Stores measurement data, which is a double-precision floating-point number followed by a unit of measurement."), + new RecordColumn("EncoderCodeBlob", null), + new RecordColumn("DecoderCodeBlob", null), + new RecordColumn("ColumnRendererCodeBlob", null), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' +echo(" "); +EOD +) + )), + new Record(array + ( + new RecordColumn("Name", "DateTime"), + new RecordColumn("Description", "Stores a date and time value."), + new RecordColumn("EncoderCodeBlob", null), + new RecordColumn("DecoderCodeBlob", null), + new RecordColumn("ColumnRendererCodeBlob", null), + new RecordColumn("EditorRendererCodeBlob", null) + )), + new Record(array + ( + new RecordColumn("Name", "SingleInstance"), + new RecordColumn("Description", "Represents a property that returns a single TenantObjectInstance object."), + new RecordColumn("EncoderCodeBlob", <<<'EOD' +// $input should be a TenantObjectInstance +if ($input == null) +{ + $bt = debug_backtrace(); + trigger_error("SingleInstance::Encoder - input is null, did you mean to pass in a blank SingleInstanceProperty?, in " . $bt["file"] . "::" . $bt["function"] . " on line " . $bt["line"] . "; ", E_USER_WARNING); + return ""; +} +// encode the property by simply storing the instance ID in the property value. +$output = ""; +$count = count($input->ValidObjects); +for ($i = 0; $i < $count; $i++) +{ + $output .= $input->ValidObjects[$i]->ID; + if ($i < $count - 1) $output .= ","; +} +$output .= ":"; +if ($input != null) +{ + if ($input->GetInstance() != null) $output .= $input->GetInstance()->ID; +} +return $output; +EOD +), + new RecordColumn("DecoderCodeBlob", <<<'EOD' +// $input should be a String in the format t0,t1,t2:i0,i1,i2,i3... where tx is an ID of a TenantObject that is valid in the property and ix is an ID of a TenantObjectInstance +// encode the property by simply storing the instance ID of each instance, separated by commas, in the property value. +$dcb = explode(":", $input); +$validObjects = explode(",", $dcb[0]); +$instance = $dcb[1]; +$output = new SingleInstanceProperty(); + +// loop through all the valid objects and add them to the MultipleInstanceProperty +$count = count($validObjects); +for ($i = 0; $i < $count; $i++) +{ + $output->ValidObjects[] = TenantObject::GetByID($validObjects[$i]); +} + +// assign the instance +$output->Instance = TenantObjectInstance::GetByID($instance); +return $output; +EOD +), + new RecordColumn("ColumnRendererCodeBlob", <<<'EOD' +$inst = $input->Instance; +echo("
"); + echo(""); + echo("
"); +if ($inst != null) +{ + echo ("" . $inst->ToString() . ""); +} + echo("
"); +echo("
"); +EOD +), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' +$inst = $input->Instance; +echo("
"); +$insts_text = $inst->ID; + echo(""); + echo(""); + echo("
"); +if ($inst != null) +{ + echo ("" . $inst->ToString() . ""); +} + echo("
"); + echo(""); +echo("
"); +EOD +) + )), + new Record(array + ( + new RecordColumn("Name", "MultipleInstance"), + new RecordColumn("Description", "Represents a property that returns an array of TenantObjectInstance objects."), + new RecordColumn("EncoderCodeBlob", <<<'EOD' +// $input should be an array of TenantObjectInstance objects +// encode the property by simply storing the instance ID of each instance, separated by commas, in the property value. the list of valid +// object types is stored in the first part of the property, separated by a colon. +if ($input == null) +{ + PhoenixSNS::Log("MultipleInstance::Encoder input is null - did you mean to pass in a blank MultipleInstanceProperty?"); + return ""; +} + +$output = ""; +$count = count($input->ValidObjects); +for ($i = 0; $i < $count; $i++) +{ + $output .= $input->ValidObjects[$i]->ID; + if ($i < $count - 1) $output .= ","; +} +$output .= ":"; +$insts = $input->GetInstances(); +$i = 0; +$count = count($insts); +foreach ($insts as $inst) +{ + $output .= $inst->ID; + if ($i < $count - 1) $output .= ","; + $i++; +} +return $output; +EOD +), + new RecordColumn("DecoderCodeBlob", <<<'EOD' +// $input should be a String in the format t0,t1,t2:i0,i1,i2,i3... where tx is an ID of a TenantObject that is valid in the property and ix is an ID of a TenantObjectInstance +// encode the property by simply storing the instance ID of each instance, separated by commas, in the property value. +if ($input == "") +{ + $bt = debug_backtrace(); + trigger_error("MultipleInstance::Decoder - input is null, did you mean to pass in a blank MultipleInstanceProperty?, in " . $bt["file"] . "::" . $bt["function"] . " on line " . $bt["line"] . "; ", E_USER_WARNING); + return null; +} + +$dcb = explode(":", $input); +$validObjects = explode(",", $dcb[0]); +$instances = explode(",", $dcb[1]); +$output = new MultipleInstanceProperty(); + +// loop through all the valid objects and add them to the MultipleInstanceProperty +$count = count($validObjects); +for ($i = 0; $i < $count; $i++) +{ + $output->ValidObjects[] = TenantObject::GetByID($validObjects[$i]); +} + +// loop through all of the instances and add them to the MultipleInstanceProperty +$count = count($instances); +for ($i = 0; $i < $count; $i++) +{ + $output->AddInstance(TenantObjectInstance::GetByID($instances[$i])); +} +return $output; +EOD +), + new RecordColumn("ColumnRendererCodeBlob", <<<'EOD' +if ($input == null) return; +if (!is_object($input) || (get_class($input) != "PhoenixSNS\\Objects\\MultipleInstanceProperty")) +{ + $bt = debug_backtrace(); + trigger_error("Expected MultipleInstanceProperty, got something else in " . $bt[1]["file"] . "::" . $bt[1]["function"] . " at line " . $bt[1]["line"], E_USER_WARNING); + return; +} +$insts = $input->GetInstances(); +echo("
"); + echo(""); + echo(""); + echo("
"); +foreach ($insts as $inst) +{ + if ($inst != null) + { + echo ("" . $inst->ToString() . ""); + } +} + echo("
"); +echo("
"); +EOD +), + new RecordColumn("EditorRendererCodeBlob", <<<'EOD' +if ($input == null) return; +if (!is_object($input) || (get_class($input) != "PhoenixSNS\\Objects\\MultipleInstanceProperty")) +{ + $bt = debug_backtrace(); + trigger_error("Expected MultipleInstanceProperty, got something else in " . $bt[1]["file"] . "::" . $bt[1]["function"] . " at line " . $bt[1]["line"], E_USER_WARNING); + return; +} +$insts = $input->GetInstances(); +echo("
"); +$insts_text = ""; +$count = count($insts); +for ($i = 0; $i < $count; $i++) +{ + $inst = $insts[$i]; + $insts_text .= $inst->ID; + if ($i < $count - 1) $insts_text .= ", "; +} + echo(""); + echo(""); + echo("
"); +foreach ($insts as $inst) +{ + if ($inst != null) + { + echo ("" . $inst->ToString() . ""); + } +} + echo("
"); + echo(""); +echo("
"); +EOD +) + )) + )); + $tables[] = $tblDataTypes; +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/000-Languages.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/000-Languages.inc.php new file mode 100644 index 00000000..04067797 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/000-Languages.inc.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/000-Modules.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/000-Modules.inc.php new file mode 100644 index 00000000..a0f4edc6 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/000-Modules.inc.php @@ -0,0 +1,168 @@ +ForeignKeys = array + ( + new TableForeignKey("ModuleID", new TableForeignKeyColumn($tblModules, $tblModules->GetColumnByName("ID"))) + ); + $tables[] = $tblModuleMenuItems; + + $tblModuleObjects = new Table("ModuleObjects", "object_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ModuleID", "INT", null, null, true), + new Column("ParentObjectID", "INT", null, null, true), + new Column("Title", "VARCHAR", 256, null, true), + new Column("Description", "LONGTEXT", null, null, true) + ), + array + ( + new Record(array + ( + new RecordColumn("ModuleID", 7), + new RecordColumn("Title", "Game") + )) + )); + $tblModuleObjects->ForeignKeys = array + ( + new TableForeignKey("ModuleID", new TableForeignKeyColumn($tblModules, $tblModules->GetColumnByName("ID"))), + new TableForeignKey("ParentObjectID", new TableForeignKeyColumn($tblModuleObjects, $tblModuleObjects->GetColumnByName("ID"))) + ); + $tables[] = $tblModuleObjects; + + $tblModulePages = new Table("ModulePages", "modulepage_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ModuleID", "INT", null, null, true), + new Column("ParentPageID", "INT", null, null, true), + new Column("URL", "VARCHAR", 1024, null, true), + new Column("Content", "LONGTEXT", null, null, true) + ), + array + ( + new Record(array + ( + new RecordColumn("ModuleID", 1), + new RecordColumn("URL", "groups") + )), + new Record(array + ( + new RecordColumn("ModuleID", 1), + new RecordColumn("URL", "pages") + )), + new Record(array + ( + new RecordColumn("ModuleID", 1), + new RecordColumn("URL", "forums") + )) + )); + $tblModulePages->ForeignKeys = array + ( + new TableForeignKey("ModuleID", new TableForeignKeyColumn($tblModules, $tblModules->GetColumnByName("ID"))), + new TableForeignKey("ParentPageID", new TableForeignKeyColumn($tblModulePages, $tblModulePages->GetColumnByName("ID"))) + ); + $tables[] = $tblModulePages; +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/001-Tenants.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/001-Tenants.inc.php new file mode 100644 index 00000000..42797d3d --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/001-Tenants.inc.php @@ -0,0 +1,78 @@ +UniqueKeys = array + ( + new TableKey(array + ( + new TableKeyColumn("URL") + )) + ); + $tables[] = $tblTenants; + + $tblTenantProperties = new Table("TenantProperties", "property_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("TenantID", "INT", null, null, true), + new Column("Name", "VARCHAR", 256, null, false), + new Column("Description", "LONGTEXT", null, null, true), + new Column("DataTypeID", "INT", null, null, false), + new Column("DefaultValue", "LONGBLOB", null, null, true) + )); + $tblTenantProperties->ForeignKeys = array + ( + new TableForeignKey("TenantID", new TableForeignKeyColumn($tblTenants, "ID")), + new TableForeignKey("DataTypeID", new TableForeignKeyColumn($tblDataTypes, "ID")) + ); + $tables[] = $tblTenantProperties; + + $tblTenantPropertyValues = new Table("TenantPropertyValues", "propval_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("PropertyID", "INT", null, null, false, true, true), + new Column("Value", "LONGTEXT", null, null, true) + )); + $tblTenantPropertyValues->ForeignKeys = array + ( + new TableForeignKey("PropertyID", new TableForeignKeyColumn($tblTenantProperties, "ID")) + ); + $tables[] = $tblTenantPropertyValues; + + $tblTenantModules = new Table("TenantModules", "tenantmodule_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("TenantID", "INT", null, null, false), + new Column("ModuleID", "INT", null, null, false) + )); + $tblTenantModules->ForeignKeys = array + ( + new TableForeignKey("TenantID", new TableForeignKeyColumn($tblTenants, "ID")) + ); + $tables[] = $tblTenantModules; +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/002-TenantObjects.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/002-TenantObjects.inc.php new file mode 100644 index 00000000..481e6ae2 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/002-TenantObjects.inc.php @@ -0,0 +1,197 @@ +ForeignKeys = array + ( + new TableForeignKey("TenantID", new TableForeignKeyColumn($tblTenants, $tblTenants->GetColumnByName("ID"))), + new TableForeignKey("ModuleID", new TableForeignKeyColumn($tblModules, $tblModules->GetColumnByName("ID"))), + new TableForeignKey("ParentObjectID", new TableForeignKeyColumn($tblTenantObjects, $tblTenantObjects->GetColumnByName("ID"))) + ); + $tables[] = $tblTenantObjects; + + $tblTenantObjectTitles = new Table("TenantObjectTitles", "entry_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("LanguageID", "INT", null, null, false), + new Column("Value", "LONGTEXT", null, null, false) + )); + $tblTenantObjectTitles->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, $tblTenantObjects->GetColumnByName("ID"))), + new TableForeignKey("LanguageID", new TableForeignKeyColumn($tblLanguages, $tblLanguages->GetColumnByName("ID"))) + ); + $tables[] = $tblTenantObjectTitles; + + $tblTenantObjectDescriptions = new Table("TenantObjectDescriptions", "entry_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("LanguageID", "INT", null, null, false), + new Column("Value", "LONGTEXT", null, null, false) + )); + $tblTenantObjectDescriptions->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, $tblTenantObjects->GetColumnByName("ID"))), + new TableForeignKey("LanguageID", new TableForeignKeyColumn($tblLanguages, $tblLanguages->GetColumnByName("ID"))) + ); + $tables[] = $tblTenantObjectDescriptions; + + // Available static properties for the objects. + $tblTenantObjectProperties = new Table("TenantObjectProperties", "property_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("Name", "VARCHAR", 256, null, true), + new Column("DataTypeID", "INT", null, null, true), + new Column("DefaultValue", "LONGBLOB", null, null, true), + new Column("IsRequired", "INT", null, 0, false), + new Column("EnumerationID", "INT", null, null, true), + new Column("RequireChoiceFromEnumeration", "INT", null, 0, false), + new Column("ColumnVisible", "INT", null, 0, false) + )); + $tblTenantObjectProperties->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, "ID")), + new TableForeignKey("DataTypeID", new TableForeignKeyColumn($tblDataTypes, "ID")) + ); + $tables[] = $tblTenantObjectProperties; + + // Values for static properties of objects. + $tblTenantObjectPropertyValues = new Table("TenantObjectPropertyValues", "propval_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("PropertyID", "INT", null, null, false), + new Column("Value", "LONGBLOB", null, null, true) + )); + $tblTenantObjectPropertyValues->ForeignKeys = array + ( + new TableForeignKey("PropertyID", new TableForeignKeyColumn($tblTenantObjectProperties, "ID")) + ); + $tables[] = $tblTenantObjectPropertyValues; + + // Instances of the objects. + $tblTenantObjectInstances = new Table("TenantObjectInstances", "instance_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false) + )); + $tblTenantObjectInstances->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, "ID")) + ); + $tables[] = $tblTenantObjectInstances; + + // Properties of the object instances. + $tblTenantObjectInstanceProperties = new Table("TenantObjectInstanceProperties", "property_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("Name", "VARCHAR", 256, null, true), + new Column("DataTypeID", "INT", null, null, true), + new Column("DefaultValue", "LONGBLOB", null, null, true), + new Column("IsRequired", "INT", null, 0, false), + new Column("EnumerationID", "INT", null, null, true), + new Column("RequireChoiceFromEnumeration", "INT", null, 0, false), + new Column("ColumnVisible", "INT", null, 0, false) + )); + $tblTenantObjectInstanceProperties->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, "ID")), + new TableForeignKey("DataTypeID", new TableForeignKeyColumn($tblDataTypes, "ID")) + ); + $tables[] = $tblTenantObjectInstanceProperties; + + // Values of the object instance properties. + $tblTenantObjectInstancePropertyValues = new Table("TenantObjectInstancePropertyValues", "propval_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("InstanceID", "INT", null, null, false), + new Column("PropertyID", "INT", null, null, false), + new Column("Value", "LONGBLOB", null, null, false) + )); + $tblTenantObjectInstancePropertyValues->PrimaryKey = new TableKey(array + ( + new TableKeyColumn("InstanceID"), + new TableKeyColumn("PropertyID") + )); + $tblTenantObjectInstancePropertyValues->ForeignKeys = array + ( + new TableForeignKey("InstanceID", new TableForeignKeyColumn($tblTenantObjectInstances, "ID")), + new TableForeignKey("PropertyID", new TableForeignKeyColumn($tblTenantObjectInstanceProperties, "ID")) + ); + $tables[] = $tblTenantObjectInstancePropertyValues; + + // Object static methods. + $tblTenantObjectMethods = new Table("TenantObjectMethods", "method_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("Name", "VARCHAR", 256, null, false), + new Column("CodeBlob", "LONGBLOB", null, null, false) + )); + $tblTenantObjectMethods->ForeignKeys = array + ( + new TableForeignKey("ObjectID", new TableForeignKeyColumn($tblTenantObjects, "ID")) + ); + $tables[] = $tblTenantObjectMethods; + + // Object static method namespace references. + $tblTenantObjectMethodNamespaceReferences = new Table("TenantObjectMethodNamespaceReferences", "ns_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("MethodID", "INT", null, null, false), + new Column("Value", "VARCHAR", 256, null, false) + )); + $tblTenantObjectMethodNamespaceReferences->ForeignKeys = array + ( + new TableForeignKey("MethodID", new TableForeignKeyColumn($tblTenantObjectMethods, "ID")) + ); + $tables[] = $tblTenantObjectMethodNamespaceReferences; + + // Object instance methods. + $tblTenantObjectInstanceMethods = new Table("TenantObjectInstanceMethods", "method_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("ObjectID", "INT", null, null, false), + new Column("Name", "VARCHAR", 256, null, false), + new Column("CodeBlob", "LONGBLOB", null, null, false) + )); + $tables[] = $tblTenantObjectInstanceMethods; + + // Object static method namespace references. + $tblTenantObjectInstanceMethodNamespaceReferences = new Table("TenantObjectInstanceMethodNamespaceReferences", "ns_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("MethodID", "INT", null, null, false), + new Column("Value", "VARCHAR", 256, null, false) + )); + $tables[] = $tblTenantObjectInstanceMethodNamespaceReferences; +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/DataCenters.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/DataCenters.inc.php new file mode 100644 index 00000000..1dad40b0 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/DataCenters.inc.php @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/DebugMessages.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/DebugMessages.inc.php new file mode 100644 index 00000000..0e633ae6 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/DebugMessages.inc.php @@ -0,0 +1,51 @@ +ForeignKeys = array + ( + new TableForeignKey("MessageID", new TableForeignKeyColumn($tblDebugMessages, "ID"), TableForeignKeyReferenceOption::Cascade) + ); + $tables[] = $tblDebugMessageBacktraces; + + $tblDebugMessageParameters = new Table("DebugMessageParameters", "mp_", array + ( + // $name, $dataType, $size, $value, $allowNull, $primaryKey, $autoIncrement + new Column("ID", "INT", null, null, false, true, true), + new Column("MessageID", "INT", null, null, false), + new Column("Name", "LONGTEXT", null, null, false), + new Column("Value", "LONGTEXT", null, null, true) + )); + $tblDebugMessageParameters->ForeignKeys = array + ( + new TableForeignKey("MessageID", new TableForeignKeyColumn($tblDebugMessages, "ID"), TableForeignKeyReferenceOption::Cascade) + ); + $tables[] = $tblDebugMessageParameters; +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/Languages.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/Languages.inc.php new file mode 100644 index 00000000..9f30e6f8 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/Languages.inc.php @@ -0,0 +1,213 @@ +Introduce yourself!") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "invitegroup"), + new RecordColumn("StringValue", "Invite this user to join a group") + )), + + // === account/settings + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "personal"), + new RecordColumn("StringValue", "Personal Information") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "realname_label"), + new RecordColumn("StringValue", "What's your real name?") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "realname_example"), + new RecordColumn("StringValue", "Johnny Test") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "birthdate_label"), + new RecordColumn("StringValue", "When were you born?") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "birthdate_example"), + new RecordColumn("StringValue", "1994-03-25") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "email_label"), + new RecordColumn("StringValue", "What's your e-mail address?") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "email_example"), + new RecordColumn("StringValue", "somebody@phoenixsns.net") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "appearance"), + new RecordColumn("StringValue", "Appearance and Personalization") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "longname_label"), + new RecordColumn("StringValue", "What do you want to be called?") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "longname_example"), + new RecordColumn("StringValue", "Phenix the Great") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "startpage_label"), + new RecordColumn("StringValue", "When I log in, take me to:") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "shortname_label"), + new RecordColumn("StringValue", "Your site URL name:") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "shortname_example"), + new RecordColumn("StringValue", "phenix") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "language_label"), + new RecordColumn("StringValue", "Default language:") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "security"), + new RecordColumn("StringValue", "Security and Authentication") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "profile_visibility_label"), + new RecordColumn("StringValue", "Who can see my profile?") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "deactivate_account"), + new RecordColumn("StringValue", "Deactivate Account") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "use_with_caution"), + new RecordColumn("StringValue", "Please exercise great care when considering this option. Once done, it cannot be un-done.") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "deactivate_account_warning"), + new RecordColumn("StringValue", "Would you like to deactivate your account and lose all your items, resources, conversation history, friends, group memberships, and other site features? If so, click the link.") + )), + new Record(array + ( + new RecordColumn("LanguageID", 1), + new RecordColumn("StringName", "deactivate_account_button"), + new RecordColumn("StringValue", "Yes, please deactivate my account now.") + )) + )); +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/PaymentPlans.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/PaymentPlans.inc.php new file mode 100644 index 00000000..2f7e356f --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/PaymentPlans.inc.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/SecurityPermissions.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/SecurityPermissions.inc.php new file mode 100644 index 00000000..9cba3022 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/SecurityPermissions.inc.php @@ -0,0 +1,126 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/TenantDataCenters.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/TenantDataCenters.inc.php new file mode 100644 index 00000000..9a920dea --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/TenantDataCenters.inc.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/TenantTypes.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/TenantTypes.inc.php new file mode 100644 index 00000000..edb96f4c --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/TenantTypes.inc.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Modules/001-Setup/Tables/Users.inc.php b/PHP/Manager/Include/Modules/001-Setup/Tables/Users.inc.php new file mode 100644 index 00000000..683c06e5 --- /dev/null +++ b/PHP/Manager/Include/Modules/001-Setup/Tables/Users.inc.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/000-LoginPage.inc.php b/PHP/Manager/Include/Pages/000-LoginPage.inc.php new file mode 100644 index 00000000..3cbe562c --- /dev/null +++ b/PHP/Manager/Include/Pages/000-LoginPage.inc.php @@ -0,0 +1,48 @@ + +

Authentication Required

+

You must log in to view this page.

+
+ + + + + + + + + + + + + + + +
+ InvalidCredentials) + { + ?>Incorrect user name/password combination. +
+ +
+
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/000-MainPage.inc.php b/PHP/Manager/Include/Pages/000-MainPage.inc.php new file mode 100644 index 00000000..6cd5e46b --- /dev/null +++ b/PHP/Manager/Include/Pages/000-MainPage.inc.php @@ -0,0 +1,116 @@ + +

Tenant Management

+

There are tenants in total.

+ + + IsExpired()) + { + $countExpired++; + } + else + { + $countActive++; + } + } + ?> +

Active Tenants ()

+ + + + + + + + + + + + IsExpired()) continue; + ?> + + + + + + + + + + + +
Tenant NameTenant TypeData CentersPayment PlanActivation DateTermination DateDescriptionActions
URL)); ?>" target="_blank">URL); ?>Type->Title); ?>DataCenters->Items as $item) + { + echo("HostName . "/" . $tenant->URL . "\">" . $item->Title . " (" . $item->HostName . ")
"); + } + ?>
PaymentPlan->Title); ?>BeginTimestamp == null ? "(indefinite)" : $tenant->BeginTimestamp); ?>EndTimestamp == null ? "(indefinite)" : $tenant->EndTimestamp); ?>Description); ?> + URL)); ?>">Manage | + URL)); ?>">Edit | + URL)); ?>">Clone | + URL)); ?>">Delete +
+

Inactive Tenants ()

+ + + + + + + + + + + + IsExpired()) continue; + ?> + + + + + + + + + + + +
Tenant NameTenant TypeData CentersPayment PlanActivation DateTermination DateDescriptionActions
URL)); ?>" target="_blank">URL); ?>Type->Title); ?>DataCenter->Title); ?>PaymentPlan->Title); ?>BeginTimestamp == null ? "(indefinite)" : $tenant->BeginTimestamp); ?>EndTimestamp == null ? "(indefinite)" : $tenant->EndTimestamp); ?>Description); ?> + URL)); ?>">Manage | + URL)); ?>">Edit | + URL)); ?>">Clone | + URL)); ?>">Delete +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/001-TenantPropertiesPage.inc.php b/PHP/Manager/Include/Pages/001-TenantPropertiesPage.inc.php new file mode 100644 index 00000000..cfb2f2d2 --- /dev/null +++ b/PHP/Manager/Include/Pages/001-TenantPropertiesPage.inc.php @@ -0,0 +1,104 @@ +Tenant != null) + { + $this->Title = "Edit Tenant Configuration: " . $this->Tenant->URL; + } + else + { + $this->Title = "Create New Tenant"; + } + } + + protected function RenderContent() + { + ?> +

Edit Tenant Configuration

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
Tenant != null && $this->Tenant->DataCenters->Contains($datacenter)) { echo(" checked=\"checked\""); } ?> name="tenant_DataCenter_ID); ?>" id="txtTenantDataCenter_ID); ?>" /> + +
+ +
+
+ + ">Cancel +
+
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/002-ConfirmOperationPage.inc.php b/PHP/Manager/Include/Pages/002-ConfirmOperationPage.inc.php new file mode 100644 index 00000000..37ee1263 --- /dev/null +++ b/PHP/Manager/Include/Pages/002-ConfirmOperationPage.inc.php @@ -0,0 +1,39 @@ +ReturnButtonURL = "~/"; + } + + protected function RenderContent() + { + ?> +

Confirm Operation

+

Message); ?>

+
+ + + Cancel +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/003-TenantManagementPage.inc.php b/PHP/Manager/Include/Pages/003-TenantManagementPage.inc.php new file mode 100644 index 00000000..363df834 --- /dev/null +++ b/PHP/Manager/Include/Pages/003-TenantManagementPage.inc.php @@ -0,0 +1,125 @@ +Title = "Manage Tenant: " . $this->Tenant->URL; + } + + protected function RenderContent() + { + ?> +

Tenant: Tenant->URL); ?>

+
+ TabPages[] = new TabPage("tabCustomProperties", "Custom Properties", null, null, null, function() + { + ?> + + + + + + + + Tenant->GetProperties(); + foreach ($properties as $property) + { + ?> + + + + + + + +
[+]PropertyDescriptionValue
[+]Name); ?>Description); ?>RenderEditor($this->Tenant->GetPropertyValue($property)); ?>
+ TabPages[] = new TabPage("tabEnabledModules", "Enabled Modules", null, null, null, function() + { + ?> +

Click on a module name to configure the module on this tenant.

+ + + + + + Tenant); + foreach ($modules as $module) + { + ?> + + + + + +
ModuleDescription
Enabled) { echo(" checked=\"checked\""); } ?> /> Tenant->URL . "/modules/" . $module->ID)); ?>">Title); ?>Description); ?>
+ TabPages[] = new TabPage("tabGlobalObjects", "Global Objects", null, null, null, function() + { + ?> +

Lists all of the objects that are available on this tenant that are not associated with a particular Module.

+ + + + + + + Tenant); + foreach ($objects as $object) + { + ?> + + + + + + +
ObjectDescriptionInstances
Tenant->URL . "/objects/" . $object->ID)); ?>">Name); ?>Description); ?>Tenant->URL . "/objects/" . $object->ID . "/instances")); ?>">CountInstances()); ?>
+ Render(); + ?> +
+ + ">Cancel +
+
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/004-TenantModuleManagementPage.inc.php b/PHP/Manager/Include/Pages/004-TenantModuleManagementPage.inc.php new file mode 100644 index 00000000..db81bf24 --- /dev/null +++ b/PHP/Manager/Include/Pages/004-TenantModuleManagementPage.inc.php @@ -0,0 +1,95 @@ +Module != null) + { + $this->Title = "Manage Tenant Module: " . $this->Module->Title . " on " . $this->Tenant->URL; + } + else + { + $this->Title = "Manage Tenant Modules: " . $this->Tenant->URL; + } + } + + protected function RenderContent() + { + if ($this->Module != null) + { + ?> +

Module: Module->Title); ?> on Tenant->URL); ?>

+

Module Configurable Properties

+ + + + + + + Module->GetProperties(); + foreach ($properties as $property) + { + ?> + + + + + + +
[+]PropertyValue
[+]Title); ?>
+ +

Tenant: Tenant->URL); ?>

+ +

Tenant Enabled Modules

+

Click on a module name to configure it

+ + + + + + Tenant); + foreach ($modules as $module) + { + ?> + + + + + +
ModuleDescription
Enabled) { echo(" checked=\"checked\""); } ?> /> Tenant->URL . "/modules/" . $module->ID)); ?>">Title); ?>Description); ?>
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/005-ModuleMainPage.inc.php b/PHP/Manager/Include/Pages/005-ModuleMainPage.inc.php new file mode 100644 index 00000000..6a884177 --- /dev/null +++ b/PHP/Manager/Include/Pages/005-ModuleMainPage.inc.php @@ -0,0 +1,41 @@ + +

Module Management

+

There are modules in total. Click a module name to configure that module.

+ + + + + + + + + + + + + +
ModuleDescription
ID)); ?>">Title); ?>Description); ?>
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/006-ModuleManagementPage.inc.php b/PHP/Manager/Include/Pages/006-ModuleManagementPage.inc.php new file mode 100644 index 00000000..212d3cc8 --- /dev/null +++ b/PHP/Manager/Include/Pages/006-ModuleManagementPage.inc.php @@ -0,0 +1,84 @@ +Title = "Manage Module: " . $this->Module->Title; + } + + protected function RenderContent() + { + ?> +

Module Management

+

Module->Title); ?>

+ +
+

Information

+ + + + + + + + + +
Title:
Description:
+ +

Application Menu Items

+ + + + + + + Module->GetMainMenuItems(); + foreach ($menuitems as $menuitem) + { + ?> + + + + + + +
TitleDescriptionTarget
Title); ?>Description); ?>TargetURL); ?>
+ +

Module Pages

+ + + + + + + + + +
URL
ID)); ?>">Title); ?>
+ +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/007-DataCenterMainPage.inc.php b/PHP/Manager/Include/Pages/007-DataCenterMainPage.inc.php new file mode 100644 index 00000000..dc58d8ac --- /dev/null +++ b/PHP/Manager/Include/Pages/007-DataCenterMainPage.inc.php @@ -0,0 +1,43 @@ + +

Data Center Management

+

There are data centers in total. Click a data center name to configure that data center.

+ + + + + + + + + + + + + + + +
Data CenterDescriptionHostname
ID)); ?>">Title); ?>Description); ?>HostName); ?>
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/008-DataCenterManagementPage.inc.php b/PHP/Manager/Include/Pages/008-DataCenterManagementPage.inc.php new file mode 100644 index 00000000..baaaf006 --- /dev/null +++ b/PHP/Manager/Include/Pages/008-DataCenterManagementPage.inc.php @@ -0,0 +1,48 @@ +Title = "Manage Data Center: " . $this->DataCenter->Title; + } + + protected function RenderContent() + { + ?> +

Data Center Management

+

DataCenter->Title); ?>

+ +
+

Information

+ + + + + + + + + + + + + +
Title:
Description:
Hostname:
+ + +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/009-TenantObjectManagementPage.inc.php b/PHP/Manager/Include/Pages/009-TenantObjectManagementPage.inc.php new file mode 100644 index 00000000..d8ce5094 --- /dev/null +++ b/PHP/Manager/Include/Pages/009-TenantObjectManagementPage.inc.php @@ -0,0 +1,224 @@ +CurrentObject != null) + { + $this->Title = "Manage Tenant Object: " . $this->CurrentObject->Name . " on " . $this->CurrentTenant->URL; + } + else + { + $this->Title = "Manage Tenant Objects: " . $this->CurrentTenant->URL; + } + } + + protected function RenderContent() + { + if ($this->CurrentObject != null) + { + ?> +

Object: CurrentObject->Name); ?> on CurrentTenant->URL); ?>

+
+ TabPages[] = new TabPage("tabStaticProperties", "Static Properties", null, null, null, function() + { + ?> + + + + + + + + CurrentObject->GetProperties(); + foreach ($properties as $property) + { + ?> + + + + + + + +
[+]PropertyData TypeDefault Value
[+]Name); ?>DataType == null ? "(undefined)" : "DataType->ID) . "\">" . $property->DataType->Name . ""); ?> + DataType == null || $property->DataType->ColumnRendererCodeBlob == null) + { + ?> + + DataType->ColumnRendererCodeBlob, $property->Value); + } + ?> +
+ TabPages[] = new TabPage("tabInstanceProperties", "Instance Properties", null, null, null, function() + { + ?> + + + + + + + + + + CurrentObject->GetInstanceProperties(); + foreach ($properties as $property) + { + ?> + + + + + + + +
[+]PropertyData TypeDefault Value
[+]Name); ?>DataType == null ? "(undefined)" : "DataType->ID) . "\">" . $property->DataType->Name . ""); ?> + RenderColumn(); + ?> +
+ TabPages[] = new TabPage("tabStaticMethods", "Static Methods", null, null, null, function() + { + ?> + + + + + + + + CurrentObject->GetMethods(); + foreach ($methods as $method) + { + ?> + + + + + + + +
[+]MethodDescriptionReturn Data Type
[+]CurrentTenant->URL . "/objects/" . $this->CurrentObject->ID . "/methods/static/" . $method->ID)); ?>">Name); ?>Description); ?>DataType == null ? "(undefined)" : "" . $method->DataType->Name . ""); */ ?>
+ TabPages[] = new TabPage("tabInstances", "Instances", null, null, null, function() + { + ?> + + + CurrentObject->GetInstanceProperties(); + foreach ($properties as $property) + { + if ($property->ColumnVisible) + { + echo(""); + } + } + ?> + + CurrentObject->GetInstances(); + foreach ($instances as $instance) + { + ?> + + ColumnVisible) + { + echo(""); + } + } + ?> + + +
" . $property->Name . "
"); + $value = $instance->GetPropertyValue($property); + $property->RenderColumn($value); + echo("
+ Render(); + ?> + + +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/010-TenantObjectMethodManagementPage.inc.php b/PHP/Manager/Include/Pages/010-TenantObjectMethodManagementPage.inc.php new file mode 100644 index 00000000..a9ce1253 --- /dev/null +++ b/PHP/Manager/Include/Pages/010-TenantObjectMethodManagementPage.inc.php @@ -0,0 +1,96 @@ +StyleSheets[] = new WebStyleSheet("http://static.alcehosting.net/dropins/CodeMirror/StyleSheets/CodeMirror.css"); + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Addons/Edit/MatchBrackets.js"); + + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Modes/clike/clike.js"); + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Modes/php/php.js"); + } + + protected function Initialize() + { + if ($this->CurrentMethod != null) + { + $this->Title = "Manage Method: " . $this->CurrentMethod->Name . " on " . $this->CurrentObject->Name . "@" . $this->CurrentTenant->URL; + } + else + { + $this->Title = "Manage Methods for Object: " . $this->CurrentObject->Name . " on " . $this->CurrentTenant->URL; + } + } + + protected function RenderContent() + { + if ($this->CurrentObject != null) + { + ?> +

Method: CurrentMethod->Name); ?> on CurrentObject->Name); ?>@CurrentTenant->URL); ?>

+ + + + + +
+

Code Blob

+
+ + + + +
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/011-TenantObjectInstanceBrowsePage.inc.php b/PHP/Manager/Include/Pages/011-TenantObjectInstanceBrowsePage.inc.php new file mode 100644 index 00000000..7d08c81e --- /dev/null +++ b/PHP/Manager/Include/Pages/011-TenantObjectInstanceBrowsePage.inc.php @@ -0,0 +1,75 @@ +Title = "Browse Instances of Tenant Object: " . $this->CurrentObject->Name . " on " . $this->CurrentTenant->URL; + } + + protected function RenderContent() + { + if ($this->CurrentObject != null) + { + ?> +

Object: CurrentObject->Name); ?> on CurrentTenant->URL); ?>

+

Object Instances

+ + + CurrentObject->GetInstanceProperties(); + foreach ($properties as $property) + { + if ($property->ColumnVisible) + { + echo(""); + } + } + ?> + + CurrentObject->GetInstances(); + foreach ($instances as $instance) + { + ?> + + ColumnVisible) + { + echo(""); + } + } + ?> + + +
" . $property->Name . "
"); + $value = $instance->GetPropertyValue($property); + $property->RenderColumn($value); + echo("
+ \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/012-DataTypeModifyPage.inc.php b/PHP/Manager/Include/Pages/012-DataTypeModifyPage.inc.php new file mode 100644 index 00000000..0daabe60 --- /dev/null +++ b/PHP/Manager/Include/Pages/012-DataTypeModifyPage.inc.php @@ -0,0 +1,252 @@ +StyleSheets[] = new WebStyleSheet("http://static.alcehosting.net/dropins/CodeMirror/StyleSheets/CodeMirror.css"); + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Addons/Edit/MatchBrackets.js"); + + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Modes/clike/clike.js"); + $this->Scripts[] = new WebScript("http://static.alcehosting.net/dropins/CodeMirror/Scripts/Modes/php/php.js"); + } + + protected function Initialize() + { + if ($this->CurrentDataType != null) + { + $this->Title = "Manage Data Type: " . $this->CurrentDataType->Name; + } + else + { + $this->Title = "Manage Data Types"; + } + } + + protected function RenderContent() + { + if ($this->CurrentDataType != null) + { + ?> +

Modify Data Type: CurrentDataType->Name); ?>

+

Create Data Type

+ + +
+ CurrentDataType != null) + { + echo("CurrentDataType->ID . "\" />"); + } + + $fv = new FormView("fv"); + $fv->Items[] = new FormViewItemText("txtDataTypeName", "datatype_Name", "Name", $this->CurrentDataType->Name); + $fv->Items[0]->Required = true; + + $fv->Items[] = new FormViewItemMemo("txtDataTypeDescription", "datatype_Description", "Description", $this->CurrentDataType->Description); + $fv->Render(); + ?> + OnClientTabChanged = "tbs_OnClientTabChanged();"; + $tbs->TabPages[] = new TabPage("tabEncoder", "Encoder", null, null, null, function() + { + ?> + + TabPages[] = new TabPage("tabDecoder", "Decoder", null, null, null, function() + { + ?> + + TabPages[] = new TabPage("tabColumnRenderer", "Column Renderer", null, null, null, function() + { + ?> + + TabPages[] = new TabPage("tabEditorRenderer", "Editor Renderer", null, null, null, function() + { + ?> + + Render(); + ?> +
+ + ">Cancel +
+
+ + + + + + + + + + + + +
NameDescription
ID)); ?>">Name); ?>Description); ?>
+ + Render(); + return true; + }), + new ModulePage("modify", function($path) + { + if ($_SERVER["REQUEST_METHOD"] == "POST") + { + if (isset($_POST["datatype_ID"])) + { + $datatype = DataType::GetByID($_POST["datatype_ID"]); + } + else + { + $datatype = new DataType(); + } + $datatype->Name = $_POST["datatype_Name"]; + $datatype->Description = $_POST["datatype_Description"]; + $datatype->EncoderCodeBlob = $_POST["datatype_EncoderCodeBlob"]; + $datatype->DecoderCodeBlob = $_POST["datatype_DecoderCodeBlob"]; + $datatype->ColumnRendererCodeBlob = $_POST["datatype_ColumnRendererCodeBlob"]; + $datatype->EditorRendererCodeBlob = $_POST["datatype_EditorRendererCodeBlob"]; + $datatype->Update(); + + System::Redirect("~/datatype"); + } + else + { + $page = new DataTypeModifyPage(); + $page->CurrentDataType = DataType::GetByID($path[0]); + $page->Render(); + } + return true; + }) + )) + )); +?> \ No newline at end of file diff --git a/PHP/Manager/Include/Pages/Default.wfx b/PHP/Manager/Include/Pages/Default.wfx deleted file mode 100644 index ffea97aa..00000000 --- a/PHP/Manager/Include/Pages/Default.wfx +++ /dev/null @@ -1,29 +0,0 @@ -<%@ Page ModuleName="com.universaleditor.manager.Default" URL="/" %> - - - This is a test - - -
- - - - - - - - - -
Name type: - - - Legal - Preferred - Maiden - Other - - -
Name:
-
- - diff --git a/PHP/Manager/Include/UUID.inc.php b/PHP/Manager/Include/UUID.inc.php new file mode 100644 index 00000000..431d1e94 --- /dev/null +++ b/PHP/Manager/Include/UUID.inc.php @@ -0,0 +1,81 @@ +urand = @fopen ( '/dev/urandom', 'rb' ); + } + + public static function Generate() + { + $uuid = new UUID(); + return $uuid->get(); + } + + /** + * @brief Generates a Universally Unique IDentifier, version 4. + * + * This function generates a truly random UUID. The built in CakePHP String::uuid() function + * is not cryptographically secure. You should uses this function instead. + * + * @see http://tools.ietf.org/html/rfc4122#section-4.4 + * @see http://en.wikipedia.org/wiki/UUID + * @return string A UUID, made up of 32 hex digits and 4 hyphens. + */ + function get() { + + $pr_bits = false; + if (is_a ( $this, 'uuid' )) { + if (is_resource ( $this->urand )) { + $pr_bits .= @fread ( $this->urand, 16 ); + } + } + if (! $pr_bits) { + $fp = @fopen ( '/dev/urandom', 'rb' ); + if ($fp !== false) { + $pr_bits .= @fread ( $fp, 16 ); + @fclose ( $fp ); + } else { + // If /dev/urandom isn't available (eg: in non-unix systems), use mt_rand(). + $pr_bits = ""; + for($cnt = 0; $cnt < 16; $cnt ++) { + $pr_bits .= chr ( mt_rand ( 0, 255 ) ); + } + } + } + $time_low = bin2hex ( substr ( $pr_bits, 0, 4 ) ); + $time_mid = bin2hex ( substr ( $pr_bits, 4, 2 ) ); + $time_hi_and_version = bin2hex ( substr ( $pr_bits, 6, 2 ) ); + $clock_seq_hi_and_reserved = bin2hex ( substr ( $pr_bits, 8, 2 ) ); + $node = bin2hex ( substr ( $pr_bits, 10, 6 ) ); + + /** + * Set the four most significant bits (bits 12 through 15) of the + * time_hi_and_version field to the 4-bit version number from + * Section 4.1.3. + * @see http://tools.ietf.org/html/rfc4122#section-4.1.3 + */ + $time_hi_and_version = hexdec ( $time_hi_and_version ); + $time_hi_and_version = $time_hi_and_version >> 4; + $time_hi_and_version = $time_hi_and_version | 0x4000; + + /** + * Set the two most significant bits (bits 6 and 7) of the + * clock_seq_hi_and_reserved to zero and one, respectively. + */ + $clock_seq_hi_and_reserved = hexdec ( $clock_seq_hi_and_reserved ); + $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2; + $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000; + + return strtoupper( sprintf ( '%08s%04s%04x%04x%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node ) ); + } + + public static function format($input) + { + $output = $input; + $output = substr($output, 0, 8) . "-" . substr($output, 8, 4) . "-" . substr($output, 12, 4) . "-" . substr($output, 16, 4) . "-" . substr($output, 20); + return "{" . $output . "}"; + } +} +?> \ No newline at end of file diff --git a/PHP/Manager/index.php b/PHP/Manager/index.php index ee65b6a2..33eb33c3 100644 --- a/PHP/Manager/index.php +++ b/PHP/Manager/index.php @@ -25,6 +25,7 @@ // Now that we have defined the root path, load the WebFX content (which also // include_once's the modules and other WebFX-specific stuff) require_once("WebFX/WebFX.inc.php"); + require_once("Include/UUID.inc.php"); // Bring in the WebFX\System and WebFX\IncludeFile classes so we can simply refer // to them (in this file only) as "System" and "IncludeFile", respectively, from diff --git a/PHP/TODO.txt b/PHP/TODO.txt new file mode 100644 index 00000000..bd98ad65 --- /dev/null +++ b/PHP/TODO.txt @@ -0,0 +1,62 @@ +Create an object (if user has permissions): +http://hosted1.universaleditor.com/default/o/create +View an object: +http://hosted1.universaleditor.com/default/o/177 +http://hosted1.universaleditor.com/default/o/177/display +Edit an object: +http://hosted1.universaleditor.com/default/o/177/modify +Delete an object: +http://hosted1.universaleditor.com/default/o/177/delete + +Create an object instance (if user has permissions): +http://hosted1.universaleditor.com/default/i/create +View an object instance: +http://hosted1.universaleditor.com/default/i/177 +http://hosted1.universaleditor.com/default/i/177/display +Edit an object instance: +http://hosted1.universaleditor.com/default/i/177/modify +Delete an object instance: +http://hosted1.universaleditor.com/default/i/177/delete + +Object instance's appearance in Display mode is specified by the object's DisplayTemplate: + + + + + +

Instance Title); ?>

+
+
+
+ + + + ... + + + +
+ +Create a task (if user has permissions): +http://hosted1.universaleditor.com/default/t/create +View a task's properties: +http://hosted1.universaleditor.com/default/t/177 [ Task.DefaultAction = Display ] +http://hosted1.universaleditor.com/default/t/177/display +Edit a task: +http://hosted1.universaleditor.com/default/t/177/modify +Delete a task: +http://hosted1.universaleditor.com/default/t/177/delete +Execute a task: +http://hosted1.universaleditor.com/default/t/177 [ Task.DefaultAction = Execute ] +http://hosted1.universaleditor.com/default/t/177/execute +Execute a task with parameters: +http://hosted1.universaleditor.com/default/t/177/execute/[base64-encoded parameters list] + +Base64-encoded parameters list: +{ + "parameter name": "value", + "parameter 2 name": "value 2" +} +etc. \ No newline at end of file diff --git a/PHP/Website/.htaccess b/PHP/Tenant/.htaccess similarity index 100% rename from PHP/Website/.htaccess rename to PHP/Tenant/.htaccess diff --git a/PHP/Tenant/Include/Modules/000-Default/Main.inc.php b/PHP/Tenant/Include/Modules/000-Default/Main.inc.php new file mode 100644 index 00000000..5b160d63 --- /dev/null +++ b/PHP/Tenant/Include/Modules/000-Default/Main.inc.php @@ -0,0 +1,347 @@ +query($query); + if ($result->num_rows < 1) return false; + return true; + } + + function GetResourceBundles() + { + $ResourceBundles = array + ( + new ResourceBundle("Common") + ); + + $tenant = Tenant::GetCurrent(); + + // References to ResourceBundle objects are stored in a MultipleInstanceProperty called "ResourceBundles" on the tenant + $bundles = $tenant->GetPropertyValue("ResourceBundles")->GetInstances(); + foreach ($bundles as $bundle) + { + $ResourceBundles[] = new ResourceBundle($bundle->GetPropertyValue("Name")); + } + return $ResourceBundles; + } + function CompileStyleSheets($compile = true) + { + global $RootPath; + $ResourceBundles = GetResourceBundles(); + + $FilePaths = array(); + + $lesstext = ""; + foreach ($ResourceBundles as $bundle) + { + $lesstext .= $bundle->CompileStyleSheets(); + } + if ($compile) + { + try + { + $less = new \lessc(); + $less->setFormatter("compressed"); + $csstext = $less->compile($lesstext); + + echo("/* compiled with lessphp v0.4.0 - GPLv3/MIT - http://leafo.net/lessphp */\n"); + echo("/* for human-readable source of this file, append ?compile=false to the file name */\n"); + echo($csstext); + } + catch (\Exception $e) + { + echo "/* " . $e->getMessage() . " */\n"; + } + } + else + { + echo($lesstext); + } + } + function CompileScripts($compile = true) + { + global $RootPath; + $ResourceBundles = GetResourceBundles(); + + $FilePaths = array(); + + $lesstext = ""; + foreach ($ResourceBundles as $bundle) + { + $lesstext .= $bundle->CompileScripts(); + } + + if ($compile) + { + try + { + $jstext = \JShrink\Minifier::minify($lesstext, array('flaggedComments' => false)); + + echo("/* compiled with JShrink v0.5.2 - BSD 3-clause - https://github.com/tedivm/JShrink */\n"); + echo("/* for human-readable source of this file, append ?compile=false to the file name */\n"); + echo($jstext); + } + catch (\Exception $e) + { + echo "/* " . $e->getMessage() . " */\n"; + } + } + else + { + echo($lesstext); + } + } + + function IsValidUserOrGuest() + { + $CurrentTenant = Tenant::GetCurrent(); + + if (!isset($_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"]) && !isset($_SESSION["CurrentPassword[" . $CurrentTenant->ID . "]"])) return true; + $user = User::GetByLoginID($_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"]); + if ($user == null) return true; + + return IsAuthenticated(); + } + function IsAuthenticated() + { + $CurrentTenant = Tenant::GetCurrent(); + + if (isset($_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"]) && isset($_SESSION["CurrentPassword[" . $CurrentTenant->ID . "]"])) + { + $user = $CurrentTenant->GetObject("User")->GetMethod("ValidateCredentials")->Execute(array + ( + new TenantObjectMethodParameterValue("username", $_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"]), + new TenantObjectMethodParameterValue("password", $_SESSION["CurrentPassword[" . $CurrentTenant->ID . "]"]) + )); + return ($user != null); + } + return false; + } + function IsModuleAuthenticationRequired($path) + { + switch ($path) + { + case "dashboard": + case "world": + { + return true; + } + } + return false; + } + + System::$BeforeLaunchEventHandler = function($path) + { + if ($path[0] == "images" || $path[0] == "StyleSheet.css" || $path[0] == "Script.js" || ($path[0] == "account" && ($path[1] == "login.page" || $path[1] == "register.page"))) return true; + + // ensure our tenant has not expired yet + $tenant = Tenant::GetByURL(System::$TenantName); + if ($tenant == null || $tenant->IsExpired()) + { + $page = new ErrorPage(); + $page->Message = "The specified tenant does not exist. Please contact the site administrator to resolve this problem."; + $page->Render(); + return false; + } + + if (!IsConfigured() && $path[0] != "setup") + { + System::Redirect("~/setup"); + return false; + } + if (!IsValidUserOrGuest()) + { + System::Redirect("~/account/login.page"); + return false; + } + + if (!IsAuthenticated() && IsModuleAuthenticationRequired($path[0])) + { + System::Redirect("~/account/login.page"); + return false; + } + return true; + }; + + System::$Modules[] = new Module("net.Objectify.Default", array + ( + new ModulePage("", function($path) + { + if (IsAuthenticated()) + { + $tenant = Tenant::GetCurrent(); + $tobjUser = $tenant->GetObject("User"); + $instUser = $tobjUser->GetMethod("GetCurrentUser")->Execute(); + + $propStartPage = $tobjUser->GetInstanceProperty("StartPage"); + + $startPageSet = $instUser->HasPropertyValue($propStartPage); + $startPage = $instUser->GetPropertyValue($propStartPage); + + if ($startPageSet) + { + /* + $spi = $startPage->Instance; + $spio = $startPage->Instance->ParentObject; + $startPage = $spi->GetPropertyValue($spio->GetProperty("Value")); + */ + System::Redirect($startPage); + } + else + { + System::Redirect("~/dashboard"); + } + return true; + } + + $page = new MainPage(); + $page->Render(); + return true; + }), + new ModulePage("dashboard", function($path) + { + $page = new DashboardPage(); + $page->Render(); + return true; + }), + new ModulePage("account", array + ( + new ModulePage("login.page", function($path) + { + $CurrentTenant = Tenant::GetCurrent(); + if ($CurrentTenant == null) return false; + + $page = new LoginPage(); + if (isset($_POST["member_username"]) && isset($_POST["member_password"])) + { + $object = $CurrentTenant->GetObject("User"); + $inst = $object->GetMethod("ValidateCredentials")->Execute(array + ( + new TenantObjectMethodParameterValue("username", $_POST["member_username"]), + new TenantObjectMethodParameterValue("password", $_POST["member_password"]) + )); + + if ($inst != null) + { + $_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"] = $_POST["member_username"]; + $_SESSION["CurrentPassword[" . $CurrentTenant->ID . "]"] = $_POST["member_password"]; + + if (isset($_SESSION["LoginRedirectURL"])) + { + System::Redirect($_SESSION["LoginRedirectURL"]); + } + else + { + System::Redirect("~/"); + } + return true; + } + else + { + $page->InvalidCredentials = true; + } + } + $page->Render(); + return true; + }), + new ModulePage("logout.page", function($path) + { + $CurrentTenant = Tenant::GetCurrent(); + + $_SESSION["CurrentUserName[" . $CurrentTenant->ID . "]"] = null; + $_SESSION["CurrentPassword[" . $CurrentTenant->ID . "]"] = null; + System::Redirect("~/"); + }) + )), + new ModulePage("images", function($path) + { + // load images from resources object + global $RootPath; + + $bundle = "Common"; + $filename = implode("/", $path); + if (isset($path[1])) + { + if ($path[1] != "") + { + $bundle = $path[0]; + array_shift($path); + $filename = implode("/", $path); + } + } + + $imagePath = $RootPath . "/Resources/" . $bundle . "/Images/" . implode("/", $path); + if (file_exists($imagePath)) + { + header("Content-Type: " . mime_content_type($imagePath)); + readfile($imagePath); + return true; + } + else + { + header("HTTP/1.1 404 Not Found"); + echo("The specified resource file was not found on this server."); + return false; + } + }), + new ModulePage("StyleSheet.css", function($path) + { + header("Content-Type: text/css"); + $compile = true; + if (isset($_GET["compile"])) $compile = ($_GET["compile"] != "false"); + $lesstext = CompileStyleSheets($compile); + echo($lesstext); + return true; + }), + new ModulePage("Script.js", function($path) + { + // load style sheet from resources object + header("Content-Type: text/javascript"); + $compile = true; + if (isset($_GET["compile"])) $compile = ($_GET["compile"] != "false"); + $lesstext = CompileScripts($compile); + echo($lesstext); + return true; + }) + )); +?> \ No newline at end of file diff --git a/PHP/Tenant/Include/Modules/000-Default/ResourceBundle.inc.php b/PHP/Tenant/Include/Modules/000-Default/ResourceBundle.inc.php new file mode 100644 index 00000000..8cef5d27 --- /dev/null +++ b/PHP/Tenant/Include/Modules/000-Default/ResourceBundle.inc.php @@ -0,0 +1,192 @@ +Name = $name; + } + + public function MakeRelativePath($filename) + { + global $RootPath; + if (substr($filename, 0, strlen($RootPath)) == $RootPath) + { + return "~/" . substr($filename, strlen($RootPath) + 1); + } + return $filename; + } + + // BEGIN: function from Sven Arduwie (http://us2.php.net/manual/en/function.realpath.php#84012) + public function get_absolute_path($path) + { + $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); + $parts = explode(DIRECTORY_SEPARATOR, $path); + $absolutes = array(); + foreach ($parts as $part) + { + if ('.' == $part) continue; + if ('..' == $part) + { + array_pop($absolutes); + } + else + { + $absolutes[] = $part; + } + } + return implode(DIRECTORY_SEPARATOR, $absolutes); + } + // END: function from Sven Arduwie (http://us2.php.net/manual/en/function.realpath.php#84012) + + public function MakeAbsolutePath($filename, $relativeTo = null) + { + global $RootPath; + if (strlen($filename) > 3 && substr($filename, 0, 3) == "../") + { + if ($relativeTo != null) + { + $path = $relativeTo . "/" . $filename; + return $this->get_absolute_path($path); + } + return $this->get_absolute_path($filename); + } + else if (strlen($filename) > 1 && substr($filename, 0, 1) == "/") + { + return $filename; + } + if ($relativeTo != null) + { + return $relativeTo . "/" . $filename; + } + return $RootPath . "/" . $filename; + } + + public function CompileImportableFile($filename, $importedFileName = null, $preprocessorToken = "#") + { + global $RootPath; + $filename = $this->MakeAbsolutePath($filename, dirname($importedFileName)); + $importedFileTitle = $this->MakeRelativePath($importedFileName); + + $lesstext = ""; + $filetitle = $this->MakeRelativePath($filename); + $lesstext .= "/* BEGIN FILE: " . $filetitle; + if ($importedFileTitle != null) + { + $lesstext .= " - IMPORTED FROM " . $importedFileTitle; + } + $lesstext .= " */\n"; + + if (file_exists($filename)) + { + $tmp = file_get_contents($filename); + if ($tmp === false) + { + $lesstext .= "/* ERROR: " . $filename . " */"; + } + else + { + $lesstext .= $tmp; + } + } + else + { + $lesstext .= "/*\n\tERROR: file does not exist\n\tFile name: \"" . $filename . "\""; + if ($importedFileTitle != null) + { + $lesstext .= "\n\tImported from: \"" . $importedFileTitle . "\""; + } + $lesstext .= "\n*/\n"; + } + $lesstext .= "\n"; + + $lesslines = explode("\n", $lesstext); + $lesstext = ""; + + $j = strlen($preprocessorToken . "import "); + foreach ($lesslines as $lessline) + { + if (substr(trim($lessline), 0, $j) == $preprocessorToken . "import ") + { + $importfilename = trim(substr($lessline, $j)); + $importfilename = substr($importfilename, 1, strlen($importfilename) - 3); // removes " and "; + + $lesstext .= $this->CompileImportableFile($importfilename, $filename, $preprocessorToken); + } + else + { + $lesstext .= $lessline . "\n"; + } + } + + $lesstext .= "/* END FILE: " . $filetitle; + if ($importedFileTitle != null) + { + $lesstext .= " - IMPORTED FROM " . $importedFileTitle; + } + $lesstext .= " */\n\n"; + return $lesstext; + } + + public function CompileStyleSheets() + { + global $RootPath; + $StyleSheetPath = $RootPath . "/Resources/" . $this->Name . "/StyleSheets"; + $lesstext = ""; + + $lesstext .= "/* BEGIN BUNDLE: " . $this->Name . " */\n"; + + $lesstext .= "/* include path: " . $StyleSheetPath . " - "; + + $lessFiles = glob($StyleSheetPath . "/*.less"); + $lesstext .= count($lessFiles) . " *.less files, "; + $cssFiles = glob($StyleSheetPath . "/*.css"); + $lesstext .= count($cssFiles) . " *.css files"; + $lesstext .= " */\n\n"; + + foreach ($lessFiles as $filename) + { + $lesstext .= $this->CompileImportableFile($filename, null, "@"); + } + foreach ($cssFiles as $filename) + { + $lesstext .= $this->CompileImportableFile($filename, null, "@"); + } + $lesstext .= "/* END BUNDLE: " . $this->Name . " */\n\n"; + return $lesstext; + } + + public function CompileScripts() + { + global $RootPath; + $ContentPaths = array + ( + "", + "Controls", + "Objects" + ); + $BasePath = $RootPath . "/Resources/" . $this->Name . "/Scripts"; + $lesstext = ""; + + $lesstext .= "/* BEGIN BUNDLE: " . $this->Name . " */\n"; + foreach ($ContentPaths as $ContentPath) + { + $truepath = $BasePath . "/" . $ContentPath; + $lesstext .= "/* include path: " . $truepath . " - "; + + $jsfiles = glob($truepath . "/*.js"); + $lesstext .= count($jsfiles) . " *.js files"; + $lesstext .= " */\n\n"; + + foreach ($jsfiles as $filename) + { + $lesstext .= $this->CompileImportableFile($filename, null, "@"); + } + } + $lesstext .= "/* END BUNDLE: " . $this->Name . " */\n\n"; + return $lesstext; + } + } +?> \ No newline at end of file diff --git a/PHP/Tenant/Include/Pages/DataFormatModifyPage.html b/PHP/Tenant/Include/Pages/DataFormatModifyPage.html deleted file mode 100644 index 041d0db1..00000000 --- a/PHP/Tenant/Include/Pages/DataFormatModifyPage.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - -

Modify Data Format

-

Slightly Mad Studios BFF archive

- -
- - - - - - - - - -
- -
-
- Import - Export -
-
-
- - - - - - - - - -
Data typeTitle
StringEncryption key
-
-
-
- -
- - \ No newline at end of file diff --git a/PHP/Tenant/Include/Pages/DataFormatModifyPage.wfx b/PHP/Tenant/Include/Pages/DataFormatModifyPage.wfx deleted file mode 100644 index a53817d6..00000000 --- a/PHP/Tenant/Include/Pages/DataFormatModifyPage.wfx +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - -

Modify Data Format

-

Slightly Mad Studios BFF archive

- - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PHP/Tenant/Include/Pages/EnumerationModifyPage.wfx b/PHP/Tenant/Include/Pages/EnumerationModifyPage.wfx deleted file mode 100644 index 578c3b1b..00000000 --- a/PHP/Tenant/Include/Pages/EnumerationModifyPage.wfx +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - -

Modify Enumeration

-

Slightly Mad Studios BFF Encryption Mode

- -

Possible values:

- - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PHP/Website/index.php b/PHP/Tenant/index.php similarity index 86% rename from PHP/Website/index.php rename to PHP/Tenant/index.php index ee65b6a2..cba49567 100644 --- a/PHP/Website/index.php +++ b/PHP/Tenant/index.php @@ -25,6 +25,7 @@ // Now that we have defined the root path, load the WebFX content (which also // include_once's the modules and other WebFX-specific stuff) require_once("WebFX/WebFX.inc.php"); + require_once("Include/UUID.inc.php"); // Bring in the WebFX\System and WebFX\IncludeFile classes so we can simply refer // to them (in this file only) as "System" and "IncludeFile", respectively, from @@ -32,6 +33,11 @@ use WebFX\System; use WebFX\IncludeFile; + // Tell WebFX that this is a tenanted hosting application. This will allow us to + // control much of the application through Tenant Manager rather than having to + // continually push out code updates. + System::$EnableTenantedHosting = true; + // Tell WebFX that we are ready to launch the application. This cycles through // all of the modules (usually you will define your main application content in // 000-Default) and executes the first module page that corresponds to the path diff --git a/PHP/Website/lessc.php b/PHP/Tenant/lessc.php similarity index 100% rename from PHP/Website/lessc.php rename to PHP/Tenant/lessc.php diff --git a/PHP/Website/Include/Configuration.inc.php b/PHP/Website/Include/Configuration.inc.php deleted file mode 100644 index e69de29b..00000000 diff --git a/PHP/Website/Include/MasterPages/000-WebPage.inc.php b/PHP/Website/Include/MasterPages/000-WebPage.inc.php deleted file mode 100644 index 6090f4a8..00000000 --- a/PHP/Website/Include/MasterPages/000-WebPage.inc.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/PHP/Website/Include/Modules/000-Default/Main.inc.php b/PHP/Website/Include/Modules/000-Default/Main.inc.php deleted file mode 100644 index 98c7a273..00000000 --- a/PHP/Website/Include/Modules/000-Default/Main.inc.php +++ /dev/null @@ -1,19 +0,0 @@ -Render(); - return true; - }) - )); -?> \ No newline at end of file diff --git a/PHP/Website/Include/Pages/000-MainPage.inc.php b/PHP/Website/Include/Pages/000-MainPage.inc.php deleted file mode 100644 index dfc0c073..00000000 --- a/PHP/Website/Include/Pages/000-MainPage.inc.php +++ /dev/null @@ -1,15 +0,0 @@ - - Welcome to Universal Editor! - \ No newline at end of file