Author: bshaffer
Date: 2010-05-04 16:08:43 +0200 (Tue, 04 May 2010)
New Revision: 29345
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/LICENSE
plugins/csDoctrineActAsSortablePlugin/branches/1.4/README
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/listener/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/listener/Sortable.php
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/template/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/template/Sortable.php
plugins/csDoctrineActAsSortablePlugin/branches/1.4/package.xml
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/css/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/css/sortable.css
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/demote.png
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/promote.png
Log:
creating 1.4 branch
Added: plugins/csDoctrineActAsSortablePlugin/branches/1.4/README
===================================================================
--- plugins/csDoctrineActAsSortablePlugin/branches/1.4/README
(rev 0)
+++ plugins/csDoctrineActAsSortablePlugin/branches/1.4/README 2010-05-04
14:08:43 UTC (rev 29345)
@@ -0,0 +1,123 @@
+csDoctrineActAsSortablePlugin
+=============================
+
+The `csDoctrineActAsSortablePlugin` is a symfony plugin that allows use of the
doctrine behavior actAsSortable.
+
+This behavior provides methods on your model for setting display
order/position.
+
+This plugin also contains images to implement for ordering.
+
+Installation
+------------
+
+ * Install the plugin
+
+ $ symfony plugin:install csDoctrineActAsSortablePlugin
+
+ * Apply the behavior to your model in your schema file
`config/doctrine/schema.yml`, ie:
+
+ [yml]
+ model:
+ actAs: [Sortable]
+ Optionally accepts a UniqueBy attribute which will be used on a model with
a one-to-many relationship
+
+ model:
+ actAs: [Sortable]
+ uniqueBy: [parent_id]
+
+ * Rebuild your models and database
+
+ $ symfony doctrine:build-all-reload
+
+ alternatively you could build the models, the sql, then run the sql
manually
+
+ * Publish your assets
+
+ $ symfony plugin:publish-assets
+
+ * Clear your cache
+
+ $ symfony cc
+
+
+Available Record Methods
+------------------------
+
+ * promote
+
+ [php]
+ $record->promote();
+
+ * demote
+
+ [php]
+ $record->demote();
+
+ * moveToFirst
+
+ [php]
+ $record->moveToFirst();
+
+ * moveToLast
+
+ [php]
+ $record->moveToLast();
+
+ * moveToPosition
+
+ [php]
+ $record->moveToPosition($newPosition);
+
+
+Available Table Methods
+------------------------
+
+ * sort - accepts the array created by the symfony/prototype sortableElement
tag
+
+ [php]
+ Doctrine::getTable('Model')->sort($order);
+
+ * findAllSorted - Accepts sort order (asc, desc)
+
+ [php]
+ Doctrine::getTable('Model')->findAllSorted('ASCENDING');
+
+ * findAllSortedWithParent - accepts the parent column name, the value, and
sort order (asc, desc)
+
+ [php]
+ Doctrine::getTable('Model')->findAllSortedWithParent($fk_value,
$fk_name, 'ASCENDING');
+
+
+Example Usage With Admin Generator
+----------------------------------
+
+ * In your module, edit `config/generator.yml`, and under list, object
actions, add:
+
+ [yml]
+ object_actions:
+ promote:
+ action: promote
+ demote:
+ action: demote
+ _edit: -
+ _delete: -
+
+ * In your module, edit ``, Add the following actions:
+
+ [php]
+ public function executePromote()
+ {
+
$object=Doctrine::getTable('MyModel')->findOneById($this->getRequestParameter('id'));
+
+
+ $object->promote();
+ $this->redirect("@moduleIndexRoute");
+ }
+
+ public function executeDemote()
+ {
+
$object=Doctrine::getTable('MyModel')->findOneById($this->getRequestParameter('id'));
+
+ $object->demote();
+ $this->redirect("@moduleIndexRoute");
+ }
\ No newline at end of file
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/listener/Sortable.php
===================================================================
---
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/listener/Sortable.php
(rev 0)
+++
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/listener/Sortable.php
2010-05-04 14:08:43 UTC (rev 29345)
@@ -0,0 +1,76 @@
+<?php
+
+
+/**
+ * Easily sort each record based on position
+ *
+ * @package csDoctrineSortablePlugin
+ * @subpackage listener
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link www.phpdoctrine.org
+ * @since 1.0
+ * @version $Revision$
+ * @author Travis Black <[email protected]>
+ */
+class Doctrine_Template_Listener_Sortable extends Doctrine_Record_Listener
+{
+ /**
+ * Array of sortable options
+ *
+ * @var array
+ */
+ protected $_options = array();
+
+
+ /**
+ * __construct
+ *
+ * @param array $options
+ * @return void
+ */
+ 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
+ */
+ public function preInsert(Doctrine_Event $event)
+ {
+ $fieldName = $this->_options['name'];
+ $object = $event->getInvoker();
+ $object->$fieldName = $object->getFinalPosition()+1;
+ }
+
+
+ /**
+ * When a sortable object is deleted, promote all objects positioned lower
than itself
+ *
+ * @param string $Doctrine_Event
+ * @return void
+ */
+ public function postDelete(Doctrine_Event $event)
+ {
+ $fieldName = $this->_options['name'];
+ $object = $event->getInvoker();
+ $position = $object->$fieldName;
+
+ $q = $object->getTable()->createQuery()
+ ->update(get_class($object))
+ ->set($fieldName, $fieldName . ' - ?', '1')
+ ->where($fieldName . ' > ?', $position)
+ ->orderBy($fieldName);
+
+ foreach ($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+
+ $q->execute();
+ }
+}
\ No newline at end of file
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/template/Sortable.php
===================================================================
---
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/template/Sortable.php
(rev 0)
+++
plugins/csDoctrineActAsSortablePlugin/branches/1.4/lib/template/Sortable.php
2010-05-04 14:08:43 UTC (rev 29345)
@@ -0,0 +1,375 @@
+<?php
+
+/**
+ * Easily create a slug for each record based on a specified set of fields
+ *
+ * @package csDoctrineSortablePlugin
+ * @subpackage template
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link www.phpdoctrine.org
+ * @since 1.0
+ * @version $Revision$
+ * @author Travis Black <[email protected]>
+ */
+class Doctrine_Template_Sortable extends Doctrine_Template
+{
+ /**
+ * Array of Sortable options
+ *
+ * @var string
+ */
+ protected $_options = array('name' => 'position',
+ 'alias' => null,
+ 'type' => 'integer',
+ 'length' => 8,
+ 'unique' => true,
+ 'options' => array(),
+ 'fields' => array(),
+ 'uniqueBy' => array(),
+ 'uniqueIndex' => true,
+ 'indexName' => 'sortable'
+ );
+
+ /**
+ * __construct
+ *
+ * @param string $array
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+ }
+
+
+ /**
+ * Set table definition for sortable behavior
+ * (borrowed and modified from Sluggable in Doctrine core)
+ *
+ * @return void
+ */
+ 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 (!empty($this->_options['uniqueBy']) &&
!is_array($this->_options['uniqueBy']))
+ {
+ throw new sfException("Sortable option 'uniqueBy' must be an array");
+ }
+
+ if ($this->_options['uniqueIndex'] == true && !
empty($this->_options['uniqueBy']))
+ {
+ $indexFields = array($this->_options['name']);
+ $indexFields = array_merge($indexFields, $this->_options['uniqueBy']);
+
+ $this->index($this->getSortableIndexName(), array('fields' =>
$indexFields, 'type' => 'unique'));
+
+ }
+ elseif ($this->_options['unique'])
+ {
+ $indexFields = array($this->_options['name']);
+ $this->index($this->getSortableIndexName(), array('fields' =>
$indexFields, 'type' => 'unique'));
+
+ }
+
+ $this->addListener(new
Doctrine_Template_Listener_Sortable($this->_options));
+ }
+
+ /**
+ * Returns the name of the index to create for the position field.
+ *
+ * @return string
+ */
+ protected function getSortableIndexName()
+ {
+ return sprintf('%s_%s_%s', $this->getTable()->getTableName(),
$this->_options['name'], $this->_options['indexName']);
+ }
+
+
+ /**
+ * Demotes a sortable object to a lower position
+ *
+ * @return void
+ */
+ public function demote()
+ {
+ $object = $this->getInvoker();
+ $position = $object->get($this->_options['name']);
+
+ if ($position < $object->getFinalPosition())
+ {
+ $object->moveToPosition($position + 1);
+ }
+ }
+
+
+ /**
+ * Promotes a sortable object to a higher position
+ *
+ * @return void
+ */
+ public function promote()
+ {
+ $object = $this->getInvoker();
+ $position = $object->get($this->_options['name']);
+
+ if ($position > 1)
+ {
+ $object->moveToPosition($position - 1);
+ }
+ }
+
+ /**
+ * Sets a sortable object to the first position
+ *
+ * @return void
+ */
+ public function moveToFirst()
+ {
+ $object = $this->getInvoker();
+ $object->moveToPosition(1);
+ }
+
+
+ /**
+ * Sets a sortable object to the last position
+ *
+ * @return void
+ */
+ public function moveToLast()
+ {
+ $object = $this->getInvoker();
+ $object->moveToPosition($object->getFinalPosition());
+ }
+
+
+ /**
+ * Moves a sortable object to a designate position
+ *
+ * @param int $newPosition
+ * @return void
+ */
+ 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->get($this->_options['name']);
+ $connection = $object->getTable()->getConnection();
+
+ //begin Transaction
+ $connection->beginTransaction();
+
+ // Position is required to be unique. Blanks it out before it moves others
up/down.
+ $object->set($this->_options['name'], null);
+ $object->save();
+
+
+ if ($position > $newPosition)
+ {
+ $q = $object->getTable()->createQuery()
+ ->update(get_class($object))
+ ->set($this->_options['name'],
$this->_options['name'] . ' + 1')
+ ->where($this->_options['name'] . ' < ?',
$position)
+ ->andWhere($this->_options['name'] . ' >= ?',
$newPosition)
+ ->orderBy($this->_options['name'] . ' DESC');
+
+ foreach ($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+
+ $q->execute();
+ }
+ elseif ($position < $newPosition)
+ {
+
+ $q = $object->getTable()->createQuery()
+ ->update(get_class($object))
+ ->set($this->_options['name'],
$this->_options['name'] . ' - 1')
+ ->where($this->_options['name'] . ' > ?',
$position)
+ ->andWhere($this->_options['name'] . ' <= ?',
$newPosition);
+
+ foreach($this->_options['uniqueBy'] as $field)
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+
+ $q->execute();
+ }
+
+ $object->set($this->_options['name'], $newPosition);
+ $object->save();
+
+ // Commit Transaction
+ $connection->commit();
+ }
+
+
+ /**
+ * Send an array from the sortable_element tag (symfony+prototype)and it will
+ * update the sort order to match
+ *
+ * @param string $order
+ * @return void
+ * @author Travis Black
+ */
+ public function sortTableProxy($order)
+ {
+ /*
+ TODO
+ - Add proper error messages.
+ */
+ $table = $this->getInvoker()->getTable();
+ $class = get_class($this->getInvoker());
+ $connection = $table->getConnection();
+
+ $connection->beginTransaction();
+
+ foreach ($order as $position => $id)
+ {
+ $newObject = Doctrine::getTable($class)->findOneById($id);
+
+ if ($newObject->get($this->_options['name']) != $position + 1)
+ {
+ $newObject->moveToPosition($position + 1);
+ }
+ }
+
+ // Commit Transaction
+ $connection->commit();
+ }
+
+
+ /**
+ * Finds all sortable objects and sorts them based on position attribute
+ * Ascending or Descending based on parameter
+ *
+ * @param string $order
+ * @return $query
+ */
+ public function findAllSortedTableProxy($order = 'ASC')
+ {
+ $order = $this->formatAndCheckOrder($order);
+ $object = $this->getInvoker();
+
+ $query = $object->getTable()->createQuery()
+ ->orderBy($this->_options['name'] . ' ' .
$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 $parentValue
+ * @param string $parent_column_value
+ * @param string $order
+ * @return $query
+ */
+ public function findAllSortedWithParentTableProxy($parentValue,
$parentColumnName = null, $order = 'ASC')
+ {
+ $order = $this->formatAndCheckOrder($order);
+
+ $object = $this->getInvoker();
+ $class = get_class($object);
+
+ if (!$parentColumnName)
+ {
+ $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
+ {
+ $parentColumnName = $parents[0]->getType();
+ exit((string) $parentColumnName);
+ exit(print_r($parents[0]->toArray()));
+ }
+ }
+
+ $query = $object->getTable()->createQuery()
+ ->from($class . ' od')
+ ->where('od.' . $parentColumnName . ' = ?',
$parentValue)
+ ->orderBy($this->_options['name'] . ' ' .
$order);
+
+ return $query->execute();
+ }
+
+
+ /**
+ * Formats the ORDER for insertion in to query, else throws exception
+ *
+ * @param string $order
+ * @return $order
+ */
+ public function formatAndCheckOrder($order)
+ {
+ $order = strtolower($order);
+
+ if ('ascending' === $order || 'asc' === $order)
+ {
+ $order = 'ASC';
+ }
+ elseif ('descending' === $order || 'desc' === $order)
+ {
+ $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
+ */
+ public function getFinalPosition()
+ {
+ $object = $this->getInvoker();
+
+ $q = $object->getTable()->createQuery()
+ ->select($this->_options['name'])
+ ->orderBy($this->_options['name'] . ' desc');
+
+ foreach($this->_options['uniqueBy'] as $field)
+ {
+ if(is_object($object[$field]))
+ {
+ $q->addWhere($field . ' = ?', $object[$field]['id']);
+ }
+ else
+ {
+ $q->addWhere($field . ' = ?', $object[$field]);
+ }
+ }
+
+ $last = $q->fetchOne();
+ $finalPosition = $last ? $last->get($this->_options['name']) : 0;
+
+ return $finalPosition;
+ }
+}
\ No newline at end of file
Added: plugins/csDoctrineActAsSortablePlugin/branches/1.4/package.xml
===================================================================
--- plugins/csDoctrineActAsSortablePlugin/branches/1.4/package.xml
(rev 0)
+++ plugins/csDoctrineActAsSortablePlugin/branches/1.4/package.xml
2010-05-04 14:08:43 UTC (rev 29345)
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.6" version="2.0"
xmlns="http://pear.php.net/dtd/package-2.0"
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
+ <name>csDoctrineActAsSortablePlugin</name>
+ <channel>plugins.symfony-project.org</channel>
+ <summary>A plugin that adds sorting functions to model</summary>
+ <description>Gives up and down arrows along with various methods to
manipulate the position of a model in a list</description>
+ <lead>
+ <name>Travis Black</name>
+ <user>travib</user>
+ <email>[email protected]</email>
+ <active>yes</active>
+ </lead>
+ <developer>
+ <name>Brent Shaffer</name>
+ <user>bshaffer</user>
+ <email>[email protected]</email>
+ <active>yes</active>
+ </developer>
+ <date>2009-07-10</date>
+ <time>15:54:35</time>
+ <version>
+ <release>1.0.3</release>
+ <api>1.0.3</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.symfony-project.org/license">MIT license</license>
+ <notes>-</notes>
+ <contents>
+ <dir name="/">
+ <file role="data" name="README" />
+ <file role="data" name="LICENSE" />
+ <dir name="lib">
+ <dir name="listener">
+ <!-- model classes -->
+ <file role="data" name="Sortable.php" />
+ </dir>
+ <dir name="template">
+ <!-- model classes -->
+ <file role="data" name="Sortable.php" />
+ </dir>
+ </dir>
+ <dir name="web">
+ <dir name="images">
+ <!-- images -->
+ <dir name="sortable">
+ <dir name="icons">
+ <file role="data" name="promote.png" />
+ <file role="data" name="demote.png" />
+ </dir>
+ </dir>
+ </dir>
+ <dir name="css">
+ <!-- css -->
+ <file role="data" name="sortable.css" />
+ </dir>
+ </dir>
+ </dir>
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.1.0</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.1</min>
+ </pearinstaller>
+ <package>
+ <name>symfony</name>
+ <channel>pear.symfony-project.com</channel>
+ <min>1.1.0</min>
+ <max>1.3.0</max>
+ <exclude>1.3.0</exclude>
+ </package>
+ </required>
+ </dependencies>
+ <phprelease />
+ <changelog>
+ <release>
+ <version>
+ <release>1.0.0</release>
+ <api>1.0.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2009-04-24</date>
+ <license uri="http://www.symfony-project.org/license">MIT license</license>
+ <notes>
+ * minor updates
+ </notes>
+ </release>
+ </changelog>
+</package>
\ No newline at end of file
Added: plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/css/sortable.css
===================================================================
--- plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/css/sortable.css
(rev 0)
+++ plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/css/sortable.css
2010-05-04 14:08:43 UTC (rev 29345)
@@ -0,0 +1,19 @@
+#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;
+}
+#sf_admin_container ul.sf_admin_td_actions {
+ width:120px !important;
+}
\ No newline at end of file
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/demote.png
===================================================================
(Binary files differ)
Property changes on:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/demote.png
___________________________________________________________________
Added: svn:executable
+
Added: svn:mime-type
+ application/octet-stream
Added:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/web/images/sortable/icons/promote.png
===================================================================
(Binary files differ)
Property changes on:
plugins/csDoctrineActAsSortablePlugin/branches/1.4/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.