protected function _processItem($itemRaw) { $index = serialize($itemRaw); if (null === ($model = $this->_modelList[$index])) { throw new CM_Exception_Nonexistent('Model itemRaw: `' . CM_Util::var_line($itemRaw) . '` has no data'); } return $model; }
/** * @param string $key * @param mixed $value * @return mixed * @throws CM_Exception_Invalid * @throws CM_Model_Exception_Validation */ public function encodeField($key, $value) { $key = (string) $key; if ($this->hasField($key)) { $schemaField = $this->_schema[$key]; if (null !== $value) { $type = isset($schemaField['type']) ? $schemaField['type'] : null; if (null !== $type) { switch ($type) { case 'integer': case 'int': $value = (int) $value; break; case 'float': $value = (double) $value; break; case 'string': break; case 'boolean': case 'bool': $value = (bool) $value; break; case 'array': break; case 'DateTime': /** @var DateTime $value */ $value = $value->getTimestamp(); break; default: if (!(class_exists($type) && is_subclass_of($type, 'CM_Model_Abstract'))) { throw new CM_Model_Exception_Validation('Field `' . $key . '` is not a valid model'); } if (!$value instanceof $type) { throw new CM_Model_Exception_Validation('Value `' . CM_Util::var_line($value) . '` is not an instance of `' . $type . '`'); } /** @var CM_Model_Abstract $value */ $id = $value->getIdRaw(); if (count($id) == 1) { $value = $value->getId(); } else { $value = CM_Params::jsonEncode($id); } } } } } return $value; }
/** * @param string[]|null $variables * @throws CM_Exception_Invalid */ public function setVariables(array $variables = null) { $previousVariables = $this->getVariables(); $variables = (array) $variables; $variables = array_values($variables); sort($variables); if ($previousVariables !== $variables) { $variablesEncoded = CM_Params::jsonEncode($variables); $this->_set('variables', $variablesEncoded); $this->_increaseUpdateCount(); if ($this->_getUpdateCount() > self::MAX_UPDATE_COUNT) { $message = ['Variables for languageKey `' . $this->getName() . '` have been updated over ' . self::MAX_UPDATE_COUNT . ' times since release.', 'Previous variables: `' . CM_Util::var_line($previousVariables) . '`', 'Current variables: `' . CM_Util::var_line($variables) . '`']; throw new CM_Exception_Invalid(join(PHP_EOL, $message)); } } }
/** * @param array $idTypeList [['type' => int, 'id' => int|array],...] | [int|array,...] Pass an array of ids if $modelType is used * @param int|null $modelType * @return CM_Model_Abstract[] Can contain null-entries when model doesn't exist * @throws CM_Exception_Invalid */ public static function factoryGenericMultiple(array $idTypeList, $modelType = null) { $modelType = null !== $modelType ? (int) $modelType : null; $modelList = array(); $idTypeMap = array(); $serializedKeyMap = array(); $storageTypeList = array('cache' => array(), 'persistence' => array()); $noPersistenceList = array(); foreach ($idTypeList as $originalKey => $idType) { if (null === $modelType) { if (!is_array($idType)) { throw new CM_Exception_Invalid('`idType` should be an array if `modelType` is not defined', null, ['idType' => CM_Util::var_line($idType)]); } $type = (int) $idType['type']; $id = $idType['id']; } else { $type = $modelType; $id = $idType; } if (!is_array($id)) { $id = array('id' => $id); } $id = self::_castIdRaw($id); $idType = array('type' => $type, 'id' => $id); $serializedKey = serialize($idType); $serializedKeyMap[$originalKey] = $serializedKey; $modelList[$serializedKey] = null; $idTypeMap[$serializedKey] = $idType; /** @var CM_Model_Abstract $modelClass */ $modelClass = CM_Model_Abstract::_getClassName($type); if ($cacheStorageClass = $modelClass::getCacheClass()) { $storageTypeList['cache'][$cacheStorageClass][$serializedKey] = $idType; } if ($persistenceStorageClass = $modelClass::getPersistenceClass()) { $storageTypeList['persistence'][$persistenceStorageClass][$serializedKey] = $idType; } else { $noPersistenceList[$serializedKey] = $idType; } } foreach ($storageTypeList as $storageType => $adapterTypeList) { $searchItemList = array_filter($modelList, function ($value) { return null === $value; }); foreach ($adapterTypeList as $adapterClass => $adapterItemList) { /** @var CM_Model_StorageAdapter_AbstractAdapter $storageAdapter */ $storageAdapter = new $adapterClass(); $result = $storageAdapter->loadMultiple(array_intersect_key($adapterItemList, $searchItemList)); foreach ($result as $serializedKey => $modelData) { $model = null; if (null !== $modelData) { $dataFromPersistence = 'persistence' === $storageType; $model = self::factoryGeneric($idTypeMap[$serializedKey]['type'], $idTypeMap[$serializedKey]['id'], $modelData, $dataFromPersistence); } $modelList[$serializedKey] = $model; } } } // no persistence foreach ($noPersistenceList as $serializedKey => $idType) { if (!isset($modelList[$serializedKey])) { try { $model = self::factoryGeneric($idType['type'], $idType['id']); } catch (CM_Exception_Nonexistent $ex) { $model = null; } $modelList[$serializedKey] = $model; } } $resultList = array(); foreach ($serializedKeyMap as $originalKey => $serializedKey) { $resultList[] = $modelList[$serializedKeyMap[$originalKey]]; } return $resultList; }
/** * @param mixed $value * @param bool|null $prettyPrint * @throws CM_Exception_Invalid * @return string */ public static function jsonEncode($value, $prettyPrint = null) { $options = 0; if ($prettyPrint) { $options = $options | JSON_PRETTY_PRINT; } $value = json_encode($value, $options); if (json_last_error() > 0) { throw new CM_Exception_Invalid('Cannot json_encode value `' . CM_Util::var_line($value) . '`.'); } return $value; }
public function testEncode() { CM_Config::get()->CM_Model_Abstract->types[CM_Model_Mock_Validation::getTypeStatic()] = 'CM_Model_Mock_Validation'; CM_Config::get()->CM_Model_Abstract->types[CM_Model_Mock_Validation2::getTypeStatic()] = 'CM_Model_Mock_Validation2'; $testDataList = array(array('value' => 12, 'schema' => array(), 'returnValue' => 12), array('value' => null, 'schema' => array('optional' => true), 'returnValue' => null), array('value' => -12, 'schema' => array('type' => 'integer'), 'returnValue' => -12), array('value' => '-12', 'schema' => array('type' => 'integer'), 'returnValue' => -12), array('value' => 14, 'schema' => array('type' => 'int'), 'returnValue' => 14), array('value' => 'foo bar', 'schema' => array('type' => 'string'), 'returnValue' => 'foo bar'), array('value' => 'foo 繁體字 bar', 'schema' => array('type' => 'string'), 'returnValue' => 'foo 繁體字 bar'), array('value' => '', 'schema' => array('type' => 'string'), 'returnValue' => ''), array('value' => 123, 'schema' => array('type' => 'string'), 'returnValue' => '123'), array('value' => -12, 'schema' => array('type' => 'float'), 'returnValue' => -12.0), array('value' => '-123', 'schema' => array('type' => 'float'), 'returnValue' => -123.0), array('value' => 12.01, 'schema' => array('type' => 'float'), 'returnValue' => 12.01), array('value' => '12.01', 'schema' => array('type' => 'float'), 'returnValue' => 12.01), array('value' => true, 'schema' => array('type' => 'boolean'), 'returnValue' => true), array('value' => false, 'schema' => array('type' => 'boolean'), 'returnValue' => false), array('value' => '1', 'schema' => array('type' => 'boolean'), 'returnValue' => true), array('value' => '0', 'schema' => array('type' => 'boolean'), 'returnValue' => false), array('value' => true, 'schema' => array('type' => 'bool'), 'returnValue' => true), array('value' => array('foo' => 'bar'), 'schema' => array('type' => 'array'), 'returnValue' => array('foo' => 'bar')), array('value' => DateTime::createFromFormat('U', 1378904141), 'schema' => array('type' => 'DateTime'), 'returnValue' => 1378904141), array('value' => new CM_Model_Mock_Validation(2), 'schema' => array('type' => 'CM_Model_Mock_Validation'), 'returnValue' => 2), array('value' => new CM_Model_Mock_Validation(4, 'bar'), 'schema' => array('type' => 'CM_Model_Mock_Validation'), 'returnValue' => '{"id":"4","foo":"bar"}'), array('value' => new CM_Model_Mock_Validation2(2), 'schema' => array('type' => 'CM_Model_Mock_Validation2'), 'returnValue' => '2')); foreach ($testDataList as $testData) { $schema = new CM_Model_Schema_Definition(array('foo' => $testData['schema'])); $value = $schema->encodeField('foo', $testData['value']); if (is_object($testData['returnValue'])) { $this->assertEquals($testData['returnValue'], $value, 'Unexpected return value (' . CM_Util::var_line($testData) . ')'); } else { $this->assertSame($testData['returnValue'], $value, 'Unexpected return value (' . CM_Util::var_line($testData) . ')'); } } }
function smarty_modifier_varline($var) { return CM_Util::var_line($var); }
/** * @param string $key * @param mixed $value * @return mixed * @throws CM_Exception_Invalid * @throws CM_Model_Exception_Validation */ public function decodeField($key, $value) { $key = (string) $key; if ($this->hasField($key)) { $schemaField = $this->_schema[$key]; if (null !== $value) { $type = isset($schemaField['type']) ? $schemaField['type'] : null; if (null !== $type) { switch ($type) { case 'integer': case 'int': $value = (int) $value; break; case 'float': $value = (double) $value; break; case 'string': $value = (string) $value; break; case 'boolean': case 'bool': $value = (bool) $value; break; case 'array': break; case 'DateTime': $value = DateTime::createFromFormat('U', $value); break; default: if (!class_exists($type)) { throw new CM_Model_Exception_Validation('Field type is not a valid class/interface', null, ['type' => $type]); } $className = $type; if (is_a($className, 'CM_Model_Abstract', true)) { /** @var CM_Model_Abstract $type */ if ($this->_isJson($value)) { $value = CM_Util::jsonDecode($value); } $id = $value; if (!is_array($id)) { $id = ['id' => $id]; } $value = CM_Model_Abstract::factoryGeneric($type::getTypeStatic(), $id); } elseif (is_subclass_of($className, 'CM_ArrayConvertible', true)) { /** @var CM_ArrayConvertible $className */ $value = CM_Util::jsonDecode($value); $value = $className::fromArray($value); } else { throw new CM_Model_Exception_Validation('Class is neither CM_Model_Abstract nor CM_ArrayConvertible', null, ['className' => $className]); } if (!$value instanceof $className) { throw new CM_Model_Exception_Validation('Value is not an instance of the class', null, ['value' => CM_Util::var_line($value), 'className' => $className]); } } } } } return $value; }