520 lines
18 KiB
PHP
520 lines
18 KiB
PHP
<?php
|
||
|
||
|
||
/**
|
||
* Переименовать контроллер !! (StubController, CrudController, PageController, BaseController) ModelController
|
||
* Возможно нужен еще класс с мета действиями как для actionIndex <= metaActionIndex либо с классам для этих действий
|
||
* Есть класс для управлениями действиями а есть сами действия в виде классов или функций !!
|
||
*
|
||
* @class Controller_Model в котором определены основные действия для редактирования, вывода списка, сохранения, поиска и т.д
|
||
* В модуле определяется только способ отображения этих данных
|
||
*/
|
||
class Controller_Model extends Controller_Action
|
||
{
|
||
public /*.array.*/$schema = array();
|
||
public /*.array.*/$schemaSearch = array();
|
||
|
||
/**
|
||
* FIXME: Лучше $this->table->setHeader
|
||
*/
|
||
public $tableSchema = null;
|
||
public /*.array.*/$formSchema = array();
|
||
|
||
public $menu;
|
||
public $table;
|
||
|
||
protected /*.string.*/$useModel;
|
||
protected /*.string.*/$itemModel;
|
||
|
||
public function __construct()
|
||
{
|
||
parent::__construct();
|
||
$this->menu = new Widgets_PageMenu();
|
||
$this->table = new Widgets_ReactListTable();
|
||
}
|
||
|
||
/**
|
||
*/
|
||
function setUp() {
|
||
parent::setUp();
|
||
$this->table->addMenuItem($this->aUrl('delete'), 'удалить', false, 'all', 'btn-danger', 'remove');
|
||
}
|
||
|
||
function saveParameters(HttpRequest $args, $list) {
|
||
foreach ($list as $item) {
|
||
$args->session()->set(array($this, $item), $args->get($item));
|
||
}
|
||
}
|
||
|
||
protected function getJSONList(/*.Model_Mapper.*/ $model, HttpRequest $request) {
|
||
$result = array();
|
||
$this->saveParameters($request, array('size','page','desc', 'key'));
|
||
|
||
$result['list'] = $model->findAll($request, $request->get('ref'));
|
||
$result['size'] = $model->getCount($request, $request->get('ref'));
|
||
return json_encode($result);
|
||
}
|
||
|
||
protected function getCSV(Model_Mapper $model, HttpRequest $request, $title) {
|
||
$ref = $request->get('ref');
|
||
|
||
$list = $model->findAll($request, $request->get('ref'));
|
||
|
||
header('Content-Type: text/csv; charset=utf-8');
|
||
header('Content-Disposition: attachment; filename='.$title.'.csv');
|
||
|
||
echo "\xEF\xBB\xBF"; //UTF-8 BOM.
|
||
|
||
$output = fopen('php://output', 'w');
|
||
if (is_resource($output)) {
|
||
foreach ($list as $row) {
|
||
fputcsv($output, (array)$row,';');
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Удаление строк из таблицы
|
||
*/
|
||
public function actionDelete(HttpRequest $request)
|
||
{
|
||
$model = $this->getModel($this->useModel);
|
||
// Почему table_item ???
|
||
$list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id');
|
||
$model->deleteList($list);
|
||
|
||
// return $this->getJSONList($model, $request);
|
||
return json_encode(array('result' => 'ok'));
|
||
}
|
||
|
||
/**
|
||
* Ответ на запрос по поиску
|
||
*/
|
||
public function actionSearch(HttpRequest $request)
|
||
{
|
||
$model = $this->getModel($this->useModel);
|
||
$model->addFilter($model->requestToSQL($request, $this->formSchema));
|
||
|
||
return $this->getJSONList($model, $request);
|
||
}
|
||
|
||
/**
|
||
* Список элементов
|
||
*/
|
||
public function actionList(HttpRequest $request)
|
||
{
|
||
$model = $this->getModel($this->useModel);
|
||
|
||
if ($request->get('filter')) {
|
||
$data = new Collection();
|
||
$data->import($request->get('filter'));
|
||
$model->addFilter($model->requestToSQL($data, $this->formSchema));
|
||
}
|
||
return $this->getJSONList($model, $request);
|
||
}
|
||
|
||
public function actionCSV(HttpRequest $request)
|
||
{
|
||
$model = $this->getModel($this->useModel);
|
||
$title = $request->get("title");
|
||
if(!$title){
|
||
$title = "noname";
|
||
}
|
||
return $this->getCSV($model, $request, $title);
|
||
}
|
||
|
||
private function setFormSchema()
|
||
{
|
||
$model = $this->getModel($this->useModel);
|
||
$ui = new Model_UIMapper($model);
|
||
|
||
$this->formSchema = $ui->getFormSchema();
|
||
}
|
||
|
||
/**
|
||
* Сохранение формы
|
||
*/
|
||
function beforeSave(/*Model*/ $item, HttpRequest $request)
|
||
{
|
||
if (empty($this->formSchema)) {
|
||
$this->setFormSchema();
|
||
}
|
||
// Сделать отображение Формы в обьект и обратно
|
||
foreach ($this->formSchema as $key => $conv) {
|
||
list($value, $type) = $conv;
|
||
$item->$value = call_user_func(array('Primitive', 'to_' . $type), $request->get($key)); // Здесь нужно преобразовывать тип значения
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обновление формы
|
||
*/
|
||
function formUpdate(Form_Form $form, HttpRequest $request) {
|
||
$form->setValues($request);
|
||
}
|
||
|
||
/**
|
||
* Загрузка формы
|
||
*/
|
||
function beforeLoad(/*.Model_Model.*/$item, Form_Form $form)
|
||
{
|
||
if (empty($this->formSchema)) {
|
||
$this->setFormSchema();
|
||
}
|
||
// Вставка значений из данных в форму
|
||
// Отображение обьекта в поля формы
|
||
$form->fill($item, $this->formSchema);
|
||
}
|
||
|
||
function beforeFirstLoad(Form_Form $form)
|
||
{
|
||
|
||
}
|
||
|
||
// Проверка ввода
|
||
protected function validate(Validator_Validator $validator, Collection $request)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* Действие для проверки формы
|
||
*/
|
||
public function actionValidate($request)
|
||
{
|
||
$validator = new Validator_Validator();
|
||
$validator->addRuleList($this->schema);
|
||
|
||
// Действия до проверки формы
|
||
$this->validate($validator, $request); // <--|
|
||
$validator->validate($request); // --|
|
||
// Проверка формы
|
||
if (!$validator->isValid()) {
|
||
return json_encode($validator->getErrorMsg());
|
||
}
|
||
return json_encode(true);
|
||
}
|
||
|
||
/**
|
||
* Инициализация формы
|
||
*/
|
||
protected function formSetup(Form_Form $form, $id = null, $ref = null)
|
||
{
|
||
if (empty($this->schema)) {
|
||
$model = $this->getModel($this->useModel);
|
||
$ui = new Model_UIMapper($model);
|
||
$schema = $ui->getEditSchema();
|
||
|
||
$form->addFieldList($schema);
|
||
} else {
|
||
$form->addFieldList($this->schema);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Добавление
|
||
*/
|
||
public function actionAdd(HttpRequest $request)
|
||
{
|
||
// {{{ тоже может быть один ref или несколько
|
||
$ref = $request->get('ref');
|
||
$this->addParameter('ref', $ref); // Добавляет параметр в url
|
||
/// }}}
|
||
|
||
// Проверка
|
||
$validator = new Validator_Validator();
|
||
$validator->addRuleList($this->schema);
|
||
|
||
// Действия до проверки формы
|
||
$this->validate($validator, $request); // <--|
|
||
$validator->validate($request); // --|
|
||
// Проверка формы
|
||
if (!$validator->isValid()) {
|
||
return json_encode(array('result'=>'fail','errors'=>$validator->getErrorMsg()));
|
||
}
|
||
// Нужен тест для формы
|
||
$model = $this->getModel($this->useModel);
|
||
$className = $model->className;
|
||
$item = new $className();
|
||
|
||
// Сохраняем значение в базе данных
|
||
$item->id = $request->get('id');
|
||
// Если таблица связана с другой таблицей
|
||
if ($request->get('ref') && $model->reference[1]) {
|
||
$ref_id = $model->reference[1];
|
||
$item->$ref_id = $request->get('ref');
|
||
}
|
||
|
||
// Подготовка к сохранению
|
||
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
|
||
// nextId ??? или выход или новая форма для создания новости
|
||
|
||
$id = $model->saveDB($item, $request);
|
||
|
||
// Для страницы со списком id -> идентификатор родительской таблицы !!??
|
||
// $request->set('id', $request->get('ref'));
|
||
if ($request->get('apply')) {
|
||
$request->setAction('form');
|
||
return (string) $this->forward('actionForm', $request);
|
||
}
|
||
//$request->setAction('index');
|
||
$result = array('result'=>'ok');
|
||
if($id){
|
||
$result['action'] = forceUrl($this->nUrl('add', array('id' => $id, 'ref' => $request->get('ref'))));
|
||
}
|
||
return json_encode($result);
|
||
}
|
||
|
||
/**
|
||
* Заголовок
|
||
*/
|
||
private function setTitlePath($ref)
|
||
{
|
||
if ($ref) {
|
||
$model = $this->getModel($this->useModel);
|
||
if (is_array($model->reference) && $model->reference[0]) {
|
||
$refmodel = $this->getModel($model->reference[0]);
|
||
try {
|
||
$parent = $refmodel->findById($ref);
|
||
$this->path->addTitle($parent->getTitle()); // Заголовок к подписям путей
|
||
} catch (Exception $e) {
|
||
// Не найден заголовок потому что неправильно определен родительский элемент
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Форма для редактирования
|
||
*/
|
||
public function actionForm(HttpRequest $request)
|
||
{
|
||
$this->getActionPath($request);
|
||
$ref = $request->get('ref');
|
||
$this->addParameter('ref', $ref); // Добавляет параметр в url
|
||
$this->setTitlePath($ref);
|
||
|
||
$model = $this->getModel($this->useModel);
|
||
$form = new Form_Form(); // Показываем форму
|
||
$form->header = 'Редактирование записи';
|
||
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
|
||
|
||
$list = $request->get('table_item');
|
||
$id = ($list[0]) ? $list[0] : $request->get('id');
|
||
//
|
||
$tpl = $this->formPage($form, $request);
|
||
if ($id) { // Редактирование
|
||
$form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Свойство формы
|
||
$item = $model->findById($id);
|
||
// Загрузка формы
|
||
$this->beforeLoad($item, $form);
|
||
}else{//Создание нового элемента
|
||
$this->beforeFirstLoad($form);
|
||
}
|
||
return json_encode($tpl);
|
||
}
|
||
|
||
/**
|
||
*/
|
||
function tableSetup(Widgets_ListTable $table, $id = null, $ref = null)
|
||
{
|
||
// FIXME: После замены везде $tableSchema -> table->setHeader удалить!
|
||
if ($this->tableSchema) {
|
||
$table->setHeader($this->tableSchema);
|
||
} else {
|
||
// Настройка таблицы отображения по схеме данных
|
||
$model = $this->getModel($this->useModel);
|
||
$ui = new Model_UIMapper($model);
|
||
$ui->hidden = $table->hidden;
|
||
|
||
$schema = $ui->getTableSchema();
|
||
$schema[0]['action'] = forceUrl($table->getFirstItem());
|
||
|
||
$table->setHeader($schema);
|
||
}
|
||
}
|
||
|
||
/**
|
||
*/
|
||
public function actionDefault(HttpRequest $request)
|
||
{
|
||
$this->getActionPath($request, 'index');
|
||
// Такое мета действие наверное можно вынести в отдельный класс
|
||
return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list'));
|
||
}
|
||
|
||
/**
|
||
* Страница по умолчанию
|
||
*/
|
||
public function metaActionIndex(HttpRequest $request, $setup, $list)
|
||
{
|
||
// может быть одно ref или несколько
|
||
// {{{ история переходов
|
||
$ref = null;
|
||
if ($request->get('ref')) {
|
||
$ref = $request->get('ref');
|
||
} else if ($request->session()->get('ref')) {
|
||
$ref = $request->session()->get('ref');
|
||
}
|
||
|
||
$request->session()->set('ref', $ref);
|
||
$this->addParameter('ref', $ref);
|
||
// }}}
|
||
$this->setTitlePath($ref);
|
||
|
||
$tpl = new stdClass();
|
||
|
||
// Помощники действий
|
||
$this->callHelpers($request);
|
||
// Таблица
|
||
if ($request->session()->get(strtolower(get_class($this)))) {
|
||
$session = $request->session()->get(strtolower(get_class($this)));
|
||
if (isset($session['view'])) {
|
||
$this->table->setView($session['view']);
|
||
}
|
||
$this->table->setData('state', array(
|
||
'page' => $session['page'],
|
||
'size' => $session['size'],
|
||
'desc' => $session['desc']));
|
||
|
||
//$this->table->setData('sorter', $session['key']);
|
||
if (isset($session['desc'])) {
|
||
$this->table->setData('desc', $session['desc']);
|
||
}
|
||
}
|
||
|
||
call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Эквивалент formSetup
|
||
$this->table->setAction($list);
|
||
if (!$this->table->getData('module')) {
|
||
$this->table->setData('module', strtolower($this->useModel));
|
||
}
|
||
$tpl->menu_path = $this->path->getItems();
|
||
|
||
$this->table->makeData();
|
||
$tpl->table = array('data' => $this->table->data);
|
||
$tpl->menu = $this->menu->menu->getItems();
|
||
$tpl->path = $this->path->getItems();
|
||
|
||
return json_encode($tpl);
|
||
}
|
||
|
||
/**
|
||
*/
|
||
public function actionSetup(HttpRequest $request) {
|
||
$left = explode(",", $request->get('left'));
|
||
$right = explode(",", $request->get('right'));
|
||
|
||
$request->session()->set(strtolower(get_class($this)),
|
||
array('view' => array('left' => $left, 'right' => $right), 'page' => 1, 'size' => 0, 'desc' => 'asc', 'key' => false));
|
||
|
||
return $this->forward('actionIndex', $request);
|
||
}
|
||
|
||
/**
|
||
*/
|
||
protected function formPage($form, $request, $template = 'form') {
|
||
$view = new stdClass();//$this->getView($template);
|
||
$view->form = $form;
|
||
$form->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Действие для формы
|
||
|
||
$view->path = $this->path->getItems();
|
||
$view->back = $this->path->getPrev();
|
||
return $view;
|
||
}
|
||
|
||
function _getActionPath() {
|
||
return new Controller_State('index');
|
||
}
|
||
|
||
// Тоже убрать в метод Controller_Model
|
||
function getActionPath(HttpRequest $request, $action = null) {
|
||
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
|
||
}
|
||
|
||
|
||
function parse_params($expression) {
|
||
$expression = htmlspecialchars_decode($expression);
|
||
$offset = strpos($expression, '?');
|
||
$url = parse_url($expression);
|
||
|
||
$arguments = array();
|
||
if ($offset === false) {
|
||
$path = $expression;
|
||
} else if (is_int($offset)) {
|
||
$path = substr($expression, 0, $offset);
|
||
$query = substr($expression, $offset+1);
|
||
parse_str($query, $arguments);
|
||
}
|
||
return $arguments;
|
||
}
|
||
|
||
public function actionFormPage(HttpRequest $request) {
|
||
//$tpl = $this->getView('formpage', 'View_Top');
|
||
|
||
$view = $this->getView('formpage', 'View_Top');
|
||
|
||
$params = $this->parse_params($request->get('params'));
|
||
|
||
|
||
// $model = $this->getModel($this->useModel);
|
||
$form = new Form_Form(); // Показываем форму
|
||
$form->header = 'Редактирование записи';
|
||
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Инициализация формы
|
||
/*
|
||
$ui = new Model_UIMapper($model);
|
||
$schema = $ui->getEditSchema();
|
||
$form->addFieldList($schema);
|
||
*/
|
||
|
||
$list = $request->get('table_item');
|
||
$id = ($list[0]) ? $list[0] : $request->get('id');
|
||
|
||
// $tpl = $this->formPage($form, $request);
|
||
|
||
$view->setView('form', $form);
|
||
$view->action = forceUrl($this->nUrl('addpage', array('ref' => $params['id']))); // Действие для формы
|
||
|
||
// $view->menu_path = $this->path->getItems();
|
||
$view->back = '';
|
||
return $view;
|
||
|
||
// return $tpl;
|
||
}
|
||
|
||
/* Для поддержки редактрования на сайте */
|
||
public function actionAddPage(HttpRequest $request)
|
||
{
|
||
// {{{ тоже может быть один ref или несколько
|
||
$ref = $request->get('ref');
|
||
$this->addParameter('ref', $ref); // Добавляет параметр в url
|
||
/// }}}
|
||
$validator = new Validator_Validator();
|
||
$validator->addRuleList($this->schema);
|
||
|
||
// Действия до проверки формы
|
||
$this->validate($validator, $request); // <--|
|
||
$validator->validate($request); // --|
|
||
// Проверка формы
|
||
if (!$validator->isValid()) {
|
||
return $validator;
|
||
}
|
||
|
||
// Нужен тест для формы
|
||
$model = $this->getModel($this->useModel);
|
||
$className = $model->className;
|
||
$item = new $className();
|
||
|
||
// Сохраняем значение в базе данных
|
||
$item->id = $request->get('id');
|
||
// Если таблица связана с другой таблицей
|
||
if ($request->get('ref') && $model->reference[1]) {
|
||
$ref_id = $model->reference[1];
|
||
$item->$ref_id = $request->get('ref');
|
||
}
|
||
|
||
// Подготовка к сохранению
|
||
$this->beforeSave($item, $request); // Сюдаже и истрия переходов
|
||
$model->saveDB($item, $request);
|
||
|
||
return null;
|
||
}
|
||
}
|