Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9733b2b

Browse files
author
Paul M. Jones
committed
extract statement-rebuilder logic to its own class
1 parent 9bd59ba commit 9733b2b

File tree

2 files changed

+227
-207
lines changed

2 files changed

+227
-207
lines changed

src/ExtendedPdo.php

Lines changed: 11 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ class ExtendedPdo extends PDO implements ExtendedPdoInterface
9595
*/
9696
protected $username;
9797

98+
/**
99+
*
100+
* A specialized statement preparer.
101+
*
102+
* @var Rebuilder
103+
*
104+
*/
105+
protected $rebuilder;
106+
98107
/**
99108
*
100109
* This constructor is pseudo-polymorphic. You may pass a normal set of PDO
@@ -911,7 +920,8 @@ public function prepareWithValues($statement, array $values = array())
911920
}
912921

913922
// rebuild the statement and values
914-
list($statement, $values) = $this->rebuild($statement, $values);
923+
$rebuilder = new Rebuilder($this);
924+
list($statement, $values) = $rebuilder->__invoke($statement, $values);
915925

916926
// prepare the statement
917927
$sth = $this->prepare($statement);
@@ -924,210 +934,4 @@ public function prepareWithValues($statement, array $values = array())
924934
// done
925935
return $sth;
926936
}
927-
928-
/**
929-
*
930-
* Returns a new anonymous object to track bind values.
931-
*
932-
* @param array $values The values to bind and/or replace into a statement.
933-
*
934-
* @return object
935-
*
936-
*/
937-
protected function newBindTracker($values)
938-
{
939-
// anonymous object to track preparation info
940-
return (object) array(
941-
// how many numbered placeholders in the original statement
942-
'num' => 0,
943-
// how many numbered placeholders to actually be bound; this may
944-
// differ from 'num' in that some numbered placeholders may get
945-
// replaced with quoted CSV strings
946-
'count' => 0,
947-
// initial values to be bound
948-
'values' => $values,
949-
// named and numbered placeholders to bind at the end
950-
'final_values' => array(),
951-
);
952-
}
953-
954-
/**
955-
*
956-
* Rebuilds a statement with array values replaced into placeholders.
957-
*
958-
* @param string $statement The statement to rebuild.
959-
*
960-
* @param array $values The values to bind and/or replace into a statement.
961-
*
962-
* @return array An array where element 0 is the rebuilt statement and
963-
* element 1 is the rebuilt array of values.
964-
*
965-
*/
966-
protected function rebuild($statement, $values)
967-
{
968-
$bind = $this->newBindTracker($values);
969-
$statement = $this->rebuildStatement($statement, $bind);
970-
return array($statement, $bind->final_values);
971-
}
972-
973-
/**
974-
*
975-
* Given a statement, rebuilds it with array values embedded.
976-
*
977-
* @param string $statement The SQL statement.
978-
*
979-
* @param object $bind The bind-values tracker.
980-
*
981-
* @return string The rebuilt statement.
982-
*
983-
*/
984-
protected function rebuildStatement($statement, $bind)
985-
{
986-
// find all parts not inside quotes or backslashed-quotes
987-
$apos = "'";
988-
$quot = '"';
989-
$parts = preg_split(
990-
"/(($apos+|$quot+|\\$apos+|\\$quot+).*?)\\2/m",
991-
$statement,
992-
-1,
993-
PREG_SPLIT_DELIM_CAPTURE
994-
);
995-
return $this->rebuildParts($parts, $bind);
996-
}
997-
998-
/**
999-
*
1000-
* Given an array of statement parts, rebuilds each part.
1001-
*
1002-
* @param array $parts The statement parts.
1003-
*
1004-
* @param object $bind The bind-values tracker.
1005-
*
1006-
* @return string The rebuilt statement.
1007-
*
1008-
*/
1009-
protected function rebuildParts($parts, $bind)
1010-
{
1011-
// loop through the non-quoted parts (0, 3, 6, 9, etc.)
1012-
$k = count($parts);
1013-
for ($i = 0; $i <= $k; $i += 3) {
1014-
$parts[$i] = $this->rebuildPart($parts[$i], $bind);
1015-
}
1016-
return implode('', $parts);
1017-
}
1018-
1019-
/**
1020-
*
1021-
* Rebuilds a single statement part.
1022-
*
1023-
* @param string $part The statement part.
1024-
*
1025-
* @param object $bind The bind-values tracker.
1026-
*
1027-
* @return string The rebuilt statement.
1028-
*
1029-
*/
1030-
protected function rebuildPart($part, $bind)
1031-
{
1032-
// split into subparts by ":name" and "?"
1033-
$subs = preg_split(
1034-
"/(:[a-zA-Z_][a-zA-Z0-9_]*)|(\?)/m",
1035-
$part,
1036-
-1,
1037-
PREG_SPLIT_DELIM_CAPTURE
1038-
);
1039-
1040-
// check subparts to convert bound arrays to quoted CSV strings
1041-
$subs = $this->prepareValuePlaceholders($subs, $bind);
1042-
1043-
// reassemble
1044-
return implode('', $subs);
1045-
}
1046-
1047-
/**
1048-
*
1049-
* Prepares the sub-parts of a query with placeholders.
1050-
*
1051-
* @param array $subs The query subparts.
1052-
*
1053-
* @param object $bind The preparation info object.
1054-
*
1055-
* @return array The prepared subparts.
1056-
*
1057-
*/
1058-
protected function prepareValuePlaceholders(array $subs, $bind)
1059-
{
1060-
foreach ($subs as $i => $sub) {
1061-
$char = substr($sub, 0, 1);
1062-
if ($char == '?') {
1063-
$subs[$i] = $this->prepareNumberedPlaceholder($sub, $bind);
1064-
}
1065-
1066-
if ($char == ':') {
1067-
$subs[$i] = $this->prepareNamedPlaceholder($sub, $bind);
1068-
}
1069-
}
1070-
1071-
return $subs;
1072-
}
1073-
1074-
/**
1075-
*
1076-
* Bind or quote a numbered placeholder in a query subpart.
1077-
*
1078-
* @param string $sub The query subpart.
1079-
*
1080-
* @param object $bind The preparation info object.
1081-
*
1082-
* @return string The prepared query subpart.
1083-
*
1084-
*/
1085-
protected function prepareNumberedPlaceholder($sub, $bind)
1086-
{
1087-
// what numbered placeholder is this in the original statement?
1088-
$bind->num ++;
1089-
1090-
// is the corresponding data element an array?
1091-
$bind_array = isset($bind->values[$bind->num])
1092-
&& is_array($bind->values[$bind->num]);
1093-
if ($bind_array) {
1094-
// PDO won't bind an array; quote and replace directly
1095-
$sub = $this->quote($bind->values[$bind->num]);
1096-
} else {
1097-
// increase the count of numbered placeholders to be bound
1098-
$bind->count ++;
1099-
$bind->final_values[$bind->count] = $bind->values[$bind->num];
1100-
}
1101-
1102-
return $sub;
1103-
}
1104-
1105-
/**
1106-
*
1107-
* Bind or quote a named placeholder in a query subpart.
1108-
*
1109-
* @param string $sub The query subpart.
1110-
*
1111-
* @param object $bind The preparation info object.
1112-
*
1113-
* @return string The prepared query subpart.
1114-
*
1115-
*/
1116-
protected function prepareNamedPlaceholder($sub, $bind)
1117-
{
1118-
$name = substr($sub, 1);
1119-
1120-
// is the corresponding data element an array?
1121-
$bind_array = isset($bind->values[$name])
1122-
&& is_array($bind->values[$name]);
1123-
if ($bind_array) {
1124-
// PDO won't bind an array; quote and replace directly
1125-
$sub = $this->quote($bind->values[$name]);
1126-
} else {
1127-
// not an array, retain the placeholder for later
1128-
$bind->final_values[$name] = $bind->values[$name];
1129-
}
1130-
1131-
return $sub;
1132-
}
1133937
}

0 commit comments

Comments
 (0)