diff --git a/CLAUDE.md b/CLAUDE.md
index ee1e915..f7778f3 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -161,6 +161,7 @@ tests/
## Important Rules
- **No `classes.php`** — this is a standalone extension; the PSR-4 autoloader handles class discovery. Do not create a `classes.php`.
+- **`composer.json` `extra.prado`** (Prado 4.4) declares `bootstrap`, `error-messages` (`src/Data/SqlMap/DataMapper/messages.txt`), and `class-map` (`config/classes.json`, short name → FQCN for XML `class="TSqlMapConfig"` style references). Keep the legacy top-level `extra.bootstrap` for Prado 4.3. Add new classes to `config/classes.json`.
- **`if` statements** always use a block (`{}`), never a single-line body.
- **Backward compatibility** — all changes must be backward compatible for point releases.
- **`@since` tag** — use the next release version when adding new methods or classes; omit the method tag when it matches the class tag. Check prado's `CLAUDE.md` for the current next-release version number.
diff --git a/composer.json b/composer.json
index 3c850b5..5f2de5e 100644
--- a/composer.json
+++ b/composer.json
@@ -76,6 +76,11 @@
]
},
"extra": {
- "bootstrap": "Prado\\Data\\SqlMap\\TSqlMapConfig"
+ "bootstrap": "Prado\\Data\\SqlMap\\TSqlMapConfig",
+ "prado": {
+ "bootstrap": "Prado\\Data\\SqlMap\\TSqlMapConfig",
+ "error-messages": "src/Data/SqlMap/DataMapper/messages.txt",
+ "class-map": "config/classes.json"
+ }
}
}
diff --git a/config/classes.json b/config/classes.json
new file mode 100644
index 0000000..e98a457
--- /dev/null
+++ b/config/classes.json
@@ -0,0 +1,57 @@
+{
+ "TDiscriminator": "Prado\\Data\\SqlMap\\Configuration\\TDiscriminator",
+ "TInlineParameterMapParser": "Prado\\Data\\SqlMap\\Configuration\\TInlineParameterMapParser",
+ "TParameterMap": "Prado\\Data\\SqlMap\\Configuration\\TParameterMap",
+ "TParameterProperty": "Prado\\Data\\SqlMap\\Configuration\\TParameterProperty",
+ "TResultMap": "Prado\\Data\\SqlMap\\Configuration\\TResultMap",
+ "TResultProperty": "Prado\\Data\\SqlMap\\Configuration\\TResultProperty",
+ "TSimpleDynamicParser": "Prado\\Data\\SqlMap\\Configuration\\TSimpleDynamicParser",
+ "TSqlMapCacheKey": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapCacheKey",
+ "TSqlMapCacheModel": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapCacheModel",
+ "TSqlMapCacheTypes": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapCacheTypes",
+ "TSqlMapDelete": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapDelete",
+ "TSqlMapInsert": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapInsert",
+ "TSqlMapSelect": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapSelect",
+ "TSqlMapSelectKey": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapSelectKey",
+ "TSqlMapStatement": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapStatement",
+ "TSqlMapUpdate": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapUpdate",
+ "TSqlMapXmlConfigBuilder": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapXmlConfigBuilder",
+ "TSqlMapXmlConfiguration": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapXmlConfiguration",
+ "TSqlMapXmlMappingConfiguration": "Prado\\Data\\SqlMap\\Configuration\\TSqlMapXmlMappingConfiguration",
+ "TSubMap": "Prado\\Data\\SqlMap\\Configuration\\TSubMap",
+ "TInvalidPropertyException": "Prado\\Data\\SqlMap\\DataMapper\\TInvalidPropertyException",
+ "TLazyLoadList": "Prado\\Data\\SqlMap\\DataMapper\\TLazyLoadList",
+ "TObjectProxy": "Prado\\Data\\SqlMap\\DataMapper\\TObjectProxy",
+ "TPropertyAccess": "Prado\\Data\\SqlMap\\DataMapper\\TPropertyAccess",
+ "TSqlMapApplicationCache": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapApplicationCache",
+ "TSqlMapCache": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapCache",
+ "TSqlMapConfigurationException": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapConfigurationException",
+ "TSqlMapDuplicateException": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapDuplicateException",
+ "TSqlMapException": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapException",
+ "TSqlMapExecutionException": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapExecutionException",
+ "TSqlMapFifoCache": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapFifoCache",
+ "TSqlMapLruCache": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapLruCache",
+ "TSqlMapPagedList": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapPagedList",
+ "TSqlMapTypeHandler": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapTypeHandler",
+ "TSqlMapTypeHandlerRegistry": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapTypeHandlerRegistry",
+ "TSqlMapUndefinedException": "Prado\\Data\\SqlMap\\DataMapper\\TSqlMapUndefinedException",
+ "IMappedStatement": "Prado\\Data\\SqlMap\\Statements\\IMappedStatement",
+ "TCachingStatement": "Prado\\Data\\SqlMap\\Statements\\TCachingStatement",
+ "TDeleteMappedStatement": "Prado\\Data\\SqlMap\\Statements\\TDeleteMappedStatement",
+ "TInsertMappedStatement": "Prado\\Data\\SqlMap\\Statements\\TInsertMappedStatement",
+ "TMappedStatement": "Prado\\Data\\SqlMap\\Statements\\TMappedStatement",
+ "TPostSelectBinding": "Prado\\Data\\SqlMap\\Statements\\TPostSelectBinding",
+ "TPreparedCommand": "Prado\\Data\\SqlMap\\Statements\\TPreparedCommand",
+ "TPreparedStatement": "Prado\\Data\\SqlMap\\Statements\\TPreparedStatement",
+ "TPreparedStatementFactory": "Prado\\Data\\SqlMap\\Statements\\TPreparedStatementFactory",
+ "TResultSetListItemParameter": "Prado\\Data\\SqlMap\\Statements\\TResultSetListItemParameter",
+ "TResultSetMapItemParameter": "Prado\\Data\\SqlMap\\Statements\\TResultSetMapItemParameter",
+ "TSelectMappedStatement": "Prado\\Data\\SqlMap\\Statements\\TSelectMappedStatement",
+ "TSimpleDynamicSql": "Prado\\Data\\SqlMap\\Statements\\TSimpleDynamicSql",
+ "TSqlMapObjectCollectionTree": "Prado\\Data\\SqlMap\\Statements\\TSqlMapObjectCollectionTree",
+ "TStaticSql": "Prado\\Data\\SqlMap\\Statements\\TStaticSql",
+ "TUpdateMappedStatement": "Prado\\Data\\SqlMap\\Statements\\TUpdateMappedStatement",
+ "TSqlMapConfig": "Prado\\Data\\SqlMap\\TSqlMapConfig",
+ "TSqlMapGateway": "Prado\\Data\\SqlMap\\TSqlMapGateway",
+ "TSqlMapManager": "Prado\\Data\\SqlMap\\TSqlMapManager"
+}
diff --git a/src/Data/SqlMap/Configuration/TParameterMap.php b/src/Data/SqlMap/Configuration/TParameterMap.php
index e3ec801..63264b1 100644
--- a/src/Data/SqlMap/Configuration/TParameterMap.php
+++ b/src/Data/SqlMap/Configuration/TParameterMap.php
@@ -40,7 +40,6 @@ class TParameterMap extends \Prado\TComponent
private $_extend;
private $_properties;
private $_propertyMap;
- private $_extendMap;
private $_ID;
/**
diff --git a/src/Data/SqlMap/Configuration/TResultMap.php b/src/Data/SqlMap/Configuration/TResultMap.php
index 1e9471e..188e011 100644
--- a/src/Data/SqlMap/Configuration/TResultMap.php
+++ b/src/Data/SqlMap/Configuration/TResultMap.php
@@ -44,7 +44,6 @@ class TResultMap extends \Prado\TComponent
private $_extends;
private $_groupBy;
private $_discriminator;
- private $_typeHandlers;
private $_ID;
/**
@@ -162,17 +161,18 @@ public function addResultProperty(TResultProperty $property)
public function createInstanceOfResult($registry)
{
$handler = $registry->getTypeHandler($this->getClass());
+ $handlerClass = $handler !== null ? $handler::class : 'null';
try {
if ($handler !== null) {
return $handler->createNewInstance();
} else {
return $registry->createInstanceOf($this->getClass());
}
- } catch (TSqlMapException $e) {
+ } catch (TSqlMapException) {
throw new TSqlMapException(
'sqlmap_unable_to_create_new_instance',
$this->getClass(),
- $handler ? $handler::class : 'null',
+ $handlerClass,
$this->getID()
);
}
diff --git a/src/Data/SqlMap/Configuration/TResultProperty.php b/src/Data/SqlMap/Configuration/TResultProperty.php
index 18d8447..3cb690f 100644
--- a/src/Data/SqlMap/Configuration/TResultProperty.php
+++ b/src/Data/SqlMap/Configuration/TResultProperty.php
@@ -50,20 +50,18 @@ class TResultProperty extends \Prado\TComponent
private $_isLazyLoad = false;
private $_select;
- private $_hostResultMapID = 'inplicit internal mapping';
-
public const LIST_TYPE = 0;
public const ARRAY_TYPE = 1;
/**
- * Gets the containing result map ID.
- * @param TResultMap $resultMap containing result map.
+ * Initializes a result property.
+ *
+ * The optional result map parameter is retained for backward compatibility.
+ * @param ?TResultMap $resultMap legacy containing result map.
+ * @phpstan-ignore constructor.unusedParameter (kept for callers that pass the containing result map)
*/
public function __construct($resultMap = null)
{
- if ($resultMap instanceof TResultMap) {
- $this->_hostResultMapID = $resultMap->getID();
- }
parent::__construct();
}
diff --git a/src/Data/SqlMap/Configuration/TSqlMapCacheModel.php b/src/Data/SqlMap/Configuration/TSqlMapCacheModel.php
index f3325a1..2d6a487 100644
--- a/src/Data/SqlMap/Configuration/TSqlMapCacheModel.php
+++ b/src/Data/SqlMap/Configuration/TSqlMapCacheModel.php
@@ -40,7 +40,6 @@ class TSqlMapCacheModel extends \Prado\TComponent
private $_requests = 0;
private $_id;
private $_implementation = TSqlMapCacheTypes::Basic;
- private $_properties = [];
private $_flushInterval = 0;
private static $_cacheTypes = [];
diff --git a/src/Data/SqlMap/Configuration/TSqlMapStatement.php b/src/Data/SqlMap/Configuration/TSqlMapStatement.php
index c97111c..ef193bb 100644
--- a/src/Data/SqlMap/Configuration/TSqlMapStatement.php
+++ b/src/Data/SqlMap/Configuration/TSqlMapStatement.php
@@ -41,7 +41,6 @@ class TSqlMapStatement extends \Prado\TComponent
private $_cacheModelName;
private $_SQL;
private $_listClass;
- private $_typeHandler;
private $_extendStatement;
private $_cache;
private $_ID;
@@ -332,9 +331,6 @@ public function __sleep()
if (!$this->_listClass) {
$exprops[] = "\0$cn\0_listClass";
}
- if (!$this->_typeHandler) {
- $exprops[] = "\0$cn\0_typeHandler";
- }
if (!$this->_extendStatement) {
$exprops[] = "\0$cn\0_extendStatement";
}
diff --git a/src/Data/SqlMap/DataMapper/TLazyLoadList.php b/src/Data/SqlMap/DataMapper/TLazyLoadList.php
index 741b67c..bad8c8c 100644
--- a/src/Data/SqlMap/DataMapper/TLazyLoadList.php
+++ b/src/Data/SqlMap/DataMapper/TLazyLoadList.php
@@ -80,7 +80,7 @@ public function intercept($method, $arguments)
*/
protected function fetchListData()
{
- if ($this->_loaded == false) {
+ if (!$this->_loaded) {
$this->_innerList = $this->_statement->executeQueryForList($this->_connection, $this->_param);
$this->_loaded = true;
//replace the target property with real list
diff --git a/src/Data/SqlMap/DataMapper/TSqlMapException.php b/src/Data/SqlMap/DataMapper/TSqlMapException.php
index 986a467..11f23a6 100644
--- a/src/Data/SqlMap/DataMapper/TSqlMapException.php
+++ b/src/Data/SqlMap/DataMapper/TSqlMapException.php
@@ -4,7 +4,6 @@
use Prado\Exceptions\TException;
use Prado\Prado;
-use Prado\TPropertyValue;
use SimpleXMLElement;
/**
@@ -16,27 +15,32 @@
class TSqlMapException extends TException
{
/**
- * Constructor, similar to the parent constructor. For parameters that
- * are of SimpleXmlElement, the tag name and its attribute names and values
- * are expanded into a string.
- * @param mixed $errorMessage
+ * Constructor. The arguments follow {@see \Prado\Exceptions\TException::__construct()}.
+ * - `new TSqlMapException('message_code', $param0, ...)` → error code 0.
+ * - `new TSqlMapException($errorCode, 'message_code', $param0, ...)` → integer error code.
+ * - A trailing {@see \Throwable} argument is the previous exception in the chain.
+ * - A {@see \SimpleXMLElement} parameter expands to its tag name with attribute names and values.
+ * @param int|string $errorCode the integer error code, or the message code in the old style.
+ * @param mixed $errorMessage the message code when $errorCode is an integer, otherwise
+ * the first message parameter.
+ * @param mixed ...$args the remaining message parameters, optionally followed by the
+ * previous exception.
*/
- public function __construct($errorMessage)
+ public function __construct($errorCode, $errorMessage = null, ...$args)
{
- $this->setErrorCode($errorMessage);
- $errorMessage = $this->translateErrorMessage($errorMessage);
- $args = func_get_args();
- array_shift($args);
- $n = count($args);
- $tokens = [];
- for ($i = 0; $i < $n; ++$i) {
- if ($args[$i] instanceof SimpleXMLElement) {
- $tokens['{' . $i . '}'] = $this->implodeNode($args[$i]);
- } else {
- $tokens['{' . $i . '}'] = TPropertyValue::ensureString($args[$i]);
+ if (!is_int($errorCode)) {
+ if (func_num_args() > 1) {
+ array_unshift($args, $errorMessage);
}
+ $errorMessage = $errorCode;
+ $errorCode = 0;
}
- parent::__construct(strtr($errorMessage, $tokens));
+ foreach ($args as $i => $arg) {
+ if ($arg instanceof SimpleXMLElement) {
+ $args[$i] = $this->implodeNode($arg);
+ }
+ }
+ parent::__construct($errorCode, $errorMessage, ...$args);
}
/**
diff --git a/src/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php b/src/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php
index ba89a75..0403490 100644
--- a/src/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php
+++ b/src/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php
@@ -38,12 +38,12 @@ public function getDbTypeHandler($dbType = 'NULL')
}
/**
- * @param string $class type handler class name
- * @return null|TSqlMapTypeHandler type handler
+ * @param ?string $class type handler class name
+ * @return null|TSqlMapTypeHandler type handler, null when $class is null or unregistered
*/
public function getTypeHandler($class)
{
- if (isset($this->_typeHandlers[$class])) {
+ if ($class !== null && isset($this->_typeHandlers[$class])) {
return $this->_typeHandlers[$class];
}
return null;
diff --git a/src/Data/SqlMap/DataMapper/messages.txt b/src/Data/SqlMap/DataMapper/messages.txt
index 0923d60..ad7cb9c 100644
--- a/src/Data/SqlMap/DataMapper/messages.txt
+++ b/src/Data/SqlMap/DataMapper/messages.txt
@@ -63,4 +63,9 @@ sqlmap_query_execution_error = Error in executing SQLMap statement '{0}' : '{1
sqlmap_invalid_delegate = Invalid callback row delegate '{1}' in mapped statement '{0}'.
sqlmap_invalid_prado_cache = Unable to find Prado cache module for SQLMap cache '{0}'.
-sqlmap_non_groupby_array_list_type = Expecting GroupBy property in result map '{0}' since {1}::{2} is an array or TList type.
\ No newline at end of file
+sqlmap_non_groupby_array_list_type = Expecting GroupBy property in result map '{0}' since {1}::{2} is an array or TList type.
+sqlmap_can_not_extend_select_key = SelectKey statements do not support inheritance via the 'extends' attribute.
+sqlmap_configfile_invalid = SQLMap configuration file or namespace '{0}' is invalid or does not exist.
+sqlmap_must_enable_custom_paging = TSqlMapPagedList always uses custom paging; CustomPaging cannot be changed.
+sqlmap_property_must_be_list = A grouped result property must be an array or TList to hold child objects.
+sqlmap_use_set_to_store_cache = Use set() to store items in the SQLMap cache; add() is not supported.
diff --git a/src/Data/SqlMap/Statements/TMappedStatement.php b/src/Data/SqlMap/Statements/TMappedStatement.php
index 0a4e8cf..604d59f 100644
--- a/src/Data/SqlMap/Statements/TMappedStatement.php
+++ b/src/Data/SqlMap/Statements/TMappedStatement.php
@@ -295,9 +295,9 @@ protected function raiseRowDelegate($handler, $param)
{
if ($handler instanceof \Closure) {
$handler($this, $param);
- } elseif (is_string($handler)) {
+ } elseif (is_string($handler) || is_object($handler) && is_callable($handler)) {
call_user_func($handler, $this, $param);
- } elseif (is_callable($handler, true)) {
+ } elseif (is_array($handler) && is_callable($handler, true)) {
// an array: 0 - object, 1 - method name/path
[$object, $method] = $handler;
if (is_string($object)) { // static method call
@@ -423,7 +423,7 @@ protected function getPostGeneratedSelectKey($connection, $parameter)
* @param \Prado\Data\TDbConnection $connection database connection
* @param mixed $parameter insert statement parameter
* @param TSqlMapSelectKey $selectKey select key statement
- * @return string last insert ID.
+ * @return mixed last insert ID.
*/
protected function executeSelectKey($connection, $parameter, $selectKey)
{
@@ -498,7 +498,7 @@ public function onExecuteQuery($sql)
* pages through a ROW_NUMBER() subquery, and its outer "SELECT *" returns that helper column.
* @param array $row a result set row retrieved from the database
* @param null|object $resultObject the result object, will create if necessary.
- * @return object the result filled with data, null if not filled.
+ * @return ?object the result filled with data, null if not filled.
*/
protected function applyResultMap($row, &$resultObject = null)
{
@@ -805,6 +805,7 @@ protected function getScalarResult($result, $type)
* @param TResultProperty $property the result property to fill.
* @param array $row a result set row retrieved from the database
* @param object $resultObject the result object
+ * @phpstan-impure
*/
protected function setObjectProperty($resultMap, $property, $row, &$resultObject)
{
@@ -835,7 +836,7 @@ protected function setObjectProperty($resultMap, $property, $row, &$resultObject
}
} else {
$obj = $nested->createInstanceOfResult($this->getManager()->getTypeHandlers());
- if ($this->fillPropertyWithResultMap($nested, $row, $obj) == false) {
+ if (!$this->fillPropertyWithResultMap($nested, $row, $obj)) {
$obj = null;
}
TPropertyAccess::set($resultObject, $key, $obj);
@@ -935,7 +936,9 @@ protected function fillPropertyWithResultMap($resultMap, $row, &$resultObject)
foreach ($resultMap->getColumns() as $property) {
$this->_IsRowDataFound = false;
$this->setObjectProperty($resultMap, $property, $row, $resultObject);
- $dataFound = $dataFound || $this->_IsRowDataFound;
+ if ($this->_IsRowDataFound) {
+ $dataFound = true;
+ }
}
$this->_IsRowDataFound = $dataFound;
return $dataFound;
diff --git a/src/Data/SqlMap/Statements/TPreparedStatementFactory.php b/src/Data/SqlMap/Statements/TPreparedStatementFactory.php
index af9b4f0..3a4fc1d 100644
--- a/src/Data/SqlMap/Statements/TPreparedStatementFactory.php
+++ b/src/Data/SqlMap/Statements/TPreparedStatementFactory.php
@@ -20,7 +20,6 @@ class TPreparedStatementFactory
{
private $_statement;
private $_preparedStatement;
- private $_parameterPrefix = 'param';
private $_commandText;
public function __construct($statement, $sqlString)
diff --git a/src/Data/SqlMap/Statements/TSqlMapObjectCollectionTree.php b/src/Data/SqlMap/Statements/TSqlMapObjectCollectionTree.php
index a621081..3d7cdcb 100644
--- a/src/Data/SqlMap/Statements/TSqlMapObjectCollectionTree.php
+++ b/src/Data/SqlMap/Statements/TSqlMapObjectCollectionTree.php
@@ -49,14 +49,13 @@ public function isEmpty()
/**
* Add a new node to the object tree graph.
- * @param string $parent parent node id
+ * @param ?string $parent parent node id, null for a root node
* @param string $node new node id
* @param mixed $object node value
*/
public function add($parent, $node, $object = '')
{
- if (isset($this->_entries[$parent]) && ($this->_entries[$parent] !== null)
- && isset($this->_entries[$node]) && ($this->_entries[$node] !== null)) {
+ if ($parent !== null && isset($this->_entries[$parent]) && isset($this->_entries[$node])) {
$this->_entries[$node] = $object;
return;
}
@@ -87,11 +86,8 @@ public function add($parent, $node, $object = '')
protected function addNode(&$childs, $parent, $node)
{
$found = false;
- reset($childs);
- for ($i = 0, $k = count($childs); $i < $k; $i++) {
- $key = key($childs);
- next($childs);
- if ($key == $parent) {
+ foreach (array_keys($childs) as $key) {
+ if ((string) $key === (string) $parent) {
$found = true;
$childs[$key][$node] = [];
} else {
@@ -136,8 +132,7 @@ protected function collectChildren($parent, &$nodes)
{
$noChildren = !$this->hasChildren($nodes);
$childs = [];
- for (reset($nodes); $key = key($nodes);) {
- next($nodes);
+ foreach (array_keys($nodes) as $key) {
if ($noChildren) {
$childs[] = $key;
unset($nodes[$key]);
diff --git a/src/Data/SqlMap/TSqlMapManager.php b/src/Data/SqlMap/TSqlMapManager.php
index 91fe8a9..84cd621 100644
--- a/src/Data/SqlMap/TSqlMapManager.php
+++ b/src/Data/SqlMap/TSqlMapManager.php
@@ -155,7 +155,7 @@ public function getMappedStatements()
*/
public function getMappedStatement($name)
{
- if ($this->_mappedStatements->contains($name) == false) {
+ if (!$this->_mappedStatements->contains($name)) {
throw new TSqlMapUndefinedException('sqlmap_contains_no_statement', $name);
}
return $this->_mappedStatements[$name];
@@ -169,7 +169,7 @@ public function getMappedStatement($name)
public function addMappedStatement(IMappedStatement $statement)
{
$key = $statement->getID();
- if ($this->_mappedStatements->contains($key) == true) {
+ if ($this->_mappedStatements->contains($key)) {
throw new TSqlMapDuplicateException('sqlmap_already_contains_statement', $key);
}
$this->_mappedStatements->add($key, $statement);
@@ -191,7 +191,7 @@ public function getResultMaps()
*/
public function getResultMap($name)
{
- if ($this->_resultMaps->contains($name) == false) {
+ if (!$this->_resultMaps->contains($name)) {
throw new TSqlMapUndefinedException('sqlmap_contains_no_result_map', $name);
}
return $this->_resultMaps[$name];
@@ -204,7 +204,7 @@ public function getResultMap($name)
public function addResultMap(TResultMap $result)
{
$key = $result->getID();
- if ($this->_resultMaps->contains($key) == true) {
+ if ($this->_resultMaps->contains($key)) {
throw new TSqlMapDuplicateException('sqlmap_already_contains_result_map', $key);
}
$this->_resultMaps->add($key, $result);
@@ -225,7 +225,7 @@ public function getParameterMaps()
*/
public function getParameterMap($name)
{
- if ($this->_parameterMaps->contains($name) == false) {
+ if (!$this->_parameterMaps->contains($name)) {
throw new TSqlMapUndefinedException('sqlmap_contains_no_parameter_map', $name);
}
return $this->_parameterMaps[$name];
@@ -238,7 +238,7 @@ public function getParameterMap($name)
public function addParameterMap(TParameterMap $parameter)
{
$key = $parameter->getID();
- if ($this->_parameterMaps->contains($key) == true) {
+ if ($this->_parameterMaps->contains($key)) {
throw new TSqlMapDuplicateException('sqlmap_already_contains_parameter_map', $key);
}
$this->_parameterMaps->add($key, $parameter);
diff --git a/tests/test_tools/phpunit_bootstrap.php b/tests/test_tools/phpunit_bootstrap.php
index 714c89f..07238c4 100644
--- a/tests/test_tools/phpunit_bootstrap.php
+++ b/tests/test_tools/phpunit_bootstrap.php
@@ -4,3 +4,10 @@
require_once(__DIR__ . '/../../vendor/pradosoft/prado/framework/Prado.php');
$application = new \Prado\Test\Unit\Harness\TTestApplication();
+
+// Prado applies extra.prado class maps and message files only for installed packages.
+// The extension under test is the root package, so they are registered here.
+if (method_exists(\Prado\Prado::class, 'registerClassMap')) {
+ \Prado\Prado::registerClassMap(json_decode(file_get_contents(__DIR__ . '/../../config/classes.json'), true));
+}
+\Prado\Exceptions\TException::addMessageFile(__DIR__ . '/../../src/Data/SqlMap/DataMapper/messages.txt');
diff --git a/tests/unit/Data/SqlMap/DataMapper/TSqlMapExceptionTest.php b/tests/unit/Data/SqlMap/DataMapper/TSqlMapExceptionTest.php
new file mode 100644
index 0000000..b074767
--- /dev/null
+++ b/tests/unit/Data/SqlMap/DataMapper/TSqlMapExceptionTest.php
@@ -0,0 +1,72 @@
+assertSame("Unable to find SQLMap statement 'findUser'.", $e->getMessage());
+ $this->assertSame(0, $e->getCode());
+ $this->assertSame('sqlmap_contains_no_statement', $e->getErrorCode());
+ $this->assertNull($e->getPrevious());
+ }
+
+ public function testOldStyleWithoutParameters()
+ {
+ $e = new TSqlMapException('sqlmap_use_set_to_store_cache');
+ $this->assertSame('Use set() to store items in the SQLMap cache; add() is not supported.', $e->getMessage());
+ }
+
+ public function testOldStyleKeepsExplicitNullParameter()
+ {
+ $e = new TSqlMapException('sqlmap_unable_to_create_new_instance', null, 'Handler', 'stmt');
+ $this->assertSame("Unable to create a new instance of '' using type hander 'Handler' for SQLMap statement with ID 'stmt'.", $e->getMessage());
+ }
+
+ public function testIntegerErrorCode()
+ {
+ $e = new TSqlMapException(42, 'sqlmap_contains_no_result_map', 'Account');
+ $this->assertSame("Unable to find SQLMap result map 'Account'.", $e->getMessage());
+ $this->assertSame(42, $e->getCode());
+ $this->assertSame('sqlmap_contains_no_result_map', $e->getErrorCode());
+ }
+
+ public function testTrailingThrowableIsPrevious()
+ {
+ $previous = new RuntimeException('inner');
+ $e = new TSqlMapException('sqlmap_contains_no_statement', 'findUser', $previous);
+ $this->assertSame($previous, $e->getPrevious());
+ $this->assertSame("Unable to find SQLMap statement 'findUser'.", $e->getMessage());
+
+ $e = new TSqlMapException(7, 'sqlmap_contains_no_statement', 'findUser', $previous);
+ $this->assertSame($previous, $e->getPrevious());
+ $this->assertSame(7, $e->getCode());
+ }
+
+ public function testSimpleXmlElementParameterExpands()
+ {
+ $node = new SimpleXMLElement('');
+ $e = new TSqlMapConfigurationException('sqlmap_undefined_attribute', 'select', 'foo', $node, 'file.xml');
+ $this->assertSame(
+ "select attribute 'foo' is not defined for