Skip to content

Commit

Permalink
Merge pull request #125 from j4mie/develop
Browse files Browse the repository at this point in the history
Release 1.5.5
  • Loading branch information
treffynnon authored Dec 14, 2016
2 parents 6cd7a3d + 185e574 commit 2b085d9
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 23 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
*.swp
*.sqlite
docs/_build
nbproject/
nbproject/
/vendor
/composer.lock
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.6
- 7.0
script: "phpunit --colors --coverage-text"
10 changes: 10 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ foreach ($tweets as $tweet) {
Changelog
---------

#### 1.5.5 - released 2016-12-14

* Fix join table name not generated correclty [[Ralphunter](https://github.com/Ralphunter)] - [issue #109](https://github.com/j4mie/paris/pull/109)
* Add phpunit as dev dependency and composer script (`composer test`) to easily run tests [[Treffynnon](https://github.com/Treffynnon)]
* Global setting to allow static requests to avoid being forced in to using the namespace + class as the auto table name [[michaelward82](https://github.com/michaelward82)] - [issue #100](https://github.com/j4mie/paris/issues/100)
* Document conflict between static Model calling and auto_prefix_models [[michaelward82](https://github.com/michaelward82)] - [issue #102](https://github.com/j4mie/paris/issues/102)
* Added @method tags for magic methods [[stellis](https://github.com/stellis)] - [issue #104](https://github.com/j4mie/paris/issues/104)
* Add missing `__unset()` magic method [[qyanu](https://github.com/qyanu)] - [issue #106](https://github.com/j4mie/paris/issues/106)
* 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.4 - released 2014-09-23

* Corrects return value in docblock for 2 Model functions [[michaelward82](https://github.com/michaelward82)] - [issue #99](https://github.com/j4mie/paris/pull/99)
Expand Down
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
"php": ">=5.2.0",
"j4mie/idiorm": "1.5.*"
},
"scripts": {
"test": "vendor/bin/phpunit"
},
"require-dev": {
"phpunit/phpunit": "^5.6"
},
"autoload": {
"classmap": ["paris.php"]
}
Expand Down
34 changes: 31 additions & 3 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,40 @@ Here is a namespaced example to make it clearer:
Model::factory('Simple')->find_many(); // SQL executed: SELECT * FROM `tests_simple`
Model::factory('SimpleUser')->find_many(); // SQL executed: SELECT * FROM `tests_simple_user`
Model prefixes are only compatible with the ``Model::factory()`` methods described above.
Where the shorter ``SimpleUser::find_many()`` style syntax is used, the addition of a
Model prefix will cause ``Class not found`` errors.

.. note::

It is possible to define the table name by setting ``$_table`` in your
individual model classes. As documented in the :doc:`Models` section of
the documentation.
Model class property ``$_table`` sets an explicit table name, ignoring the
``$auto_prefix_models`` property in your individual model classes. See documentation in
the :doc:`Models` section of the documentation.

Model prefixing
~~~~~~~~~~~~~~~

Setting: ``Model::$short_table_names``

Set as ``true`` to disregard namespace information when computing table names
from class names.

By default the class ``\Models\CarTyre`` expects the table name ``models_car_tyre``.
With ``Model::$short_table_names = true`` the class ``\Models\CarTyre`` expects the
table name ``car_tyre``.

.. code-block:: php
<?php
Model::$short_table_names = true;
Model::factory('CarTyre')->find_many(); // SQL executed: SELECT * FROM `car_tyre`
namespace Models {
class CarTyre extends Model {
}
}
Further Configuration
~~~~~~~~~~~~~~~~~~~~~
Expand Down
11 changes: 8 additions & 3 deletions docs/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ in a similar way. For example ``\Models\CarTyre`` would be converted to
``models_car_tyre``. Note here that backslashes are replaced with underscores
in addition to the *CapWords* replacement discussed in the previous paragraph.

To disregard namespace information when calculating the table name, set a
**public static** property named ``$_table_use_short_name`` on your class.
This would result in ``\Models\CarTyre`` being converted to ``car_tyre``.
To disregard namespace information when calculating the table name, set
``Model::$short_table_names = true;``. Optionally this may be set or overridden at
class level with the **public static** property ``$_table_use_short_name``. The

``$_table_use_short_name`` takes precedence over ``Model::$short_table_names``
unless ``$_table_use_short_name`` is ``null`` (default).

Either setting results in ``\Models\CarTyre`` being converted to ``car_tyre``.

.. code-block:: php
Expand Down
87 changes: 75 additions & 12 deletions paris.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
* You shouldn't need to interact with this class
* directly. It is used internally by the Model base
* class.
*
*
* 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 void setClassName($class_name)
* @method static \ORMWrapper forTable($table_name, $connection_name = parent::DEFAULT_CONNECTION)
* @method \Model findOne($id=null)
* @method Array findMany()
*/
class ORMWrapper extends ORM {

Expand Down Expand Up @@ -155,7 +165,7 @@ public function find_many() {
* empty instance of the class associated with
* this wrapper instead of the raw ORM class.
*
* return ORMWrapper|bool
* @return ORMWrapper|bool
*/
public function create($data=null) {
return $this->_create_model_instance(parent::create($data));
Expand All @@ -169,6 +179,16 @@ public function create($data=null) {
* class Widget extends Model {
* }
*
*
* 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 void setOrm($orm)
* @method $this setExpr($property, $value = null)
* @method bool isDirty($property)
* @method bool isNew()
* @method Array asArray()
*/
class Model {

Expand All @@ -190,6 +210,17 @@ class Model {
*/
public static $auto_prefix_models = null;

/**
* Set true to to ignore namespace information when computing table names
* from class names.
*
* @example Model::$short_table_names = true;
* @example Model::$short_table_names = false; // default
*
* @var bool $short_table_names
*/
public static $short_table_names = false;

/**
* The ORM instance used by this model
* instance to communicate with the database.
Expand Down Expand Up @@ -225,17 +256,18 @@ protected static function _get_static_property($class_name, $property, $default=
* If not, the class name will be converted using
* the _class_name_to_table_name method method.
*
* If public static property $_table_use_short_name == true
* then $class_name passed to _class_name_to_table_name is
* stripped of namespace information.
* If Model::$short_table_names == true or public static
* property $_table_use_short_name == true then $class_name passed
* to _class_name_to_table_name is stripped of namespace information.
*
* @param string $class_name
* @return string
*
*@return string
*/
protected static function _get_table_name($class_name) {
$specified_table_name = self::_get_static_property($class_name, '_table');
$use_short_class_name =
self::_get_static_property($class_name, '_table_use_short_name');

$use_short_class_name = self::_use_short_table_name($class_name);

if ($use_short_class_name) {
$exploded_class_name = explode('\\', $class_name);
Expand All @@ -248,6 +280,20 @@ protected static function _get_table_name($class_name) {
return $specified_table_name;
}

/**
* Should short table names, disregarding class namespaces, be computed?
*
* $class_property overrides $global_option, unless $class_property is null
*
* @param string $class_name
* @return bool
*/
protected static function _use_short_table_name($class_name) {
$global_option = self::$short_table_names;
$class_property = self::_get_static_property($class_name, '_table_use_short_name');
return is_null($class_property) ? $global_option : $class_property;
}

/**
* Convert a namespace to the standard PEAR underscore format.
*
Expand Down Expand Up @@ -439,12 +485,19 @@ protected function has_many_through($associated_class_name, $join_class_name=nul
// formed by concatenating the names of the base class
// and the associated class, in alphabetical order.
if (is_null($join_class_name)) {
$model = explode('\\', $base_class_name);
$model_name = end($model);
if (substr($model_name, 0, strlen(self::$auto_prefix_models)) == self::$auto_prefix_models) {
$model_name = substr($model_name, strlen(self::$auto_prefix_models), strlen($model_name));
$base_model = explode('\\', $base_class_name);
$base_model_name = end($base_model);
if (substr($base_model_name, 0, strlen(self::$auto_prefix_models)) == self::$auto_prefix_models) {
$base_model_name = substr($base_model_name, strlen(self::$auto_prefix_models), strlen($base_model_name));
}
// Paris wasn't checking the name settings for the associated class.
$associated_model = explode('\\', $associated_class_name);
$associated_model_name = end($associated_model);
if (substr($associated_model_name, 0, strlen(self::$auto_prefix_models)) == self::$auto_prefix_models) {
$associated_model_name = substr($associated_model_name, strlen(self::$auto_prefix_models), strlen($associated_model_name));
}
$class_names = array($model_name, $associated_class_name);
$class_names = array($base_model_name, $associated_model_name);

sort($class_names, SORT_STRING);
$join_class_name = join("", $class_names);
}
Expand Down Expand Up @@ -510,6 +563,16 @@ public function __set($property, $value) {
$this->orm->set($property, $value);
}

/**
* Magic unset method, allows unset($model->property)
*
* @param string $property
* @return void
*/
public function __unset($property) {
$this->orm->__unset($property);
}

/**
* Magic isset method, allows isset($model->property) to work correctly.
*
Expand Down
89 changes: 89 additions & 0 deletions test/HasManyThroughTest53.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
namespace
{
class HasManyThroughTest extends PHPUnit_Framework_TestCase
{
private $sql = '
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT
);
CREATE TABLE tag (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
CREATE TABLE post_tag (
post_id INTEGER,
tag_id INTEGER,
FOREIGN KEY(post_id) REFERENCES post(id),
FOREIGN KEY(tag_id) REFERENCES tag(id)
);
INSERT INTO post (title)
VALUES ("A Blog Post Title: PHPUnit Testing");
INSERT INTO tag (name) VALUES ("php");
INSERT INTO tag (name) VALUES ("programming");
INSERT INTO tag (name) VALUES ("github");
INSERT INTO post_tag (post_id, tag_id) VALUES (1, 1);
INSERT INTO post_tag (post_id, tag_id) VALUES (1, 2);
INSERT INTO post_tag (post_id, tag_id) VALUES (1, 3);
';

public function setUp () {
$db_handle = new PDO('sqlite::memory:');
$db_handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db_handle->exec($this->sql);

ORM::set_db($db_handle);
ORM::configure('logging', true);
}

public function tearDown ()
{
ORM::configure('logging', false);
ORM::set_db(null);
}

public function testHasManyThrough () {
$video = \PHPProject\Models\Post::find_one(1);
$tags = $video->tags()->find_many();
$this->assertArrayHasKey('id', $tags[0]->as_array());
$this->assertArrayHasKey('name', $tags[0]->as_array());
}
}
}

// We need to use the namespaces here to test whether
// the table names are being correctly generated when
// using $_table_use_short_name = true;
namespace PHPProject\Models
{
class Post extends \Model
{
public static $_table_use_short_name = true;

public function tags ()
{
return $this->has_many_through('\\PHPProject\\Models\\Tag');
}
}
class Tag extends \Model
{
public static $_table_use_short_name = true;

public function posts ()
{
return $this->has_many_through('\\PHPProject\\Models\\Post');
}
}
class PostTag extends \Model
{
public static $_table_use_short_name = true;
}
}
?>
29 changes: 29 additions & 0 deletions test/MagicMethodsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

class MagicMethodsTest extends PHPUnit_Framework_TestCase {

public function setUp() {
// Set up the dummy database connection
ORM::set_db(new MockPDO('sqlite::memory:'));

// Enable logging
ORM::configure('logging', true);

Model::$auto_prefix_models = null;
}

public function tearDown() {
ORM::configure('logging', false);
ORM::set_db(null);

Model::$auto_prefix_models = null;
}

public function testMagicMethodUnset() {
$model = Model::factory("Simple")->create();
$model->property = "test";
unset($model->property);
$this->assertFalse(isset($model->property));
$this->assertTrue($model->get("property")!="test");
}
}
Loading

0 comments on commit 2b085d9

Please sign in to comment.