Skip to content

Commit

Permalink
Merge pull request #310 from j4mie/develop
Browse files Browse the repository at this point in the history
Merge develop into master for release
  • Loading branch information
treffynnon authored Dec 14, 2016
2 parents 1db83c9 + b479cad commit 00b5fcd
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 40 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
*.sqlite
docs/_build
/phpunit.phar
/vendor
/composer.lock
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.6
- 7.0
- hhvm
script: "phpunit --colors --coverage-text"
37 changes: 26 additions & 11 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,27 @@ foreach ($tweets as $tweet) {

Changelog
---------

#### 1.5.1 - release 2014-06-23
#### 1.5.2 - released 2016-12-14

* Fix autoincremented compound keys inserts [[lrlopez](https://github.com/lrlopez)] - [issue #233](https://github.com/j4mie/idiorm/issues/233) and [pull #235](https://github.com/j4mie/idiorm/pull/235)
* Add @method tags for magic methods [[stellis](https://github.com/stellis)] - [issue #237](https://github.com/j4mie/idiorm/issues/237)
* Ensure `is_dirty()` returns correctly when fed null or an empty string [[tentwofour](https://github.com/tentwofour)] - [issue #268](https://github.com/j4mie/idiorm/issues/268)
* Adding Code Climate badge to the readme file [[e3betht](https://github.com/e3betht)] - [issue #260](https://github.com/j4mie/idiorm/issues/260)
* Typo in navigation [[leongersen](https://github.com/leongersen)] - [issue #257](https://github.com/j4mie/idiorm/issues/257)
* Support named placeholders logging and test [[m92o](https://github.com/m92o)] - [issue #223](https://github.com/j4mie/idiorm/issues/223)
* `having_id_is()` reference undefined variable `$value` [[Treffynnon](https://github.com/treffynnon)] - [issue #224](https://github.com/j4mie/idiorm/issues/224)
* Documentation fix - ORM query output for `where_any_is()` [[uovidiu](https://github.com/uovidiu)] - [issue #306](https://github.com/j4mie/idiorm/issues/306)
* Code style fix preventing nested loops from using the same variable names [[mkkeck](https://github.com/mkkeck)] - [issue #301](https://github.com/j4mie/idiorm/issues/301)
* Document shortcomings of the built in query logger [[Treffynnon](https://github.com/treffynnon)] - [issue #307](https://github.com/j4mie/idiorm/issues/307)
* Add phpunit to dev dependencies, add `composer test` script shortcut and fix PDO mock in test bootstrap [[Treffynnon](https://github.com/treffynnon)]
* New test for multiple raw where clauses [[Treffynnon](https://github.com/treffynnon)] - [issue #236](https://github.com/j4mie/idiorm/issues/236)
* Remove PHP 5.2 from travis-ci containers to test against (**note** Idiorm still supports PHP 5.2 despite this) [[Treffynnon](https://github.com/treffynnon)]

#### 1.5.1 - released 2014-06-23

* Binding of named parameters was broken [[cainmi](https://github.com/cainmi)] - [issue #221](https://github.com/j4mie/idiorm/pull/221)

#### 1.5.0 - release 2014-06-22
#### 1.5.0 - released 2014-06-22

* Multiple OR'ed conditions support [[lrlopez](https://github.com/lrlopez)] - [issue #201](https://github.com/j4mie/idiorm/issues/201)
* `where_id_in()` for selecting multiple records by primary key [[lrlopez](https://github.com/lrlopez)] - [issue #202](https://github.com/j4mie/idiorm/issues/202)
Expand All @@ -100,13 +115,13 @@ Changelog
* Improve where statement precendence documentation [[thomasahle](https://github.com/thomasahle)] - [issue #190](https://github.com/j4mie/idiorm/issues/190)
* Improve testing checks [[charsleysa](https://github.com/charsleysa)] - [issue #173](https://github.com/j4mie/idiorm/issues/173)

#### 1.4.1 - release 2013-12-12
#### 1.4.1 - released 2013-12-12

**Patch update to remove a broken pull request** - may have consequences for users of 1.4.0 that exploited the "`find_many()` now returns an associative array with the databases primary ID as the array keys" change that was merged in 1.4.0.

* Back out pull request/issue [#133](https://github.com/j4mie/idiorm/pull/133) as it breaks backwards compatibility in previously unexpected ways (see [#162](https://github.com/j4mie/idiorm/pull/162), [#156](https://github.com/j4mie/idiorm/issues/156) and [#133](https://github.com/j4mie/idiorm/pull/133#issuecomment-29063108)) - sorry for merging this change into Idiorm - closes [issue 156](https://github.com/j4mie/idiorm/issues/156)

#### 1.4.0 - release 2013-09-05
#### 1.4.0 - released 2013-09-05

* `find_many()` now returns an associative array with the databases primary ID as the array keys [[Surt](https://github.com/Surt)] - [issue #133](https://github.com/j4mie/idiorm/issues/133)
* Calls to `set()` and `set_expr()` return `$this` allowing them to be chained [[Surt](https://github.com/Surt)]
Expand All @@ -123,7 +138,7 @@ Changelog
* Fix docblock [[ulrikjohansson](https://github.com/ulrikjohansson)] - [issue #147](https://github.com/j4mie/idiorm/issues/147)
* Fix incorrect variable name in querying documentation [[fridde](https://github.com/fridde)] - [issue #146](https://github.com/j4mie/idiorm/issues/146)

#### 1.3.0 - release 2013-01-31
#### 1.3.0 - released 2013-01-31

* Documentation moved to [idiorm.rtfd.org](http://idiorm.rtfd.org) and now built using [Sphinx](http://sphinx-doc.org/)
* Add support for multiple database connections - closes [issue #15](https://github.com/j4mie/idiorm/issues/15) [[tag](https://github.com/tag)]
Expand All @@ -143,19 +158,19 @@ Changelog
* Fix issue with aggregate functions always returning `int` when is `float` sometimes required - closes [issue #92](https://github.com/j4mie/idiorm/issues/92)
* Move testing into PHPUnit to unify method testing and query generation testing

#### 1.2.3 - release 2012-11-28
#### 1.2.3 - released 2012-11-28

* Fix [issue #78](https://github.com/j4mie/idiorm/issues/78) - remove use of PHP 5.3 static call

#### 1.2.2 - release 2012-11-15
#### 1.2.2 - released 2012-11-15

* Fix bug where input parameters were sent as part-indexed, part associative

#### 1.2.1 - release 2012-11-15
#### 1.2.1 - released 2012-11-15

* Fix minor bug caused by IdiormStringException not extending Exception

#### 1.2.0 - release 2012-11-14
#### 1.2.0 - released 2012-11-14

* Setup composer for installation via packagist (j4mie/idiorm)
* Add `order_by_expr` method [[sandermarechal](http://github.com/sandermarechal)]
Expand All @@ -173,7 +188,7 @@ Changelog
* Add `find_array` to get the records as associative arrays [[Surt](https://github.com/Surt)] - closes [issue #17](https://github.com/j4mie/idiorm/issues/17)
* Fix bug in `_log_query` with `?` and `%` supplied in raw where statements etc. - closes [issue #57](https://github.com/j4mie/idiorm/issues/57) [[ridgerunner](https://github.com/ridgerunner)]

#### 1.1.1 - release 2011-01-30
#### 1.1.1 - released 2011-01-30

* Fix bug in quoting column wildcard. j4mie/paris#12
* Small documentation improvements
Expand Down
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
"role": "Maintainer"
}
],
"scripts": {
"test": "vendor/bin/phpunit"
},
"require-dev": {
"phpunit/phpunit": "^5.6"
},
"license": [
"BSD-2-Clause",
"BSD-3-Clause",
Expand Down
11 changes: 11 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@ the log. ``ORM::get_last_query()`` returns the most recent query
executed. ``ORM::get_query_log()`` returns an array of all queries
executed.

.. note::

The code that does the query log is an approximation of that provided by PDO/the
database (see the Idiorm source code for detail). The actual query isn't even available
to idiorm to log as the database/PDO handles the binding outside of idiorm's reach and
doesn't pass it back.

This means that you might come across some inconsistencies between what is logged and
what is actually run. In these case you'll need to look at the query log provided by
your database vendor (eg. MySQL).

Query logger
^^^^^^^^^^^^

Expand Down
2 changes: 1 addition & 1 deletion docs/querying.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ column using a second parameter:
->find_many();
// Creates SQL:
SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` > '10' ) OR ( `name` = 'Fred' AND `age` > '20' ));
SELECT * FROM `widget` WHERE (( `name` = 'Joe' AND `age` = '10' ) OR ( `name` = 'Fred' AND `age` > '20' ));
If you want to set the default operator for all the columns, just pass it as the second parameter:

Expand Down
124 changes: 102 additions & 22 deletions idiorm.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,80 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The methods documented below are magic methods that conform to PSR-1.
* This documentation exposes these methods to doc generators and IDEs.
* @see http://www.php-fig.org/psr/psr-1/
*
* @method static array|string getConfig($key = null, $connection_name = self::DEFAULT_CONNECTION)
* @method static null resetConfig()
* @method static \ORM forTable($table_name, $connection_name = self::DEFAULT_CONNECTION)
* @method static null setDb($db, $connection_name = self::DEFAULT_CONNECTION)
* @method static null resetDb()
* @method static null setupLimitClauseStyle($connection_name)
* @method static \PDO getDb($connection_name = self::DEFAULT_CONNECTION)
* @method static bool rawExecute($query, $parameters = array())
* @method static \PDOStatement getLastStatement()
* @method static string getLastQuery($connection_name = null)
* @method static array getQueryLog($connection_name = self::DEFAULT_CONNECTION)
* @method array getConnectionNames()
* @method $this useIdColumn($id_column)
* @method \ORM|bool findOne($id=null)
* @method array|\IdiormResultSet findMany()
* @method \IdiormResultSet findResultSet()
* @method array findArray()
* @method $this forceAllDirty()
* @method $this rawQuery($query, $parameters = array())
* @method $this tableAlias($alias)
* @method int countNullIdColumns()
* @method $this selectExpr($expr, $alias=null)
* @method \ORM selectMany()
* @method \ORM selectManyExpr()
* @method $this rawJoin($table, $constraint, $table_alias, $parameters = array())
* @method $this innerJoin($table, $constraint, $table_alias=null)
* @method $this leftOuterJoin($table, $constraint, $table_alias=null)
* @method $this rightOuterJoin($table, $constraint, $table_alias=null)
* @method $this fullOuterJoin($table, $constraint, $table_alias=null)
* @method $this whereEqual($column_name, $value=null)
* @method $this whereNotEqual($column_name, $value=null)
* @method $this whereIdIs($id)
* @method $this whereAnyIs($values, $operator='=')
* @method array|string whereIdIn($ids)
* @method $this whereLike($column_name, $value=null)
* @method $this whereNotLike($column_name, $value=null)
* @method $this whereGt($column_name, $value=null)
* @method $this whereLt($column_name, $value=null)
* @method $this whereGte($column_name, $value=null)
* @method $this whereLte($column_name, $value=null)
* @method $this whereIn($column_name, $values)
* @method $this whereNotIn($column_name, $values)
* @method $this whereNull($column_name)
* @method $this whereNotNull($column_name)
* @method $this whereRaw($clause, $parameters=array())
* @method $this orderByDesc($column_name)
* @method $this orderByAsc($column_name)
* @method $this orderByExpr($clause)
* @method $this groupBy($column_name)
* @method $this groupByExpr($expr)
* @method $this havingEqual($column_name, $value=null)
* @method $this havingNotEqual($column_name, $value=null)
* @method $this havingIdIs($id)
* @method $this havingLike($column_name, $value=null)
* @method $this havingNotLike($column_name, $value=null)
* @method $this havingGt($column_name, $value=null)
* @method $this havingLt($column_name, $value=null)
* @method $this havingGte($column_name, $value=null)
* @method $this havingLte($column_name, $value=null)
* @method $this havingIn($column_name, $values=null)
* @method $this havingNotIn($column_name, $values=null)
* @method $this havingNull($column_name)
* @method $this havingNotNull($column_name)
* @method $this havingRaw($clause, $parameters=array())
* @method static this clearCache($table_name = null, $connection_name = self::DEFAULT_CONNECTION)
* @method array asArray()
* @method bool setExpr($key, $value = null)
* @method bool isDirty($key)
* @method bool isNew()
*/

class ORM implements ArrayAccess {
Expand Down Expand Up @@ -456,29 +530,33 @@ protected static function _log_query($query, $parameters, $connection_name, $que
self::$_query_log[$connection_name] = array();
}

// Strip out any non-integer indexes from the parameters
foreach($parameters as $key => $value) {
if (!is_int($key)) unset($parameters[$key]);
}

if (count($parameters) > 0) {
if (empty($parameters)) {
$bound_query = $query;
} else {
// Escape the parameters
$parameters = array_map(array(self::get_db($connection_name), 'quote'), $parameters);

// Avoid %format collision for vsprintf
$query = str_replace("%", "%%", $query);
if (array_values($parameters) === $parameters) {
// ? placeholders
// Avoid %format collision for vsprintf
$query = str_replace("%", "%%", $query);

// Replace placeholders in the query for vsprintf
if(false !== strpos($query, "'") || false !== strpos($query, '"')) {
$query = IdiormString::str_replace_outside_quotes("?", "%s", $query);
// Replace placeholders in the query for vsprintf
if(false !== strpos($query, "'") || false !== strpos($query, '"')) {
$query = IdiormString::str_replace_outside_quotes("?", "%s", $query);
} else {
$query = str_replace("?", "%s", $query);
}

// Replace the question marks in the query with the parameters
$bound_query = vsprintf($query, $parameters);
} else {
$query = str_replace("?", "%s", $query);
// named placeholders
foreach ($parameters as $key => $val) {
$query = str_replace($key, $val, $query);
}
$bound_query = $query;
}

// Replace the question marks in the query with the parameters
$bound_query = vsprintf($query, $parameters);
} else {
$bound_query = $query;
}

self::$_last_query = $bound_query;
Expand Down Expand Up @@ -1255,14 +1333,14 @@ public function where_any_is($values, $operator='=') {
$data = array();
$query = array("((");
$first = true;
foreach ($values as $item) {
foreach ($values as $value) {
if ($first) {
$first = false;
} else {
$query[] = ") OR (";
}
$firstsub = true;
foreach($item as $key => $item) {
foreach($value as $key => $item) {
$op = is_string($operator) ? $operator : (isset($operator[$key]) ? $operator[$key] : '=');
if ($firstsub) {
$firstsub = false;
Expand Down Expand Up @@ -1469,7 +1547,7 @@ public function having_not_equal($column_name, $value=null) {
*/
public function having_id_is($id) {
return (is_array($this->_get_id_column_name())) ?
$this->having($this->_get_compound_id_column_values($value)) :
$this->having($this->_get_compound_id_column_values($id), null) :
$this->having($this->_get_id_column_name(), $id);
}

Expand Down Expand Up @@ -1964,7 +2042,7 @@ protected function _set_orm_property($key, $value = null, $expr = false) {
* object was saved.
*/
public function is_dirty($key) {
return isset($this->_dirty_fields[$key]);
return array_key_exists($key, $this->_dirty_fields);
}

/**
Expand Down Expand Up @@ -2023,7 +2101,7 @@ public function save() {
// if the primary key is compound, assign the last inserted id
// to the first column
if (is_array($column)) {
$column = array_slice($column, 0, 1);
$column = reset($column);
}
$this->_data[$column] = $db->lastInsertId();
}
Expand Down Expand Up @@ -2313,6 +2391,8 @@ protected function _str_replace_outside_quotes_cb($matches) {
/**
* A result set class for working with collections of model instances
* @author Simon Holywell <treffynnon@php.net>
* @method null setResults(array $results)
* @method array getResults()
*/
class IdiormResultSet implements Countable, IteratorAggregate, ArrayAccess, Serializable {
/**
Expand Down
8 changes: 7 additions & 1 deletion test/ORMTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,15 @@ public function testIsNew() {
public function testIsDirty() {
$model = ORM::for_table('test')->create();
$this->assertFalse($model->is_dirty('test'));

$model = ORM::for_table('test')->create(array('test' => 'test'));
$this->assertTrue($model->is_dirty('test'));

$model->test = null;
$this->assertTrue($model->is_dirty('test'));

$model->test = '';
$this->assertTrue($model->is_dirty('test'));
}

public function testArrayAccess() {
Expand Down
6 changes: 6 additions & 0 deletions test/QueryBuilderPsr1Test53.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ public function testRawQueryWithParameters() {
$this->assertEquals($expected, ORM::getLastQuery());
}

public function testRawQueryWithNamedPlaceholders() {
ORM::forTable('widget')->rawQuery('SELECT `w`.* FROM `widget` w WHERE `name` = :name AND `age` = :age', array(':name' => 'Fred', ':age' => 5))->findMany();
$expected = "SELECT `w`.* FROM `widget` w WHERE `name` = 'Fred' AND `age` = '5'";
$this->assertEquals($expected, ORM::getLastQuery());
}

public function testSimpleResultColumn() {
ORM::forTable('widget')->select('name')->findMany();
$expected = "SELECT `name` FROM `widget`";
Expand Down
12 changes: 12 additions & 0 deletions test/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ public function testRawWhereClauseInMethodChain() {
$this->assertEquals($expected, ORM::get_last_query());
}

public function testRawWhereClauseMultiples() {
ORM::for_table('widget')->where('age', 18)->where_raw('(`name` = ? OR `name` = ?)', array('Fred', 'Bob'))->where_raw('(`name` = ? OR `name` = ?)', array('Sarah', 'Jane'))->where('size', 'large')->find_many();
$expected = "SELECT * FROM `widget` WHERE `age` = '18' AND (`name` = 'Fred' OR `name` = 'Bob') AND (`name` = 'Sarah' OR `name` = 'Jane') AND `size` = 'large'";
$this->assertEquals($expected, ORM::get_last_query());
}

public function testRawQuery() {
ORM::for_table('widget')->raw_query('SELECT `w`.* FROM `widget` w')->find_many();
$expected = "SELECT `w`.* FROM `widget` w";
Expand All @@ -304,6 +310,12 @@ public function testRawQueryWithParameters() {
$this->assertEquals($expected, ORM::get_last_query());
}

public function testRawQueryWithNamedPlaceholders() {
ORM::for_table('widget')->raw_query('SELECT `w`.* FROM `widget` w WHERE `name` = :name AND `age` = :age', array(':name' => 'Fred', ':age' => 5))->find_many();
$expected = "SELECT `w`.* FROM `widget` w WHERE `name` = 'Fred' AND `age` = '5'";
$this->assertEquals($expected, ORM::get_last_query());
}

public function testSimpleResultColumn() {
ORM::for_table('widget')->select('name')->find_many();
$expected = "SELECT `name` FROM `widget`";
Expand Down
Loading

0 comments on commit 00b5fcd

Please sign in to comment.