Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
57 changes: 57 additions & 0 deletions config/classes.json
Original file line number Diff line number Diff line change
@@ -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"
}
1 change: 0 additions & 1 deletion src/Data/SqlMap/Configuration/TParameterMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class TParameterMap extends \Prado\TComponent
private $_extend;
private $_properties;
private $_propertyMap;
private $_extendMap;
private $_ID;

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Data/SqlMap/Configuration/TResultMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class TResultMap extends \Prado\TComponent
private $_extends;
private $_groupBy;
private $_discriminator;
private $_typeHandlers;
private $_ID;

/**
Expand Down Expand Up @@ -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()
);
}
Expand Down
12 changes: 5 additions & 7 deletions src/Data/SqlMap/Configuration/TResultProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
1 change: 0 additions & 1 deletion src/Data/SqlMap/Configuration/TSqlMapCacheModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand Down
4 changes: 0 additions & 4 deletions src/Data/SqlMap/Configuration/TSqlMapStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class TSqlMapStatement extends \Prado\TComponent
private $_cacheModelName;
private $_SQL;
private $_listClass;
private $_typeHandler;
private $_extendStatement;
private $_cache;
private $_ID;
Expand Down Expand Up @@ -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";
}
Expand Down
2 changes: 1 addition & 1 deletion src/Data/SqlMap/DataMapper/TLazyLoadList.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 22 additions & 18 deletions src/Data/SqlMap/DataMapper/TSqlMapException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Prado\Exceptions\TException;
use Prado\Prado;
use Prado\TPropertyValue;
use SimpleXMLElement;

/**
Expand All @@ -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);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion src/Data/SqlMap/DataMapper/messages.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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.
15 changes: 9 additions & 6 deletions src/Data/SqlMap/Statements/TMappedStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion src/Data/SqlMap/Statements/TPreparedStatementFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class TPreparedStatementFactory
{
private $_statement;
private $_preparedStatement;
private $_parameterPrefix = 'param';
private $_commandText;

public function __construct($statement, $sqlString)
Expand Down
15 changes: 5 additions & 10 deletions src/Data/SqlMap/Statements/TSqlMapObjectCollectionTree.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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]);
Expand Down
Loading
Loading