OrigamiStructures / StudioManagerScratch

A place to push around some experimental code
0 stars 0 forks source link

Prefs system is a REPL-local stub #170

Closed dreamingmind closed 4 years ago

dreamingmind commented 4 years ago

Discussion and a plan required.

This system works, but needs to be generalized.

It is currently local to addressbook/index. It uses hard-coded ctp logic, the PreferencesHelper has one specific method and the setPrefs() call is local to this one controller.

dreamingmind commented 4 years ago

Progress

This is improving. The setPrefs() call point is now in the PreferencesController and some tasks are delegated to PreferencesComponent.

The Component provides a variety of services to Controllers that need to respond to user prefs. But perhaps the setPrefs code could all move up to the Controller?

Other issues included clumsy and coupled rendering code and a need for a growing number of variables on any page that wanted to provide forms for user prefs UI.

On a horse in the middle of a stream

I expect there to be several different prefs forms:

And within each form type I expect the available fields to vary. For example, pagination prefs on a Person page would allow first or last name sorting. But a category page would only allow name sorting. An artwork index page would allow recent activity or title sorting.

But, despite these differences, 'limit' is an option in every case.

So, how to keep these dry and flexible both, without putting a heavy set-up burden on the many controller actions... And keep things from getting too magical. A real needle to thread.

Current pattern

As of today, there is PreferencesComponent::includePrefsViewBundle($user_id) that a controller method to prepare variables for the view.

And I have the beginnings of an element pattern. The hard coded stuff and helper+element mess has been eliminated.

Variables for the view

I'm thinking the component call can be improved by making it return a single object rather than two objects on separate variables (Form and Entity). The Form is required to return version of itself at various stages of rendering and requires a user-id to produce it.

So the rendering is still pretty coupled as it requires 3 separate named variables.

Once the controller is done, the user id never changes, both versions of the Form and the Entity can be bundled into a single object with a simple interface.

or

The PreferencesComponent::includePrefsViewBundle($user_id) call could easily prepare the object and we would have an object with a know interface rather that a couple of object variables that depended on input params to produce proper results.

Elements

To make the elements algorithm-derived...

The pagination.ctp has all the common parts of a form and allows insertion of person or category unique parts.

If the Prefs object could deliver the variant name that applied to the current request, the forms could self assemble using this value.

That would put one more param on the call PreferencesComponent::includePrefsViewBundle($user_id, variant)

I don't know if this simple pattern based on the needs of the pagination preference form would hold for other categories of prefs. And the goal is to make an easy-to-grow system.

The way I hope this system would play out:

//in a template .ctp
echo 'some stuff'
echo $this->element($UserPrefs->form('Pagination');
echo 'more stuff'

If the UserPrefs object had been front loaded with 'person', it could get the right element if the elements followed a pattern like this:


<?php
//Elements/Pagination/person.ctp

use App\Form\PrefCon;
/* @var \App\View\AppView $this */

//Here a view block is prepared. It contains the variant specific inputs
$this->start('pagination_sort_preference_control');
echo $this->Form->control(
    PrefCon::PAGINATION_SORT_PEOPLE, [
    'options' => $prefsForm->asContext($prefs->user_id)->selectList(PrefCon::PAGINATION_SORT_PEOPLE),]);
$this->end();

//Here the Form is output. It will fetch the prepared view block
echo $this->element('pagination');
?>

<?php
//Elements/Pagination/pagination.ctp

use App\Form\PrefCon;
/**
 * @var \App\View\AppView $this
 * @var \App\Form\LocalPreferencesForm $prefsForm
 * @var \App\Model\Entity\Preference $prefs
 */

echo $this->Form->create($prefsForm->asContext($prefs->user_id), [
    'url' => ['controller' => 'preferences', 'action' => 'setPrefs']
]);
echo $this->Html->tag(
    'ul',
    '<li>' .
    $this->Form->control(PrefCon::PAGINATION_LIMIT) .
    '</li>' .
    '<li>' .
    //Here the view block of variant specific inputs are inserted
    $this->fetch('pagination_sort_preference_control') .
    '</li>',
    ['class' => 'menu']
);
echo $this->Form->control('id', ['type' => 'hidden']);
echo $this->Form->submit();
echo $this->Form->end();
dreamingmind commented 4 years ago

This system is still evolving but it is now encapsulated and that was the main issue