Skip to content
This repository has been archived by the owner on Jan 12, 2018. It is now read-only.

Commit

Permalink
moved code from sapphire/trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
chillu committed Oct 8, 2008
1 parent c05a43a commit f1f9046
Show file tree
Hide file tree
Showing 10 changed files with 609 additions and 0 deletions.
Empty file added CHANGELOG
Empty file.
24 changes: 24 additions & 0 deletions LICENSE
@@ -0,0 +1,24 @@
* Copyright (c) 2008, Silverstripe Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Silverstripe Ltd. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Silverstripe Ltd. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
13 changes: 13 additions & 0 deletions README
@@ -0,0 +1,13 @@
####################################################
Generic Views Module
####################################################

# Maintainer Contact
Ingo Schommer (Nickname: ischommer)
<ingo (at) silverstripe (dot) com>

# Requirements
SilverStripe 2.3

# Documentation
http://doc.silverstripe.com/doku.php?id=modules:genericviews
2 changes: 2 additions & 0 deletions _config.php
@@ -0,0 +1,2 @@
<?php
?>
283 changes: 283 additions & 0 deletions code/CollectionController.php
@@ -0,0 +1,283 @@
<?php
/**
* @package sapphire
* @subpackage control
*/
abstract class CollectionController extends Controller {

public $parentController;

/**
* @var string $modelClass Subclass of {@link DataObject} that should be processed.
* You can influence the selection of records through {@link getRecords()}.
*/
protected $modelClass;

/**
* @var string|boolean $recordControllerClass Use a {@link RecordController} subclass
* to customize the detail viewing/editing behaviour.
*/
protected $recordControllerClass = 'RecordController';

static $url_handlers = array(
'' => 'index',
'$Action' => 'handleActionOrID',
);

public static $page_size = 20;

static $allowed_actions = array('index','search','add','AddForm','SearchForm','ResultsForm');

/**
* @param string $parentController
* @param string $modelClass
*/
function __construct($parentController = null, $modelClass = null) {
if($parentController) $this->parentController = $parentController;
if($modelClass) $this->modelClass = $modelClass;

parent::__construct();
}

function init() {
parent::init();

Requirements::themedCSS('layout');
Requirements::themedCSS('typography');
Requirements::themedCSS('form');
}

/**
* Appends the model class to the URL.
*
* @return unknown
*/
function Link() {
if($this->parentController) {
return Controller::join_links($this->parentController->Link(), "$this->modelClass");
} else {
return Controller::join_links("$this->modelClass");
}
}

/**
* Delegate to different control flow, depending on whether the
* URL parameter is a number (record id) or string (action).
*
* @param unknown_type $request
* @return unknown
*/
function handleActionOrID($request) {
if (is_numeric($request->param('Action'))) {
return $this->handleID($request);
} else {
return $this->handleAction($request);
}
}

/**
* Delegate to the RecordController if a valid numeric ID appears in the URL
* segment.
*
* @param HTTPRequest $request
* @return RecordController
*/
function handleID($request) {
$class = $this->recordControllerClass;
return new $class($this, $request);
}

/**
* Return the class name of the model being managed.
*
* @return unknown
*/
function getModelClass() {
return $this->modelClass;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

function index($request) {
return $this->render(array(
'Results' => $this->getRecords()
));
}

function getRecords($searchCriteria = array()) {
$start = ($this->request->getVar('start')) ? (int)$this->request->getVar('start') : 0;
$limit = $this->stat('page_size');

$context = singleton($this->modelClass)->getDefaultSearchContext();
$query = $context->getQuery($searchCriteria, null, array('start'=>$start,'limit'=>$limit));
$records = $context->getResults($searchCriteria, null, array('start'=>$start,'limit'=>$limit));
if($records) {
$records->setPageLimits($start, $limit, $query->unlimitedRowCount());
}

return $records;
}

/**
* Get a search form for a single {@link DataObject} subclass.
*
* @return Form
*/
public function SearchForm() {
$context = singleton($this->modelClass)->getDefaultSearchContext();
$fields = $context->getSearchFields();
$form = new Form($this, "SearchForm",
$fields,
new FieldSet(
new FormAction('search', _t('MemberTableField.SEARCH'))
)
);
$form->setFormMethod('get');

return $form;
}

/**
* Action to render a data object collection, using the model context to provide filters
* and paging.
*
* @return string
*/
function search($data, $form, $request) {
return $this->render(array(
'Results' => $this->getRecords($form->getData()),
'SearchForm' => $form
));
}

/**
* Gets the search query generated on the SearchContext from
* {@link DataObject::getDefaultSearchContext()},
* and the current GET parameters on the request.
*
* @return SQLQuery
*/
function getSearchQuery($searchCriteria) {
$context = singleton($this->modelClass)->getDefaultSearchContext();
return $context->getQuery($searchCriteria);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////


/**
* Create a new model record.
*
* @param unknown_type $request
* @return unknown
*/
function add($request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}

return $this->render(array(
'Form' => $this->AddForm(),
'SearchForm' => false
));
}

/**
* Returns a form for editing the attached model
*/
public function AddForm() {
$newRecord = new $this->modelClass();
if($newRecord->hasMethod('getAddFormFields')) {
$fields = $newRecord->getAddFormFields();
} else {
$fields = $newRecord->getFormFields();
}

$validator = ($newRecord->hasMethod('getValidator')) ? $newRecord->getValidator() : null;

$actions = new FieldSet(new FormAction("doAdd", "Add"));

$form = new Form($this, "AddForm", $fields, $actions, $validator);

return $form;
}

function doAdd($data, $form, $request) {
if(!singleton($this->modelClass)->canCreate(Member::currentUser())) {
return $this->httpError(403);
}

$className = $this->modelClass;
$model = new $className();
// We write before saveInto, since this will let us save has-many and many-many relationships :-)
$model->write();
$form->saveInto($model);
$model->write();

/*
$form->sessionMessage(
_t('RecordController.SAVESUCCESS','Saved record'),
'good'
);
*/

if($this->canDetailView()) {
Director::redirect(Controller::join_links($this->Link(), $model->ID , 'edit'));
} else {
Director::redirectBack();
}

}


/////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* @return string
*/
public function ModelNameSingular() {
return singleton($this->modelClass)->i18n_singular_name();
}

/**
* @return string
*/
public function ModelNamePlural() {
return singleton($this->modelClass)->i18n_plural_name();
}

/**
* Use this to control permissions or completely disable
* links to detail records.
* @return boolean (Default: true)
*/
public function canDetailView() {
return true;
}

/**
* If a parentcontroller exists, use its main template,
* and mix in specific collectioncontroller subtemplates.
*/
function getViewer($action) {
if($this->parentController) {
$viewer = $this->parentController->getViewer($action);
$parentClass = $this->class;
$layoutTemplate = null;
while($parentClass != "Controller" && !$layoutTemplate) {
$layoutGenericTemplate = SSViewer::getTemplateFileByType($parentClass, 'Layout');
if($layoutGenericTemplate) $layoutTemplate = $layoutGenericTemplate;
$layoutActionTemplate = SSViewer::getTemplateFileByType(strtok($parentClass,'_') . '_' . $action, 'Layout');
if($layoutActionTemplate) $layoutTemplate = $layoutActionTemplate;
$parentClass = get_parent_class($parentClass);
}
if($layoutTemplate) $viewer->setTemplateFile('Layout', $layoutTemplate);

return $viewer;
} else {
return parent::getViewer($action);
}
}
}
?>

0 comments on commit f1f9046

Please sign in to comment.