Author: bshaffer
Date: 2010-05-04 16:09:07 +0200 (Tue, 04 May 2010)
New Revision: 29346
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/Readme.txt
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/listener/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/listener/Sortable.php
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/template/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/template/Sortable.php
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/css/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/css/sortable.css
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/demote.png
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/promote.png
Log:
creating 1.2 branch
Added: plugins/csDoctrineActAsSortablePlugin/branches/1.2/Readme.txt
===================================================================
--- plugins/csDoctrineActAsSortablePlugin/branches/1.2/Readme.txt
(rev 0)
+++ plugins/csDoctrineActAsSortablePlugin/branches/1.2/Readme.txt
2010-05-04 14:09:07 UTC (rev 29346)
@@ -0,0 +1,88 @@
+Documentation for CSDoctrineActAsSortablePlugin
+(created by Travis Black @ CentreSource )
+
+ ======================
+ = GETTING THE PLUGIN =
+ ======================
+ActAsSortable is a behavior for Doctrine which can add a sort order and
ordering functions to any model in your database, even if it is in a
one-to-many relationship.
+
+In order to add the plugin, you can do an SVN checkout. I highly suggest using
svn-externals when adding to your own project.
+
+svn co
http://svn.centresource.com/symfony_plugins/trunk/csDoctrineActAsSortablePlugin
plugins/
+
+
+
+ =================================================================
+ = APPLYING THE PLUGIN AND SORTABLE FUNCTIONALITY TO YOUR SCHEMA =
+ =================================================================
+This will add the behavior models and listener to your project. In order to
implement this behavior on a model, you will just do "actAs: [Sortable]" in
your schema.yml file. ie:
+
+Movie:
+ actAs: [Sortable, Timestampable]
+
+
+Adding this behavior will add a position column to your database. Each record
added to your database will automatically get the lowest possible position.
Each time a record is deleted, all of the other records are repositioned
accordingly.
+
+ActAsSortable also takes an option that will allow you to specify a
combination of fields to apply a sort order to, rather than applying it to a
full set of records. (ie)
+
+Movie:
+ actAs:
+ Sortable:
+ uniqueBy: [genre_id]
+
+The above schema will make it so that each genre of movies is sorted
independently. ie:
+
+genre1['movie1'][]
+
+This also gives your movie and movie table objects access to a number of
sorting methods.
+
+Some common uses of these methods would be:
+
+
+--Retrieving all records from a database in sorted order:
+
+$movies = Doctrine::getTable('Movie')->findAllSorted();
+
+
+--Retrieving all records from a database with a parent model in mind.
+
+$movies = Doctrine::getTable('Movie')->findAllSortedWithParent($genre_id,
'genre_id', $sort_order);
+
+option 1 is the value of the foreign key.
+option 2 is the column name of the foreign key.
+option 3 is the sort order ASC or DESC.
+
+
+--Promoting a record to a higher position
+
+$movie->promote();
+
+
+--Demoting a record to a lower position
+
+$movie->demote();
+
+
+--Moving a record to a position by position number
+
+$movie->moveToPosition($position);
+
+option 1 must be an integer representing the position in which you want your
record to be placed.
+
+
+--Moving a record to the first position
+
+$movie->moveToFirst();
+
+
+
+--Moving a record to the last position
+
+$movie->moveToLast();
+
+
+
+
+--Using the Symfony/Prototype sortable_element function to update the sort
order
+
+Doctrine->getTable('Movie')->sort($sortOrderArray);
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/listener/Sortable.php
===================================================================
---
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/listener/Sortable.php
(rev 0)
+++
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/listener/Sortable.php
2010-05-04 14:09:07 UTC (rev 29346)
@@ -0,0 +1,78 @@
+<?php
+
+//
+// Sortable.php
+// csDoctrineActAsSortablePlugin
+//
+// Created by Travis Black on 2008-12-22.
+// Copyright 2008 Centre{source}. All rights reserved.
+//
+
+class Doctrine_Template_Listener_Sortable extends Doctrine_Record_Listener
+{
+ /**
+ * Array of sortable options
+ */
+ protected $_options = array();
+
+
+ /**
+ * Constructor for Sortable Template
+ *
+ * @param array $options
+ * @return void
+ * @author Travis Black
+ */
+ public function __construct(array $options)
+ {
+ $this->_options = $options;
+ }
+
+
+ /**
+ * Set the position value automatically when a new sortable object is created
+ *
+ * @param Doctrine_Event $event
+ * @return void
+ * @author Travis Black
+ */
+ public function preInsert(Doctrine_Event $event)
+ {
+ $object = $event->getInvoker();
+ $object->position = $object->getFinalPosition()+1;
+ }
+
+ public function preSave(Doctrine_Event $event)
+ {
+ $object = $event->getInvoker();
+ if(!$object->position)
+ {
+ $object->position = $object->getFinalPosition()+1;
+ }
+ }
+ /**
+ * When a sortable object is deleted, promote all objects positioned lower
than itself
+ *
+ * @param string $Doctrine_Event
+ * @return void
+ * @author Travis Black
+ */
+ public function postDelete(Doctrine_Event $event)
+ {
+ $object = $event->getInvoker();
+ $position = $object->position;
+
+ $q = Doctrine_Query::create()
+ ->update(get_class($object))
+ ->set('position', 'position - ?', '1')
+ ->where('position > ' . $position)
+ ->orderBy($this->_options['name']);
+
+ foreach ($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+
+ $q->execute();
+ }
+}
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/template/Sortable.php
===================================================================
---
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/template/Sortable.php
(rev 0)
+++
plugins/csDoctrineActAsSortablePlugin/branches/1.2/lib/template/Sortable.php
2010-05-04 14:09:07 UTC (rev 29346)
@@ -0,0 +1,417 @@
+<?php
+
+//
+// Sortable.php
+// csDoctrineActAsSortablePlugin
+//
+// Created by Travis Black on 2008-12-22.
+// Copyright 2008 Centre{source}. All rights reserved.
+//
+
+class Doctrine_Template_Sortable extends Doctrine_Template
+{
+ /**
+ * Array of sortable options
+ */
+ protected $_options = array('name' => 'position',
+ 'alias' => null,
+ 'type' => 'integer',
+ 'length' => 8,
+ 'unique' => true,
+ 'options' => array(),
+ 'fields' => array(),
+ 'uniqueBy' => array(),
+ 'uniqueIndex' => true,
+ 'canUpdate' => false,
+ 'indexName' => 'sortable'
+ );
+
+
+ /**
+ * Constructor for Sortable Template
+ *
+ * @param array $options
+ * @return void
+ * @author Travis Black
+ */
+ public function __construct(array $options = array())
+ {
+ $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+ }
+
+
+ public function setup()
+ {
+ }
+
+
+ /**
+ * Set table definition for sortable behavior
+ * (borrowed from Sluggabl in Doctrine core)
+ *
+ * @return void
+ * @author Travis Black
+ */
+ public function setTableDefinition()
+ {
+ $name = $this->_options['name'];
+
+ if ($this->_options['alias'])
+ {
+ $name .= ' as ' . $this->_options['alias'];
+ }
+
+ $this->hasColumn($name, $this->_options['type'],
$this->_options['length'], $this->_options['options']);
+
+ if ($this->_options['uniqueIndex'] == true && !
empty($this->_options['uniqueBy']))
+ {
+ $indexFields = array($this->_options['name']);
+ $indexFields = array_merge($indexFields, $this->_options['uniqueBy']);
+
+ $this->index($this->_options['indexName'], array('fields' =>
$indexFields,
+ 'type' => 'unique'));
+ }
+ elseif ($this->_options['unique'])
+ {
+ $indexFields = array($this->_options['name']);
+ $this->index($this->_options['indexName'], array('fields' =>
$indexFields,
+ 'type' => 'unique'));
+ }
+
+ $this->addListener(new
Doctrine_Template_Listener_Sortable($this->_options));
+ }
+
+
+ public function getRelatedClassesArray()
+ {
+ $relations = array();
+
+ foreach ($this->getInvoker()->getTable()->getRelations() as $rel)
+ {
+ $componentName = $rel->getTable()->getComponentName();
+ $relations[] = $componentName;
+ }
+
+ return $relations;
+ }
+
+
+ public function getParentRelations()
+ {
+ $parents = array();
+
+ foreach ($this->getInvoker()->getTable()->getRelations() as $rel)
+ {
+ if ($rel->isOwningSide())
+ {
+ $parents[] = $rel;
+ }
+ }
+
+ return $parents;
+ }
+
+
+ /**
+ * Demotes a sortable object to a lower position
+ *
+ * @return void
+ * @author Travis Black
+ */
+ public function demote()
+ {
+ $object = $this->getInvoker();
+ $position = $object->position;
+
+ if ($object->position < $object->getFinalPosition())
+ {
+ $object->moveToPosition($position + 1);
+ }
+ }
+
+
+ /**
+ * Promotes a sortable object to a lower position
+ *
+ * @return void
+ * @author Travis Black
+ */
+ public function promote()
+ {
+ $object = $this->getInvoker();
+ $position = $object->position;
+
+ if ($object->position > 1)
+ {
+ $object->moveToPosition($position - 1);
+ }
+ }
+
+
+ public function promoteByIdTableProxy()
+ {
+ }
+
+ public function promoteByTableProxy()
+ {
+ }
+
+
+ /**
+ * Sets a sortable object to the first position
+ *
+ * @return void
+ * @author Travis Black
+ */
+ public function moveToFirst()
+ {
+ $object = $this->getInvoker();
+ $object->moveToPosition(1);
+ }
+
+
+ /**
+ * Sets a sortable object to the last position
+ *
+ * @return void
+ * @author Travis Black
+ */
+ public function moveToLast()
+ {
+ $object = $this->getInvoker();
+ $object->moveToPosition($object->getFinalPosition());
+ }
+
+
+ /**
+ * Moves a sortable object to a designate position
+ *
+ * @param string $newPosition
+ * @return void
+ * @author Travis Black
+ */
+ public function moveToPosition($newPosition)
+ {
+ if (!is_int($newPosition))
+ {
+ throw new Doctrine_Exception('moveToPosition requires an Integer as the
new position. Entered ' . $newPosition);
+ }
+
+ $object = $this->getInvoker();
+ $position = $object->position;
+
+ // Position is required to be unique. Blanks it out before it moves others
up/down.
+ if(!$object->setPosition(null)){
+ throw new Doctrine_Exception('Failed to set the position to null on your
'.get_class($object));
+ }
+ $object->save();
+
+ // if(!$object->save()){
+ // throw new Doctrine_Exception('Failed to save your
'.get_class($object).' with a blank position.');
+ // }
+ if ($position > $newPosition)
+ {
+ $q = Doctrine_Query::create()
+ ->update(get_class($object))
+ ->set('position', 'position + 1')
+ ->where('position < ' . $position)
+ ->andWhere('position >= ' . $newPosition)
+ ->orderBy('position DESC');
+
+ foreach ($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field.' = ?', $object[$field]);
+ }
+
+ $q->execute();
+ }
+ elseif ($position < $newPosition)
+ {
+
+ $q = Doctrine_Query::create()
+ ->update(get_class($object))
+ ->set('position', 'position - 1')
+ ->where('position > ?', $position)
+ ->andWhere('position <= ' . $newPosition);
+
+ foreach($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+
+
+ $q->execute();
+ }
+
+ if(!$object->setPosition($newPosition)){
+ throw new Doctrine_Exception('Failed to set the position on your
'.get_class($object));
+ }
+ $object->save();
+ }
+
+
+ /**
+ * Send an array from the sortable_element tag and it will
+ * update the sort order to match
+ *
+ * @param string $order
+ * @return void
+ * @author Travis Black
+ */
+ public function sortTableProxy($order)
+ {
+ /*
+ TODO
+ - Make this a transaction.
+ - Add proper error messages.
+ */
+
+ $class = get_class($this->getInvoker());
+
+ foreach ($order as $position => $id)
+ {
+ $newObject = Doctrine::getTable($class)->findOneById($id);
+
+ if ($newObject->position != $position + 1)
+ {
+ $newObject->moveToPosition($position + 1);
+ }
+ }
+ }
+
+
+ /**
+ * Finds all sortable objects and sorts them based on position attribute
+ * Ascending or Descending based on parameter
+ *
+ * @param string $order
+ * @return $query
+ * @author Travis Black
+ */
+ public function findAllSortedTableProxy($order = 'ASC')
+ {
+ $order = $this->formatAndCheckOrder($order);
+
+ $class = get_class($this->getInvoker());
+ $query = Doctrine_Query::create()
+ ->from($class . ' od')
+ ->orderBy('od.position ' . $order);
+
+ return $query->execute();
+ }
+
+
+ /**
+ * Finds and returns records sorted where the parent (fk) in a specified
+ * one to many relationship has the value specified
+ *
+ * @param string $parent_value
+ * @param string $parent_column_value
+ * @param string $order
+ * @return $query
+ * @author Travis Black
+ */
+ public function findAllSortedWithParentTableProxy($parent_value,
$parent_column_name = null, $order = 'ASC')
+ {
+ $order = $this->formatAndCheckOrder($order);
+
+ $object = $this->getInvoker();
+ $class = get_class($object);
+
+ if (!$parent_column_name)
+ {
+ $parents = get_class($object->getParent());
+
+ if (count($parents) > 1)
+ {
+ throw new Doctrine_Exception('No parent column name specified and
object has mutliple parents');
+ }
+ elseif (count($parents) < 1)
+ {
+ throw new Doctrine_Exception('No parent column name specified and
object has no parents');
+ }
+ else
+ {
+ $parent_column_name = $parents[0]->getType();
+ exit((string) $parent_column_name);
+ exit(print_r($parents[0]->toArray()));
+ }
+ }
+
+ $query = Doctrine_Query::create()
+ ->from($class . ' od')
+ ->where('od.' . $parent_column_name . ' = ?',
$parent_value)
+ ->orderBy('position ' . $order);
+
+ return $query->execute();
+ }
+
+
+ /**
+ * Formats the ORDER for insertion in to query, else throws exception
+ *
+ * @param string $order
+ * @return $order
+ * @author Travis Black
+ */
+ public function formatAndCheckOrder($order)
+ {
+ $order = strtolower($order);
+
+ if ($order == 'ascending' || $order == 'asc')
+ {
+ $order = 'ASC';
+ }
+ elseif ($order == 'descending' || $order == 'desc')
+ {
+ $order = 'DESC';
+ }
+ else
+ {
+ throw new Doctrine_Exception('Order parameter value must be "asc" or
"desc"');
+ }
+
+ return $order;
+ }
+
+
+ /**
+ * Get the final position of a model
+ *
+ * @return $position
+ * @author Travis Black
+ */
+ public function getFinalPosition()
+ {
+ $object = $this->getInvoker();
+
+ $q = Doctrine_Query::create()
+ ->select('position')
+ ->from(get_class($object) . ' st')
+ ->orderBy('position desc')
+ ->limit(1);
+
+ foreach($this->_options['uniqueBy'] as $field)
+ {
+ if(is_object($object[$field])){
+ $q->addWhere($field . ' = ?', $object[$field]['id']);
+ }
+ else{
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+ }
+
+ try
+ {
+ $last = $q->execute();
+ $position = $last[0]->position;
+ }
+ catch (Exception $e)
+ {
+ //return 0;
+ exit ($q->getSql());
+ }
+
+ return $position;
+ }
+}
Added: plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/css/sortable.css
===================================================================
--- plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/css/sortable.css
(rev 0)
+++ plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/css/sortable.css
2010-05-04 14:09:07 UTC (rev 29346)
@@ -0,0 +1,16 @@
+#sf_admin_container ul li.sf_admin_action_promote a
+{
+ background-image:none;
+}
+#sf_admin_container ul li.sf_admin_action_demote a
+{
+ background-image:none;
+}
+#sf_admin_container ul li.sf_admin_action_promote
+{
+ background:transparent url(../images/sortable/icons/promote.png)
no-repeat scroll 0 0;
+}
+#sf_admin_container ul li.sf_admin_action_demote
+{
+ background:transparent url(../images/sortable/icons/demote.png)
no-repeat scroll 0 0;
+}
\ No newline at end of file
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/demote.png
===================================================================
(Binary files differ)
Property changes on:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/demote.png
___________________________________________________________________
Added: svn:executable
+
Added: svn:mime-type
+ application/octet-stream
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/promote.png
===================================================================
(Binary files differ)
Property changes on:
plugins/csDoctrineActAsSortablePlugin/branches/1.2/web/images/sortable/icons/promote.png
___________________________________________________________________
Added: svn:executable
+
Added: svn:mime-type
+ application/octet-stream
--
You received this message because you are subscribed to the Google Groups
"symfony SVN" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/symfony-svn?hl=en.