Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add support for scope_column in sluggable behavior #341

Closed
wants to merge 8 commits into from

3 participants

@justinhilles

added a config option to support using a scope column

generator/lib/behavior/sluggable/SluggableBehavior.php
@@ -43,6 +44,10 @@ public function modifyTable()
$unique = new Unique($this->getColumnForParameter('slug_column'));
$unique->setName($this->getTable()->getCommonName() . '_slug');
$unique->addColumn($this->getTable()->getColumn($this->getParameter('slug_column')));
+ if($this->getParameter('scope_column'))
+ {
@willdurand Owner

this curly bracket should be on the same line than the if

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@willdurand
Owner

Can you add a unit test to prove your improvement?

@justinhilles

I'll give it a shot but this is something ive never done but need to start doing :-)

@willdurand
Owner

Read other tests, it's often useful :)
If you have questions, just ask here or on IRC (#propel on freenode.net)

@willdurand
Owner

Thanks for the CS fix. Anyway, the only chance you get this PR merged is to add few unit tests.
Propel 1.6 is bug fixes only. I can make exceptions when it makes sense, but without few unit tests, I can't understand the purpose of this PR ;)

@justinhilles
@willdurand
Owner

Describe your use case, show me the code, and I will help you.

@justinhilles
@willdurand
Owner

Ah so, it's quite easy.

First, add a table_with_scope table in the schema.xml related to the Sluggable tests. Don't forget to add the scope_column parameter.

Then, use the following tests:

<?php
// test/testsuite/generator/behavior/sluggable/SluggableBehaviorTest.php

public function testUniqueViolationWithoutScope()
{
    TableWithScopeQuery::create()->deleteAll();
    $t = new TableWithScope();
    $t->setTitle('Hello, World');
    $t->save();
    $this->assertEquals('hello-world', $t->getSlug());

    try {
        $t = new TableWithScope();
        $t->setTitle('Hello, World');
        $t->save();

        $this->fail('Exception expected');
    } catch (Exception $e) {
       $this->assertTrue(true, 'Exception successfully thrown'); 
   }
}

public function testNoUniqueViolationWithScope()
{
    TableWithScope::create()->deleteAll();
    $t = new TableWithScope();
    $t->setTitle('Hello, World');
    $t->save();
    $this->assertEquals('hello-world', $t->getSlug());

    try {
        $t = new TableWithScope();
        $t->setTitle('Hello, World');
        $t->setScope('foo');
        $t->save();

        $this->assertEquals('hello-world', $t->getSlug());
    } catch (Exception $e) {
        $this->fail('Unexpected exception catched');
   }
}

My question is: what will be the behavior of the findOneBySlug() method?

@justinhilles
@willdurand
Owner
@justinhilles

Got it, wow thanks! I'll give this a try

@justinhilles

Finally added tests for this. Let me know if they are correct, they are passing for me

@willdurand
Owner

@justinhilles awesome! Can you rebase your PR, then I'll merge it?

@justinhilles

I forked the propel repo and was doing work in my version. I see its different than you explain here: http://www.propelorm.org/contribute.html. Should I do this over and start with that then add my changes? Or is there some slicker way?

@travisbot

This pull request passes (merged 9ee3eb9 into 3b15493).

@justinhilles

I think i rebased but it says in the last commit:
Conflicts:
test/testsuite/generator/behavior/sluggable/SluggableBehaviorTest.php

but i edited the conflict before i committed? Any idea if thats an issue?

@travisbot

This pull request passes (merged cb4acf5 into 3b15493).

@willdurand
Owner

Merged, thank you @justinhilles!

@willdurand willdurand closed this
@willdurand
Owner

Could you port your PR on Propel2 as well? propelorm/Propel2#244

Cheers!

@willdurand willdurand referenced this pull request in propelorm/Propel2
Closed

Port PR #341 from Propel 1.6 #244

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 23, 2012
  1. @justinhilles
  2. @justinhilles
Commits on Jun 4, 2012
  1. @justinhilles
Commits on Jun 7, 2012
  1. @justinhilles

    added support for scope_column

    justinhilles authored Justin Hilles committed
  2. @justinhilles

    tweak for proper php format

    justinhilles authored Justin Hilles committed
  3. @justinhilles

    add test for sluggable with scope and alter make unique in behavior t…

    justinhilles authored Justin Hilles committed
    …o include scope
  4. Merge remote-tracking branch 'origin/master'

    Justin Hilles authored
    Conflicts:
    	test/testsuite/generator/behavior/sluggable/SluggableBehaviorTest.php
  5. @justinhilles
This page is out of date. Refresh to see the latest.
View
158 generator/lib/behavior/sluggable/SluggableBehavior.php
@@ -18,64 +18,68 @@
*/
class SluggableBehavior extends Behavior
{
- // default parameters value
- protected $parameters = array(
- 'slug_column' => 'slug',
- 'slug_pattern' => '',
- 'replace_pattern' => '/\W+/', // Tip: use '/[^\\pL\\d]+/u' instead if you're in PHP5.3
- 'replacement' => '-',
- 'separator' => '-',
- 'permanent' => 'false'
- );
-
- /**
- * Add the slug_column to the current table
- */
- public function modifyTable()
- {
- if (!$this->getTable()->containsColumn($this->getParameter('slug_column'))) {
- $this->getTable()->addColumn(array(
- 'name' => $this->getParameter('slug_column'),
- 'type' => 'VARCHAR',
- 'size' => 255
- ));
- // add a unique to column
- $unique = new Unique($this->getColumnForParameter('slug_column'));
- $unique->setName($this->getTable()->getCommonName() . '_slug');
- $unique->addColumn($this->getTable()->getColumn($this->getParameter('slug_column')));
- $this->getTable()->addUnique($unique);
- }
- }
-
- /**
- * Get the getter of the column of the behavior
- *
- * @return string The related getter, e.g. 'getSlug'
- */
- protected function getColumnGetter()
- {
- return 'get' . $this->getColumnForParameter('slug_column')->getPhpName();
- }
-
- /**
- * Get the setter of the column of the behavior
- *
- * @return string The related setter, e.g. 'setSlug'
- */
- protected function getColumnSetter()
- {
- return 'set' . $this->getColumnForParameter('slug_column')->getPhpName();
- }
-
- /**
- * Add code in ObjectBuilder::preSave
- *
- * @return string The code to put at the hook
- */
- public function preSave($builder)
- {
- $const = $builder->getColumnConstant($this->getColumnForParameter('slug_column'));
- $script = "
+ // default parameters value
+ protected $parameters = array(
+ 'slug_column' => 'slug',
+ 'slug_pattern' => '',
+ 'replace_pattern' => '/\W+/', // Tip: use '/[^\\pL\\d]+/u' instead if you're in PHP5.3
+ 'replacement' => '-',
+ 'separator' => '-',
+ 'permanent' => 'false',
+ 'scope_column' => ''
+ );
+
+ /**
+ * Add the slug_column to the current table
+ */
+ public function modifyTable()
+ {
+ if(!$this->getTable()->containsColumn($this->getParameter('slug_column'))) {
+ $this->getTable()->addColumn(array(
+ 'name' => $this->getParameter('slug_column'),
+ 'type' => 'VARCHAR',
+ 'size' => 255
+ ));
+ // add a unique to column
+ $unique = new Unique($this->getColumnForParameter('slug_column'));
+ $unique->setName($this->getTable()->getCommonName() . '_slug');
+ $unique->addColumn($this->getTable()->getColumn($this->getParameter('slug_column')));
+ if($this->getParameter('scope_column')) {
+ $unique->addColumn($this->getTable()->getColumn($this->getParameter('scope_column')));
+ }
+ $this->getTable()->addUnique($unique);
+ }
+ }
+
+ /**
+ * Get the getter of the column of the behavior
+ *
+ * @return string The related getter, e.g. 'getSlug'
+ */
+ protected function getColumnGetter()
+ {
+ return 'get' . $this->getColumnForParameter('slug_column')->getPhpName();
+ }
+
+ /**
+ * Get the setter of the column of the behavior
+ *
+ * @return string The related setter, e.g. 'setSlug'
+ */
+ protected function getColumnSetter()
+ {
+ return 'set' . $this->getColumnForParameter('slug_column')->getPhpName();
+ }
+
+ /**
+ * Add code in ObjectBuilder::preSave
+ *
+ * @return string The code to put at the hook
+ */
+ public function preSave($builder)
+ {
+ $const = $builder->getColumnConstant($this->getColumnForParameter('slug_column'));
+ $script = "
if (\$this->isColumnModified($const) && \$this->{$this->getColumnGetter()}()) {
\$this->{$this->getColumnSetter()}(\$this->makeSlugUnique(\$this->{$this->getColumnGetter()}()));";
if ($this->getParameter('permanent') == 'true') {
@@ -264,22 +268,28 @@ public function addMakeSlugUnique(&$script)
*/
protected function makeSlugUnique(\$slug, \$separator = '" . $this->getParameter('separator') ."', \$increment = 0)
{
- \$slug2 = empty(\$increment) ? \$slug : \$slug . \$separator . \$increment;
- \$slugAlreadyExists = " . $this->builder->getStubQueryBuilder()->getClassname() . "::create()
- ->filterBySlug(\$slug2)
- ->prune(\$this)";
- // watch out: some of the columns may be hidden by the soft_delete behavior
- if ($this->table->hasBehavior('soft_delete')) {
- $script .= "
- ->includeDeleted()";
- }
- $script .= "
- ->count();
- if (\$slugAlreadyExists) {
- return \$this->makeSlugUnique(\$slug, \$separator, ++\$increment);
- } else {
- return \$slug2;
- }
+ \$slug2 = empty(\$increment) ? \$slug : \$slug . \$separator . \$increment;
+ \$slugAlreadyExists = " . $this->builder->getStubQueryBuilder()->getClassname() . "::create()
+ ->filterBySlug(\$slug2)
+ ->prune(\$this)";
+
+ if($this->getParameter('scope_column')) {
+ $getter = 'get' . $this->getColumnForParameter('scope_column')->getPhpName();
+ $script .="
+ ->filterBy('{$this->getColumnForParameter('scope_column')->getPhpName()}', \$this->{$getter}())";
+ }
+ // watch out: some of the columns may be hidden by the soft_delete behavior
+ if ($this->table->hasBehavior('soft_delete')) {
+ $script .= "
+ ->includeDeleted()";
+ }
+ $script .= "
+ ->count();
+ if (\$slugAlreadyExists) {
+ return \$this->makeSlugUnique(\$slug, \$separator, ++\$increment);
+ } else {
+ return \$slug2;
+ }
}
";
}
View
9 test/fixtures/bookstore/behavior-sluggable-schema.xml
@@ -20,4 +20,13 @@
</behavior>
</table>
+ <table name="table_with_scope">
+ <column name="id" required="true" primaryKey="true" autoIncrement="true" type="INTEGER" />
+ <column name="scope" required="true" type="INTEGER" />
+ <column name="title" type="VARCHAR" size="100" primaryString="true" />
+ <behavior name="sluggable">
+ <parameter name="scope_column" value="scope" />
+ </behavior>
+ </table>
+
</database>
View
59 test/testsuite/generator/behavior/sluggable/SluggableBehaviorTest.php
@@ -245,16 +245,55 @@ public function testQueryFindOneBySlug()
$this->assertTrue(method_exists('Table13Query', 'findOneBySlug'), 'The generated query provides a findOneBySlug() method');
$this->assertTrue(method_exists('Table14Query', 'findOneBySlug'), 'The generated query provides a findOneBySlug() method even if the slug column doesnt have the default name');
- Table14Query::create()->deleteAll();
- $t1 = new Table14();
- $t1->setTitle('Hello, World');
- $t1->save();
- $t2 = new Table14();
- $t2->setTitle('Hello, Cruel World');
- $t2->save();
- $t = Table14Query::create()->findOneBySlug('/foo/hello-world/bar');
- $this->assertEquals($t1, $t, 'findOneBySlug() returns a single object matching the slug');
- }
+ Table14Query::create()->deleteAll();
+ $t1 = new Table14();
+ $t1->setTitle('Hello, World');
+ $t1->save();
+ $t2 = new Table14();
+ $t2->setTitle('Hello, Cruel World');
+ $t2->save();
+ $t = Table14Query::create()->findOneBySlug('/foo/hello-world/bar');
+ $this->assertEquals($t1, $t, 'findOneBySlug() returns a single object matching the slug');
+ }
+
+ public function testUniqueViolationWithoutScope()
+ {
+ TableWithScopeQuery::create()->deleteAll();
+ $t = new TableWithScope();
+ $t->setTitle('Hello, World');
+ $t->save();
+ $this->assertEquals('hello-world', $t->getSlug());
+
+ try {
+ $t = new TableWithScope();
+ $t->setTitle('Hello, World');
+ $t->save();
+
+ $this->fail('Exception expected');
+ } catch (Exception $e) {
+ $this->assertTrue(true, 'Exception successfully thrown');
+ }
+ }
+
+ public function testNoUniqueViolationWithScope()
+ {
+ TableWithScopeQuery::create()->deleteAll();
+ $t = new TableWithScope();
+ $t->setTitle('Hello, World');
+ $t->save();
+ $this->assertEquals('hello-world', $t->getSlug());
+
+ try {
+ $t = new TableWithScope();
+ $t->setTitle('Hello, World');
+ $t->setScope(1);
+ $t->save();
+
+ $this->assertEquals('hello-world', $t->getSlug());
+ } catch (Exception $e) {
+ $this->fail($e->getMessage());
+ }
+ }
}
class TestableTable13 extends Table13
Something went wrong with that request. Please try again.