Skip to content

Commit

Permalink
Merge pull request #6 from fr3nch13/dev
Browse files Browse the repository at this point in the history
Adding controller traits and tests for them.
  • Loading branch information
fr3nch13 committed Mar 3, 2023
2 parents 8987146 + 5278897 commit 11f80ee
Show file tree
Hide file tree
Showing 22 changed files with 1,059 additions and 15 deletions.
1 change: 1 addition & 0 deletions config/Migrations/00000000000001_InitialMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function change(): void
$table->addColumn('name', 'string', ['length' => '255'])
->addColumn('slug', 'string', ['length' => '255', 'null' => true])
->addColumn('updateme', 'string', ['length' => '255', 'null' => true])
->addColumn('alive', 'boolean', ['default' => 1])
->create();

$table = $this->table('courses_students');
Expand Down
52 changes: 52 additions & 0 deletions src/Controller/AppController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);

/**
* AppController
*/

namespace Fr3nch13\Utilities\Controller;

use Cake\View\JsonView;

/**
* App Controller
*
* @property \Cake\Controller\Component\RequestHandlerComponent $RequestHandler
* @property \Cake\Controller\Component\FlashComponent $Flash
*/

class AppController extends \Cake\Controller\Controller
{
/**
* Sets what classes this controller uses.
*
* @return array<string>
*/
public function viewClasses(): array
{
return [JsonView::class];
}

/**
* Figures out the referer with a given default.
*
* @param mixed|null $referer the default referer.
* @return mixed The determined referer to use.
*/
public function getReferer($referer = null)
{
if (!$referer) {
$referer = $this->getRequest()->referer();
}

if ($this->getRequest()->getQuery('referer')) {
$referer = $this->getRequest()->getQuery('referer');
if (is_string($referer) && strpos($referer, '%') !== false) {
$referer = urldecode($referer);
}
}

return $referer;
}
}
48 changes: 48 additions & 0 deletions src/Controller/CoursesController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);

/**
* CoursesController
*/

namespace Fr3nch13\Utilities\Controller;

use Cake\Core\Configure;

/**
* Courses Controller
*
* Used to test the Controller Toggle Trait.
*
* @property \Cake\Controller\Component\RequestHandlerComponent $RequestHandler
* @property \Fr3nch13\Utilities\Model\Table\CoursesTable $Courses
*/
class CoursesController extends AppController
{
use MergeDeleteTrait;
use ToggleTrait;

/**
* Setup stuff for the actions to use
*
* @return void
*/
public function initialize(): void
{
parent::initialize();
if (Configure::check('LoadFlash') && Configure::read('LoadFlash')) {
$this->loadComponent('Flash');
}
}

/**
* Index method
*
* @return void
*/
public function index(): void
{
$courses = $this->Courses->find('all')->all();
$this->set(compact('courses'));
}
}
79 changes: 79 additions & 0 deletions src/Controller/FuModelFindTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);

/**
* FuModelFindTrait
*/

namespace Fr3nch13\Utilities\Controller;

use Cake\Core\Configure;
use Cake\Http\Exception\NotFoundException;

trait FuModelFindTrait
{
/**
* The name of the model we're using, if it's not set,
* then it'll use the name of the controller, to try to figure it out.
*
* @var null|string The name of the model.
*/
public $fuModel = null;

/**
* @var null|string The model alias to use.
*/
public $fuModelAlias = null;

/**
* Used to find the model for the other taits here.
* @return void
*/
public function traitModelFind(): void
{
// try to figure out what model to use from the controller name.
if (!$this->fuModel) {
$this->fuModel = $this->defaultTable;
// used for testing but should be set in the controller, not through Configure.
if (Configure::check('fuModel')) {
$this->fuModel = Configure::read('fuModel');
}
}

// If we're in a plugin, see if we can load the overloaded model from the app, if it exists.
// This is incase there are other relationships we need to account for.
$this->fuModelAlias = $this->fuModel;
if (strpos($this->fuModel, '.') !== false) {
$parts = explode('.', $this->fuModel);
$this->fuModelAlias = array_pop($parts);
// thows an exception if TableLocator::allowFallbackClass(false)
try {
$table = $this->fetchTable($this->fuModelAlias);
if (get_class($table) != 'Cake\ORM\Table') {
$this->{$this->fuModelAlias} = $table;
}
} catch (\Exception $e) {
// pass
}
}

// if it wasn't found as a model in app (aka, not overloaded), then use the plugin model.
if (!isset($this->{$this->fuModelAlias})) {
try {
$this->{$this->fuModelAlias} = $this->fetchTable($this->fuModel);
} catch (\Exception $e) {
// pass
}
}

// if we can't figure it out, throw an error to the user.
// This looks for CahePHP's autoloading of tables.
if (!isset($this->{$this->fuModelAlias}) || get_class($this->{$this->fuModelAlias}) == 'Cake\ORM\Table') {
throw new NotFoundException(__('Unable to find the model `{0}` (alias:{1}) to use to toggle.', [
$this->fuModel,
$this->fuModelAlias,
]));
}
}
}
99 changes: 99 additions & 0 deletions src/Controller/MergeDeleteTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);

/**
* MergeDeleteTrait
*/

namespace Fr3nch13\Utilities\Controller;

use Cake\Core\Configure;
use Cake\Http\Exception\NotFoundException;

/**
* Merge/Delete Trait
*
* Common methods merging one record into another, then deleting the first record.
*/
trait MergeDeleteTrait
{
use FuModelFindTrait;

/**
* The merge-delete display field of the model.
* Can be either real, or virtual.
*
* @var null|string
*/
public $mdDisplayField = null;

/**
* Allows to merge associated records from one attribute to another, then delete the old record.
*
* @param int $sourceId The record id to delete.
* @return \Cake\Http\Response|null
* @throws \Cake\Http\Exception\NotFoundException When record not found.
*/
public function mergeDelete($sourceId): ?\Cake\Http\Response
{
$this->traitModelFind();

try {
$sourceRecord = $this->{$this->fuModelAlias}->get($sourceId);
} catch (\Exception $e) {
throw new NotFoundException(__('Unable to find the old record to merge/delete.'));
}

if ($this->getRequest()->is(['patch', 'post', 'put'])) {
$data = $this->getRequest()->getData();

if (!isset($data['id']) || !$data['id']) {
throw new NotFoundException(__('No new record was selected.'));
}
if (is_string($data['id'])) {
$data['id'] = intval($data['id']);
}

try {
$result = $this->{$this->fuModelAlias}->mergeDelete($sourceRecord->get('id'), $data['id']);
if ($result) {
$this->Flash->success(__('The Old record has been merged into the new record, and deleted.'));
$redirect = ['action' => 'index'];
if (isset($data['referer'])) {
$redirect = $data['referer'];
}

return $this->redirect($redirect);
}
} catch (\Exception $e) {
throw new NotFoundException(__('Unable to merge the old record into ' .
'the new record. Ensure both records exist.'));
}
}

$displayField = $this->{$this->fuModelAlias}->getDisplayField();
// used for testing but should be set in the controller, not through Configure.
if (Configure::check('mdDisplayField')) {
$this->mdDisplayField = Configure::read('mdDisplayField');
}

if ($this->mdDisplayField) {
$displayField = $this->mdDisplayField;
}

$records = $this->{$this->fuModelAlias}->find('mergeRecords', [
'sourceId' => $sourceRecord->get('id'),
'displayField' => $displayField,
]);
$stats = $this->{$this->fuModelAlias}->getMergeStats($sourceRecord->get('id'));

$this->set([
'sourceRecord' => $sourceRecord,
'displayField' => $displayField,
'records' => $records,
'stats' => $stats,
]);

return null;
}
}

0 comments on commit 11f80ee

Please sign in to comment.