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

Send data to eventhandler to mutate #135

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#Active repository forked from usmanhalalit

# Pixie Query Builder [![Build Status](https://travis-ci.org/usmanhalalit/pixie.png?branch=master)](https://travis-ci.org/usmanhalalit/pixie)
A lightweight, expressive, framework agnostic query builder for PHP it can also be referred as a Database Abstraction Layer. Pixie supports MySQL, SQLite and PostgreSQL and it takes care of query sanitization, table prefixing and many other things with a unified API. At least PHP 5.3 is required.

Expand All @@ -8,6 +10,7 @@ It has some advanced features like:
- Sub Queries
- Nested Queries
- Multiple Database Connections.
- Added support for table creation/mutation

The syntax is quite similar to Laravel's query builder.

Expand Down
23 changes: 11 additions & 12 deletions src/Pixie/EventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function removeEvent($event, $table = ':any')
* @param $event
* @return mixed
*/
public function fireEvents($queryBuilder, $event)
public function fireEvents($queryBuilder, $event, &$args = array())
{
$statements = $queryBuilder->getStatements();
$tables = isset($statements['tables']) ? $statements['tables'] : array();
Expand All @@ -77,22 +77,21 @@ public function fireEvents($queryBuilder, $event)
array_unshift($tables, ':any');

// Fire all events
$counter = 0;
foreach ($tables as $table) {
// Fire before events for :any table
if ($action = $this->getEvent($event, $table)) {
// Make an event id, with event type and table
$eventId = $event . $table;

// Fire event
$handlerParams = func_get_args();
unset($handlerParams[1]); // we do not need $event
// Add to fired list
$this->firedEvents[] = $eventId;
$result = call_user_func_array($action, $handlerParams);
if (!is_null($result)) {
return $result;
};
$eventId = $event . $table;
$params = array($queryBuilder, $tables[$counter + 1], &$args);
// Add to fired list
$this->firedEvents[] = $eventId;
$result = call_user_func_array($action, $params);
if (!is_null($result)) {
return $result;
};
}
$counter++;
}
}
}
224 changes: 223 additions & 1 deletion src/Pixie/QueryBuilder/Adapters/BaseAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,228 @@ public function delete($statements)

return compact('sql', 'bindings');
}

/*
* Create table and returns full query
*
* @param $statements
*
* @return array
* @throws Exception
*/
public function createTable($statements)
{
if (!isset($statements['tables'])) {
throw new Exception('No table specified', 3);
}

if (!isset($statements['columns'])) {
throw new Exception('No columns specified', 3);
}

$table = end($statements['tables']);

$criteria = "(";
for($i = 0; $i < count($statements["columns"]);$i++)
{
$statement = $statements["columns"][$i];
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
$criteria .= $this->createCriteriaForStatement($values, "name datatype(size) constraint", ($i < (count($statements["columns"]) - 1)));
}
$criteria .= ")";

$sqlArray = array('CREATE TABLE', $this->wrapSanitizer($table), $criteria);
$sql = $this->concatenateQuery($sqlArray, ' ', false);
$bindings = array();
return compact('sql', 'bindings');
}

/*
* using the str_ireplace make it possible to replace names by array keys which are the same as in the format
*/
private function createCriteriaForStatement($values, $format, $addCommaToEnd)
{
if (empty($values)) {
throw new Exception('No values specified', 3);
}

$format = $this->addCommaIfNeeded($format, $addCommaToEnd);
return str_ireplace(array_keys($values), $values, $format);
}

/*
* Adding comma to format when its not last item
*/
private function addCommaIfNeeded($format, $addCommaToEnd)
{
if($addCommaToEnd) {
return $format . ", ";
}
return $format;
}

/*
* Alter table and returns full query
* @param $statements
*
* @return array
* @throws Exception
*/
public function alterTable($statements)
{
$totalColumns = count($statements["columns"]);

if (!isset($statements['tables'])) {
throw new Exception('No table specified', 3);
}

if (!isset($statements['columns']) || $totalColumns <= 0) {
throw new Exception('No columns specified', 3);
}

$table = end($statements['tables']);
$criteria = "";
if($totalColumns > 1) {
//Batch
for($i = 0; $i < $totalColumns;$i++)
{
$statement = $statements["columns"][$i];
$criteria .= $this->getAlterTableColumnCriteriaForBatchStatement($statement, ($i < ($totalColumns - 1)));
}
} else {
$statement = $statements["columns"][0];
//Single
$criteria = $this->getAlterTableColumnCriteriaForSingleStatement($statement);
}

$sqlArray = array('ALTER TABLE', $this->wrapSanitizer($table), $criteria);
$sql = $this->concatenateQuery($sqlArray, ' ', false);
$bindings = array();
return compact('sql', 'bindings');
}

/*
* Returns criteria when add/modify one column
*/
private function getAlterTableColumnCriteriaForSingleStatement($statement)
{
switch(strtolower($statement['action']))
{
case "add":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "ADD COLUMN name datatype(size) constraint", false);
case "modify":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "MODIFY COLUMN name datatype(size) constraint", false);
case "rename":
$values = $this->createDynamicCollectionOfValuesForStatement($statement, array("old_name", "new_name"));
return $this->createCriteriaForStatement($values, "CHANGE old_name new_name datatype(size) constraint", false);
case "drop":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "DROP COLUMN name ", false);
default:
throw new Exception('No unknown action is query specified.', 3);
break;
}
}

/*
* Returns criteria when multiple columns mutated in the table
*/
private function getAlterTableColumnCriteriaForBatchStatement($statement, $addCommaToEnd)
{
switch(strtolower($statement['action']))
{
case "add":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "ADD name datatype(size) constraint", $addCommaToEnd);
case "modify":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "MODIFY COLUMN name datatype(size) constraint", $addCommaToEnd);
case "rename":
$values = $this->createDynamicCollectionOfValuesForStatement($statement, array("old_name", "new_name"));
return $this->createCriteriaForStatement($values, "CHANGE old_name new_name datatype(size) constraint", $addCommaToEnd);
case "drop":
$values = $this->createDynamicCollectionOfValuesForStatement($statement);
return $this->createCriteriaForStatement($values, "DROP name ", $addCommaToEnd);
default:
throw new Exception('No unknown action is query specified.', 3);
break;
}
}

/*
* Creates an array where the values are transformed in the correct format, like uppercasing or sanitize
*/
private function createDynamicCollectionOfValuesForStatement($statement, $sanitizeNames = array("name"), $uppercaseNames = array("datatype", "constraint"))
{
$values = array();
foreach($statement as $key => $value)
{
if($key == "action")
continue;

if(is_array($value)) {
$value = implode(" ", $value);
}

if(in_array($key, $sanitizeNames)) {
$values[$key] = $this->wrapSanitizer($value);
} elseif(in_array($key, $uppercaseNames)) {
$values[$key] = strtoupper($value);
} elseif(is_numeric($value)) {
$values[$key] = (int)$value;
} else {
$values[$key] = $value;
}
}
return $values;
}

/*
* Drops a table from database
* @param $statements
*
* @return array
* @throws Exception
*/
public function dropTable($statements)
{
if (!isset($statements['tables'])) {
throw new Exception('No table specified', 3);
}

$table = end($statements['tables']);

$sqlArray = array('DROP TABLE', $this->wrapSanitizer($table));
$sql = $this->concatenateQuery($sqlArray, ' ', false);
$bindings = array();

return compact('sql', 'bindings');
}

/*
* Renames a table in the database
* @param $statements
*
* @return array
* @throws Exception
*/
public function renameTable($statements)
{
if (!isset($statements['tables'])) {
throw new Exception('No table specified', 3);
}

$table_new = end($statements['tables']);
$table_old = prev($statements['tables']);

$sqlArray = array('RENAME TABLE', $this->wrapSanitizer($table_old), "TO", $this->wrapSanitizer($table_new));
$sql = $this->concatenateQuery($sqlArray, ' ', false);
$bindings = array();

return compact('sql', 'bindings');
}

/**
* Array concatenating method, like implode.
Expand Down Expand Up @@ -534,4 +756,4 @@ protected function buildJoin($statements)

return $sql;
}
}
}
Loading