Commit 618398f6 authored by Yohan Liebart's avatar Yohan Liebart
Browse files

Partie 3 terminée : Tree Behaviour

parent 6494ba05
This diff is collapsed.
<?php
use Migrations\AbstractMigration;
class CreateArticles extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* @return void
*/
public function change()
{
$table = $this->table('articles');
$table->addColumn('title', 'string', [
'default' => null,
'limit' => 255,
'null' => false,
]);
$table->addColumn('body', 'text', [
'default' => null,
'null' => false,
]);
$table->addColumn('category_id', 'integer', [
'default' => null,
'limit' => 11,
'null' => false,
]);
$table->addColumn('created', 'datetime', [
'default' => null,
'null' => false,
]);
$table->addColumn('modified', 'datetime', [
'default' => null,
'null' => false,
]);
$table->create();
}
}
<?php
use Migrations\AbstractMigration;
class CreateCategories extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* @return void
*/
public function change()
{
$table = $this->table('categories');
$table->addColumn('parent_id', 'integer', [
'default' => null,
'limit' => 11,
'null' => true,
]);
$table->addColumn('lft', 'integer', [
'default' => null,
'limit' => 10,
'null' => false,
]);
$table->addColumn('rght', 'integer', [
'default' => null,
'limit' => 10,
'null' => false,
]);
$table->addColumn('name', 'string', [
'default' => null,
'limit' => 100,
'null' => false,
]);
$table->addColumn('description', 'string', [
'default' => null,
'limit' => 255,
'null' => false,
]);
$table->addColumn('created', 'datetime', [
'default' => null,
'null' => false,
]);
$table->addColumn('modified', 'datetime', [
'default' => null,
'null' => false,
]);
$table->create();
}
}
......@@ -13,6 +13,7 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// You can remove this if you are confident that your PHP version is sufficient.
if (version_compare(PHP_VERSION, '5.6.0') < 0) {
trigger_error('Your PHP version must be equal or higher than 5.6.0 to use CakePHP.', E_USER_ERROR);
......@@ -219,4 +220,5 @@ Type::build('timestamp')
*/
if (Configure::read('debug')) {
Plugin::load('DebugKit', ['bootstrap' => true]);
Plugin::load('Migrations');
}
......@@ -23,6 +23,7 @@ class ArticlesController extends AppController
public function add()
{
$article = $this->Articles->newEntity();
if ($this->request->is('post')) {
$article = $this->Articles->patchEntity($article, $this->request->getData());
......@@ -33,7 +34,7 @@ class ArticlesController extends AppController
//$article = $this->Articles->patchEntity($article, $newData);
if ($this->Articles->save($article)) {
$this->Flash->success(__('Your article has been saved.'));
return $this->redirect(['action' => 'index']);
return $this->redirect(['controller' => 'Categories', 'action' => 'index']);
}
$this->Flash->error(__('Unable to add your article.'));
}
......@@ -43,6 +44,7 @@ class ArticlesController extends AppController
// one category for an article
$categories = $this->Articles->Categories->find('treeList');
$this->set(compact('categories'));
}
public function edit($id = null)
......@@ -58,6 +60,8 @@ class ArticlesController extends AppController
}
$this->set('article', $article);
}
public function delete($id)
......
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* Categories Controller
*
* @property \App\Model\Table\CategoriesTable $Categories
*/
class CategoriesController extends AppController
{
/**
* Index method
*
* @return \Cake\Network\Response|null
*/
public function index()
{
$this->paginate = [
'contain' => ['ParentCategories']
];
$categories = $this->paginate($this->Categories);
$this->set(compact('categories'));
$this->set('_serialize', ['categories']);
}
public function moveUp($id = null)
{
$this->request->allowMethod(['post', 'put']);
$category = $this->Categories->get($id);
if ($this->Categories->moveUp($category)) {
$this->Flash->success('The category has been moved Up.');
} else {
$this->Flash->error('The category could not be moved up. Please, try again.');
}
return $this->redirect($this->referer(['action' => 'index']));
}
public function moveDown($id = null)
{
$this->request->allowMethod(['post', 'put']);
$category = $this->Categories->get($id);
if ($this->Categories->moveDown($category)) {
$this->Flash->success('The category has been moved down.');
} else {
$this->Flash->error('The category could not be moved down. Please, try again.');
}
return $this->redirect($this->referer(['action' => 'index']));
}
/**
* View method
*
* @param string|null $id Category id.
* @return \Cake\Network\Response|null
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$category = $this->Categories->get($id, [
'contain' => ['ParentCategories', 'Articles', 'ChildCategories']
]);
$this->set('category', $category);
$this->set('_serialize', ['category']);
}
/**
* Add method
*
* @return \Cake\Network\Response|null Redirects on successful add, renders view otherwise.
*/
public function add()
{
$category = $this->Categories->newEntity();
if ($this->request->is('post')) {
$category = $this->Categories->patchEntity($category, $this->request->getData());
if ($this->Categories->save($category)) {
$this->Flash->success(__('The category has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The category could not be saved. Please, try again.'));
}
$parentCategories = $this->Categories->ParentCategories->find('list', ['limit' => 200]);
$this->set(compact('category', 'parentCategories'));
$this->set('_serialize', ['category']);
}
/**
* Edit method
*
* @param string|null $id Category id.
* @return \Cake\Network\Response|null Redirects on successful edit, renders view otherwise.
* @throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$category = $this->Categories->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$category = $this->Categories->patchEntity($category, $this->request->getData());
if ($this->Categories->save($category)) {
$this->Flash->success(__('The category has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The category could not be saved. Please, try again.'));
}
$parentCategories = $this->Categories->ParentCategories->find('list', ['limit' => 200]);
$this->set(compact('category', 'parentCategories'));
$this->set('_serialize', ['category']);
}
/**
* Delete method
*
* @param string|null $id Category id.
* @return \Cake\Network\Response|null Redirects to index.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$category = $this->Categories->get($id);
if ($this->Categories->delete($category)) {
$this->Flash->success(__('The category has been deleted.'));
} else {
$this->Flash->error(__('The category could not be deleted. Please, try again.'));
}
return $this->redirect(['action' => 'index']);
}
}
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* Category Entity
*
* @property int $id
* @property int $parent_id
* @property int $lft
* @property int $rght
* @property string $name
* @property string $description
* @property \Cake\I18n\Time $created
* @property \Cake\I18n\Time $modified
*
* @property \App\Model\Entity\ParentCategory $parent_category
* @property \App\Model\Entity\Article[] $articles
* @property \App\Model\Entity\ChildCategory[] $child_categories
*/
class Category extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'*' => true,
'id' => false
];
}
......@@ -17,6 +17,9 @@ class ArticlesTable extends Table
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
]);
}
public function validationDefault(Validator $validator)
......
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Categories Model
*
* @property \Cake\ORM\Association\BelongsTo $ParentCategories
* @property \Cake\ORM\Association\HasMany $Articles
* @property \Cake\ORM\Association\HasMany $ChildCategories
*
* @method \App\Model\Entity\Category get($primaryKey, $options = [])
* @method \App\Model\Entity\Category newEntity($data = null, array $options = [])
* @method \App\Model\Entity\Category[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Category|bool save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Category patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\Category[] patchEntities($entities, array $data, array $options = [])
* @method \App\Model\Entity\Category findOrCreate($search, callable $callback = null, $options = [])
*
* @mixin \Cake\ORM\Behavior\TimestampBehavior
* @mixin \Cake\ORM\Behavior\TreeBehavior
*/
class CategoriesTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('categories');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->addBehavior('Tree');
$this->belongsTo('ParentCategories', [
'className' => 'Categories',
'foreignKey' => 'parent_id'
]);
$this->hasMany('Articles', [
'foreignKey' => 'category_id'
]);
$this->hasMany('ChildCategories', [
'className' => 'Categories',
'foreignKey' => 'parent_id'
]);
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->requirePresence('name', 'create')
->notEmpty('name');
$validator
->requirePresence('description', 'create')
->notEmpty('description');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['parent_id'], 'ParentCategories'));
return $rules;
}
}
......@@ -2,9 +2,11 @@
<h1>Add Article</h1>
<?php
echo $this->Form->create($article);
echo $this->Form->input('title');
echo $this->Form->input('body', ['rows' => '3']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
echo $this->Form->create($article);
// just added the categories input
echo $this->Form->input('category_id');
echo $this->Form->input('title');
echo $this->Form->input('body', ['rows' => '3']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
?>
\ No newline at end of file
<?php
/**
* @var \App\View\AppView $this
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Categories'), ['action' => 'index']) ?></li>
<li><?= $this->Html->link(__('List Parent Categories'), ['controller' => 'Categories', 'action' => 'index']) ?></li>
<li><?= $this->Html->link(__('New Parent Category'), ['controller' => 'Categories', 'action' => 'add']) ?></li>
<li><?= $this->Html->link(__('List Articles'), ['controller' => 'Articles', 'action' => 'index']) ?></li>
<li><?= $this->Html->link(__('New Article'), ['controller' => 'Articles', 'action' => 'add']) ?></li>
</ul>
</nav>
<div class="categories form large-9 medium-8 columns content">
<?= $this->Form->create($category) ?>
<fieldset>
<legend><?= __('Add Category') ?></legend>
<?php
echo $this->Form->control('parent_id', ['options' => $parentCategories, 'empty' => 'No parent category']);
echo $this->Form->control('name');
echo $this->Form->control('description');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
<?php
/**
* @var \App\View\AppView $this
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', $category->id],
['confirm' => __('Are you sure you want to delete # {0}?', $category->id)]
)
?></li>
<li><?= $this->Html->link(__('List Categories'), ['action' => 'index']) ?></li>
<li><?= $this->Html->link(__('List Parent Categories'), ['controller' => 'Categories', 'action' => 'index']) ?></li>
<li><?= $this->Html->link(__('New Parent Category'), ['controller' => 'Categories', 'action' => 'add']) ?></li>
<li><?= $this->Html->link(__('List Articles'), ['controller' => 'Articles', 'action' => 'index']) ?></li>
<li><?= $this->Html->link(__('New Article'), ['controller' => 'Articles', 'action' => 'add']) ?></li>
</ul>
</nav>
<div class="categories form large-9 medium-8 columns content">
<?= $this->Form->create($category) ?>
<fieldset>
<legend><?= __('Edit Category') ?></legend>
<?php
echo $this->Form->control('parent_id', ['options' => $parentCategories, 'empty' => 'No parent category']);
echo $this->Form->control('name');
echo $this->Form->control('description');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
<?php
/**
* @var \App\View\AppView $this
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('New Category'), ['action' => 'add']) ?></li>
<li><?= $this->Html->link(__('List Articles'), ['controller' => 'Articles', 'action' => 'index']) ?></li>
<li><?= $this->Html->link(__('New Article'), ['controller' => 'Articles', 'action' => 'add']) ?></li>
</ul>
</nav>
<div class="categories index large-9 medium-8 columns content">
<h3><?= __('Categories') ?></h3>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th scope="col"><?= $this->Paginator->sort('id') ?></th>
<th scope="col"><?= $this->Paginator->sort('parent_id') ?></th>
<th scope="col"><?= $this->Paginator->sort('name') ?></th>
<th scope="col"><?= $this->Paginator->sort('description') ?></th>
<th scope="col"><?= $this->Paginator->sort('created') ?></th>
<th scope="col"><?= $this->Paginator->sort('modified') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($categories as $category): ?>
<tr>
<td><?= $this->Number->format($category->id) ?></td>
<td><?= $category->has('parent_category') ? $this->Html->link($category->parent_category->name, ['controller' => 'Categories', 'action' => 'view', $category->parent_category->id]) : '' ?></td>
<td><?= h($category->name) ?></td>
<td><?= h($category->description) ?></td>
<td><?= h($category->created) ?></td>
<td><?= h($category->modified) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $category->id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $category->id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $category->id], ['confirm' => __('Are you sure you want to delete # {0}?', $category->id)]) ?>
<?= $this->Form->postLink(__('Move down'), ['action' => 'moveDown', $category->id], ['confirm' => __('Are you sure you want to move down # {0}?', $category->id)]) ?>
<?= $this->Form->postLink(__('Move up'), ['action' => 'moveUp', $category->id], ['confirm' => __('Are you sure you want to move up # {0}?', $category->id)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
</div>
</div>
<?php
/**
* @var \App\View\AppView $this
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('Edit Category'), ['action' => 'edit', $category->id]) ?> </li>
<li><?= $this->Form->postLink(__('Delete Category'), ['action' => 'delete', $category->id], ['confirm' => __('Are you sure you want to delete # {0}?', $category->id)]) ?> </li>
<li><?= $this->Html->link(__('List Categories'), ['action' => 'index']) ?> </li>
<li><?= $this->Html->link(__('New Category'), ['action' => 'add']) ?> </li>
<li><?= $this->Html->link(__('List Parent Categories'), ['controller' => 'Categories', 'action' => 'index']