/** * Creates a new selectbox in an elementcontainer, with room for an error/notice block and a label. * Clientside JS validation will be applied and can be chained using bitmasking. * @param string The id and the name of the formfield * @param \System\Collection\Map the options to be displayed * @param string The selectedvalue of the selectbox * @param string The error/notice to display in the elementcontainer * @param string The label to show before the element * @param int A bitwise combination of \Module\HTMLForm\FormBuilder\ValidationOptions for JS clientside validation * @return \Module\HTMLForm\Element\Label A Label with nested elements to be outputted to a form */ public static final function createSelectBox($id, \System\Collection\Map $options, $value = '', $notice = '', $label = '', $validationMethod = \Module\HTMLForm\FormBuilder\ValidationOptions::VALIDATE_NONE) { $vectorOptions = new \System\Collection\Vector(); foreach ($options as $index => $option) { $vOption = new \Module\HTMLForm\Element\Option($option, $index); $vectorOptions->add($vOption); } $selectBox = new \Module\HTMLForm\Element\Select($id); $selectBox->setId($id); $selectBox->addOptions($vectorOptions); $selectBox->setSelectedValue($value); if (!empty($notice)) { $selectBox->setClass('notice'); } self::applyValidationScript($selectBox, $validationMethod, ''); $container = new \Module\HTMLForm\Element\ElementContainer($selectBox, $notice); $label = new \Module\HTMLForm\Element\Label($container, $label); return $label; }
/** * Stores the current object back to the database. This function only does an incremental update, meaning that only the changed fields are updated. * The update reflects the changes made to the object, and does not consider updates to the database in the time between retrieval of this object * and the calling of this function. * This update is executed without the use of transactions. * @param string The condition to use for the update * @param \System\Collection\Vector The parameters for the condition * @return integer The amount of affected rows */ public function store($condition, \System\Collection\Vector $parameters) { $fieldMap = self::validateMap(self::$fieldMap); $conditionMap = self::validateMap(self::$conditionMap); $modifications = $this->validateInstanceMap($this->modifications); $virtualModifications = $this->validateInstanceMap($this->virtualModifications); $dataMap = $this->validateInstanceMap($this->data); //we dont do anything if we dont have anything to do, no modifications if (!$modifications->hasItems() && !$virtualModifications->hasItems()) { return 0; } if (!$conditionMap->keyExists($condition)) { throw new \System\Error\Exception\ObjectLoaderSourceException('Invalid condition given. Condition is not defined in ' . $this->getClassName() . '.'); } //create the query $tuples = new \System\Collection\Vector(); foreach ($modifications as $modification) { $dataField = $fieldMap->{$modification}; $tuples[] = "`" . mb_strtolower((string) $dataField['dbkey']) . "` = %?%"; } //iterate over all the virtual modifications as we do want to reflect those foreach ($virtualModifications as $virtualModification) { $tuples[] = "`" . mb_strtolower($virtualModification) . "` = %?%"; } //we get the table definitions again. could have saved this at load, but now we reduce memory footprint at the cost of neglectable slower saving. $querySources = self::createQuerySources(self::$xmlTree[get_class($this)]); $conditionString = $conditionMap->{$condition}; $sql = 'UPDATE ' . $querySources . ' SET ' . $tuples->convertToString() . ' ' . $conditionString; $query = new \System\Db\Query($this->getDatabase(), $sql); //bind the values to the query for setting the new values foreach ($modifications as $modification) { $fieldData = $fieldMap->{$modification}; $modification = mb_strtolower($modification); //get the type of the parameter. only integers and strings are supported switch (mb_strtolower((string) $fieldData['type'])) { case \System\Type::TYPE_BOOL: case \System\Type::TYPE_BOOLEAN: case \System\Type::TYPE_INT: case \System\Type::TYPE_INTEGER: $type = \System\Db\QueryType::TYPE_INTEGER; break; default: $type = \System\Db\QueryType::TYPE_STRING; } //we first check if the new value is set to nullify, if so, we actually store NULL if (isset($fieldData['nullify']) && (string) $fieldData['nullify'] == $dataMap->{$modification}) { $query->bind('NULL', \System\Db\QueryType::TYPE_QUERY); } elseif (isset($fieldData['encoding'])) { switch (mb_strtolower((string) $fieldData['encoding'])) { case self::ENCRYPTION_BASE64: $type = \System\Db\QueryType::TYPE_STRING; $query->bind(self::encodeBase64($dataMap->{$modification}), $type); break; case self::ENCRYPTION_XOR: $type = \System\Db\QueryType::TYPE_STRING; $query->bind(self::encodeXOR($dataMap->{$modification}), $type); break; case self::ENCRYPTION_AES: $type = \System\Db\QueryType::TYPE_STRING; $query->bind(self::encodeAES($dataMap->{$modification}), $type); break; default: throw new \System\Error\Exception\ObjectLoaderSourceException('The given encryptionmethod is not supported.'); } } else { $query->bind($dataMap->{$modification}, $type); } } //bind the values to the query for setting the new values foreach ($virtualModifications as $virtualModification) { $type = \System\Db\QueryType::TYPE_STRING; $virtualField = 'virtual_' . $virtualModification; $value = $dataMap->{$virtualField}; $query->bind((string) $value, $type); } //bind the condition values to the query $val = new \System\Security\Validate(); foreach ($parameters as $index => $param) { //we need to decide the type of the parameter. Currently we only support integers and strings. $type = \System\Db\QueryType::TYPE_INTEGER; if ($val->isInt($param, $index, null, null, true) == \System\Security\ValidateResult::VALIDATE_INVALIDVALUE) { $type = \System\Db\QueryType::TYPE_STRING; } $query->bind($param, $type); } //execute the query $this->getDatabase()->query($query); //reset the modified list, because we already stored this. No need to store the same things at successive calls. $modifications->clear(); return $this->getDatabase()->getAffectedRows(); }
/** * The main processing loop. This function is not supposed to exit. */ public final function run() { $time = time(); while (true) { //we make sure the mastersocket is in the sockets list if (empty($this->sockets)) { $this->sockets[self::MASTERSOCKET_KEY] = $this->masterSocket; } $read = $this->sockets; //these sockets are wachted for reading $write = array(); //these sockets are watched for writing $except = array(); //these sockets are watched for exceptions //we check for the changes in the socket list, and this modifies the arrays if (@socket_select($read, $write, $except, 0) === false) { $this->handleSocketError(); } //we iterate over all the read sockets to process them foreach ($read as $socket) { //when the socket is the master, we check if we can accept a new connection if ($socket == $this->masterSocket) { if ($client = @socket_accept($socket)) { $this->connect($client); } else { $this->handleSocketError(false); } } else { //there is a client socket with info to read $buffer = null; $numberOfBytes = @socket_recv($socket, $buffer, $this->maximumBufferSize, 0); if ($numberOfBytes === false) { $this->handleSocketError(false); $this->disconnect($socket); } elseif ($numberOfBytes == 0) { $this->disconnect($socket); } else { $connection = $this->getConnectionBySocket($socket); if (!$connection->getHandshake()) { $tmp = str_replace("\r", '', $buffer); if (strpos($tmp, "\n\n") === false) { //the client has not finished sending the initiation header, so we wait another cycle continue; } $this->doHandshake($connection, $buffer); } else { //we split the packet into frame and send it to deframe $this->splitPacket($numberOfBytes, $buffer, $connection); } } } } //prepare a cycle $connections = new \System\Collection\Vector(); foreach ($this->connections as $connection) { if ($connection != $this->masterSocket && !$connection->isHandlingPartialPacket() && !$connection->isSendingContinuous() && !$connection->isSentClose()) { $connections->add($connection); } } $onCycleEvent = new \System\Web\Websocket\Event\OnCycleEvent(); $onCycleEvent->setServer($this); $onCycleEvent->setConnections($connections); $onCycleEvent->raise(); if ($time != time()) { $on1SCycleEvent = new \System\Web\Websocket\Event\On1SCycleEvent(); $on1SCycleEvent->setServer($this); $on1SCycleEvent->setConnections($connections); $on1SCycleEvent->raise(); $time = time(); } } }
/** * Returns a \System\Collection\Vector containing all the information about all the currently loaded * modules. This information is using a default format and displays any information from the iModule interface * and outputs additional information retrieval function. * @return \System\Collection\Vector A Vector containing a listing of all loaded modules */ public static final function getAllModules() { $register = self::getRegistryModuleEntry(); $map = new \System\Collection\Vector(); foreach ($register->modules as $moduleName => $module) { $mod = new \System\Collection\Map(); $mod->name = $module->getModuleName(); $mod->manifest = $moduleName; $mod->major = $module->getMajor(); $mod->minor = $module->getMinor(); $mod->revision = \System\Version::transformRevStringToInt($module->getSourceRevision()); $additional = $module->getModuleInformation(); $additional->requiredConfigDirectives = implode(', ', $module->getRequiredConfigDirectives()->getArrayCopy()); $mod->additional = $additional; $map->add($mod); } return $map; }
/** * Outputs the systeminfo in a human readable format. * This function outputs html styled information and should only be used for displaying information. * @return string The html styled system information */ public static final function getSystemInfo() { $output = ''; $output .= '<table style="margin: 10px; font-family: Verdana; font-size: 12px; width: 600px; border: 1px solid black; background-color: #9999cc;"> <tr><td colspan="2"> <p style="font-size: 14px; font-weight: bold;">SYSTEM INFORMATION</p> <p style="font-size: 10px;"> Notice: This file is copyrighted and unauthorized use is strictly prohibited.<br /> The file contains proprietary information and may not be distributed, modified<br /> or altered in any way, without written perimission.<br /> Copyright: SUPERHOLDER B.V. ' . date('Y') . ' </p> </td></tr> </table>'; $info = new \System\Collection\Vector(); $system = new \System\Collection\Map(); $system->name = 'SYSTEM Namespace'; $system->manifest = 'N/A'; $system->major = self::getMajor(); $system->minor = self::getMinor(); $system->revision = self::getSourceRevision(); $map = new \System\Collection\Map(); $map->PHP = self::getPHPVersion(); $map->hasSlowQueryListener = \System\Event\EventHandler::hasListeners('\\System\\Event\\Event\\OnSlowMySQLQueryEvent') ? 'true' : 'false'; if (self::$configDirectives == null) { self::$configDirectives = new \System\Collection\Vector(); } $map->requiredConfigDirectives = implode(', ', self::$configDirectives->getArrayCopy()); $map->PATH_PROJECT = PATH_PROJECT; $map->PATH_SYSTEM = PATH_SYSTEM; $map->PATH_CONFIG = PATH_CONFIG; $map->PATH_TEMP = PATH_TEMP; $map->PATH_LOGS = PATH_LOGS; $map->PATH_MODULES = PATH_MODULES; $map->installedCaches = 'LUTCache, Memcache, APCCache'; $system->additional = $map; $info[] = $system; $info->combine(\System\Module\Module::getAllModules()); foreach ($info as $module) { $output .= '<table style="margin: 10px; font-family: Verdana; font-size: 12px; width: 600px; border: 1px solid black; background-color: #9999cc;">'; $output .= '<tr><td colspan="2" style="text-align: center; font-weight: bold; font-size: 14px;">' . $module->name . '</td></tr>'; $output .= '<tr><td style="background-color: #ccccff; width: 200px;">Manifest</td><td style="background-color: #cccccc; width: 400px;">' . $module->manifest . '</td></tr>'; $output .= '<tr><td style="background-color: #ccccff; width: 200px;">Version</td><td style="background-color: #cccccc; width: 400px;">' . $module->major . "." . $module->minor . "." . $module->revision . '</td></tr>'; foreach ($module->additional as $index => $value) { $output .= '<tr><td style="background-color: #ccccff; width: 200px;">' . $index . '</td><td style="background-color: #cccccc; width: 400px;">' . $value . '</td></tr>'; } $output .= '</table>'; } return $output; }
/** * Cleans the current file cache by deleting unused files. * @param \System\Db\Database The database to LUT query */ public static final function cleanPageCache(\System\Db\Database $db) { $results = \System\Cache\LUTCache\LUTCache::getCache($db); $baseFiles = new \System\Collection\Vector(); foreach ($results as $result) { $baseFiles[] = basename($result->value); } $folder = new \System\IO\Directory(\System\Cache\PageCache\StaticBlock::CACHE_CACHEFOLDER); $extensions = new \System\Collection\Vector('xml'); $files = $folder->getFiles($extensions); foreach ($files as $file) { /** @var \System\IO\File */ $file = $file; if (mb_strpos($file->getFilename(), 'PageCache') !== false) { if (!$baseFiles->contains($file->getFilename())) { $file->delete(); } } } }
/** * Executes a query on the database system and tries to return it as a vector * The result will be converted to a \System\Collection\Vector. * The first field will be added as the value. * If the number of fields retrieved from the query does not equal 1 an exception will be thrown. * @param Query The query to be executed * @return \System\Collection\Vector A Vector */ public final function queryScalar(\System\Db\Query $query) { $results = $this->query($query); $vec = new \System\Collection\Vector(); if (count($results->getFields()) == 1) { $fields = $results->getFields(); foreach ($results as $result) { $value = $fields[0]->name; $vec->add($result->{$value}); } } else { throw new \System\Error\Exception\DatabaseQueryException('Given query should have 1 field but has: ' . count($results->getFields())); } return $vec; }