Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for DatabaseSource new binding parsing and select expressions #14

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
86 changes: 86 additions & 0 deletions src/Charcoal/Property/PropertyField.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@ class PropertyField
*/
private $extra;

/**
* @var \Closure
*/
private $sqlSelectExpression;

/**
* @var mixed
*/
private $val;

/**
* @var \Closure
*/
private $sqlPdoBindParamExpression;

/**
* @var mixed
*/
Expand Down Expand Up @@ -86,9 +96,15 @@ public function setData(array $data)
if (isset($data['extra'])) {
$this->setExtra($data['extra']);
}
if (isset($data['sqlSelectExpression'])) {
$this->setSqlSelectExpression($data['sqlSelectExpression']);
}
if (isset($data['val'])) {
$this->setVal($data['val']);
}
if (isset($data['sqlPdoBindParamExpression'])) {
$this->setSqlPdoBindParamExpression($data['sqlPdoBindParamExpression']);
}
if (isset($data['defaultVal'])) {
$this->setDefaultVal($data['defaultVal']);
}
Expand Down Expand Up @@ -247,6 +263,42 @@ public function sqlEncoding()
return $this->sqlEncoding;
}

/**
* Format the property's PDO select statement.
*
* This method can be overridden for custom select function parsing.
*
* This method allows a property to apply an SQL function to a property select statement:
*
* ```sql
* function ($select) {
* return 'ST_AsGeoJSON('.$select.')';
* }
* ```
*
* This method returns a closure to be called during the processing of fetching the object
* or collection in {@see \Charcoal\Source\DatabaseSource}.
*
* @return \Closure
*/
public function sqlSelectExpression()
{
return $this->sqlSelectExpression;
}

/**
* Set the SQL SELECT field expression.
*
* @param \Closure $expression The field expression.
* @return self
*/
public function setSqlSelectExpression($expression)
{
$this->sqlSelectExpression = $expression;

return $this;
}

/**
* @param mixed $val The field value.
* @return PropertyField Chainable
Expand All @@ -265,6 +317,40 @@ public function val()
return $this->val;
}

/**
* Format the property's PDO binding parameter identifier.
*
* This method allows a property to apply an SQL function to a named placeholder:
*
* ```sql
* function ($param) {
* return 'ST_GeomFromGeoJSON('.$param.')';
* }
* ```
*
* This method returns a closure to be called during the processing of object
* inserts and updates in {@see \Charcoal\Source\DatabaseSource}.
*
* @link https://www.php.net/manual/en/pdostatement.bindparam.php
*
* @return \Closure
*/
public function sqlPdoBindParamExpression()
{
return $this->sqlPdoBindParamExpression;
}

/**
* @param \Closure $sqlPdoBindParamExpression A callback function to apply an SQL function to a named placeholder.
* @return self
*/
public function setSqlPdoBindParamExpression($sqlPdoBindParamExpression)
{
$this->sqlPdoBindParamExpression = $sqlPdoBindParamExpression;

return $this;
}

/**
* @param mixed $defaultVal The default field value.
* @return PropertyField Chainable
Expand Down
126 changes: 111 additions & 15 deletions src/Charcoal/Property/StorablePropertyTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,46 @@ public function fieldIdent($key = null)
/**
* Retrieve the property's namespaced storage field names.
*
* Examples:
* 1. `name`: `name_en`, `name_fr`, `name_de`
* 2. `obj`: `obj_id`, `obj_type`
* 3. `file`: `file`, `file_type`
* 4. `opt`: `opt_0`, `opt_1`, `opt_2`
* This method can be overridden for custom field names.
*
* @return string[]
* Example #1 property `name`:
*
* ```
* {
* "": "name_en"
* }
* ```
*
* Example #2 multilingual property `title`:
*
* ```
* {
* "en": "title_en",
* "fr": "title_fr",
* "de": "title_de"
* }
* ```
*
* Example #3 custom property `obj`:
*
* ```
* {
* "id": "obj_id",
* "type": "obj_type"
* }
* ```
*
* Example #4 custom property `tuple`:
*
* ```
* {
* "1": "tuple_1",
* "2": "tuple_2",
* "3": "tuple_3"
* }
* ```
*
* @return array<(string|int), string>
*/
public function fieldNames()
{
Expand All @@ -122,7 +155,35 @@ public function fieldNames()
}

/**
* Retrieve the property's value in a format suitable for the given field key.
* Format the property's PDO select statement.
*
* This method can be overridden for custom select function parsing.
*
* This method allows a property to apply an SQL function to a property select statement:
*
* ```sql
* function ($select) {
* return 'ST_AsGeoJSON('.$select.')';
* }
* ```
*
* This method returns a closure to be called during the processing of fetching the object
* or collection in {@see \Charcoal\Source\DatabaseSource}.
*
* @return \Closure
*/
protected function sqlSelectExpression()
{
return function ($select) {
return $select;
};
}

/**
* Format the property's value for the given field key suitable for storage.
*
* This method can be overridden for parsing custom field values.
* It is recommended to override {@see self::storageVal()} instead.
*
* @param string $key The property field key.
* @param mixed $val The value to set as field value.
Expand Down Expand Up @@ -190,6 +251,39 @@ public function storageVal($val)
return $val;
}

/**
* Format the property's PDO binding parameter identifier.
*
* This method can be overridden for custom named placeholder parsing.
*
* This method allows a property to apply an SQL function to a named placeholder:
*
* ```sql
* function ($param) {
* return 'ST_GeomFromGeoJSON('.$param.')';
* }
* ```
*
* This method returns a closure to be called during the processing of object
* inserts and updates in {@see \Charcoal\Source\DatabaseSource}.
*
* @link https://www.php.net/manual/en/pdostatement.bindparam.php
*
* @return \Closure
*/
protected function sqlPdoBindParamExpression()
{
/**
* Format the PDO parameter name.
*
* @param string $param A PDO parameter name in the form `:name`.
* @return string The formatted parameter name.
*/
return function ($param) {
return $param;
};
}

/**
* Parse the property's value (from a flattened structure)
* in a format suitable for models.
Expand Down Expand Up @@ -254,14 +348,16 @@ protected function generateFields($val = null)
$fieldNames = $this->fieldNames();
foreach ($fieldNames as $fieldKey => $fieldName) {
$field = $this->createPropertyField([
'ident' => $fieldName,
'sqlType' => $this->sqlType(),
'sqlPdoType' => $this->sqlPdoType(),
'sqlEncoding' => $this->sqlEncoding(),
'extra' => $this->sqlExtra(),
'val' => $this->fieldValue($fieldKey, $val),
'defaultVal' => $this->sqlDefaultVal(),
'allowNull' => $this['allowNull'],
'ident' => $fieldName,
'sqlType' => $this->sqlType(),
'sqlPdoType' => $this->sqlPdoType(),
'sqlEncoding' => $this->sqlEncoding(),
'extra' => $this->sqlExtra(),
'val' => $this->fieldValue($fieldKey, $val),
'sqlSelectExpression' => $this->sqlSelectExpression(),
'sqlPdoBindParamExpression' => $this->sqlPdoBindParamExpression(),
'defaultVal' => $this->sqlDefaultVal(),
'allowNull' => $this['allowNull'],
]);

$fields[$fieldKey] = $field;
Expand Down