Plugin Directory

Changeset 3394866


Ignore:
Timestamp:
11/13/2025 09:25:06 AM (4 months ago)
Author:
plainware
Message:

2.0.5

Location:
plain-event-calendar/trunk
Files:
56 added
17 deleted
96 edited

Legend:

Unmodified
Added
Removed
  • plain-event-calendar/trunk/include-wp.php

    r3372822 r3394866  
    44'vendor/plainware/database-wordpress',
    55'vendor/plainware/ui-wordpress',
     6'vendor/plainware/http-wordpress',
    67];
  • plain-event-calendar/trunk/include.php

    r3372822 r3394866  
    44'vendor/plainware/app',
    55'vendor/plainware/http',
    6 'vendor/plainware/time',
     6'vendor/plainware/datetime',
    77'vendor/plainware/database',
    88'vendor/plainware/ui',
    99'vendor/plainware/ui-ajax',
     10'vendor/plainware/rest',
    1011'module/app',
     12'module/setting',
     13'module/rest',
    1114];
  • plain-event-calendar/trunk/module/app/boot.php

    r3372822 r3394866  
    77use Plainware\Database\Migrator;
    88use Plainware\Http\Router;
     9use Plainware\Ui\Component\Link;
     10use Plainware\Ui\PageMap;
    911use Plainware\Ui\Ui;
    1012
    11 return [
    12     App::class => function (App $app) {
    13         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    14     },
     13return function(App $app) {
     14    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    1515
    16     Migrator::class => function (Migrator $m) {
     16    $app->onBoot(Migrator::class, function ($m) {
    1717        $m
    18             ->registerMigration('setting', 1, [Repo\SettingRepo::class, 'up1'], [Repo\SettingRepo::class, 'down1'])
    19             ->registerMigration('event', 1, [Repo\EventRepo::class, 'up1'], [Repo\EventRepo::class, 'down1'])
     18            ->registerMigration('event', 1,
     19                [Database\EventDatabaseTable::class, 'up1'],
     20                [Database\EventDatabaseTable::class, 'down1']
     21            )
    2022        ;
    21     },
     23    });
    2224
    23     Ui::class => function (Ui $ui) {
     25    $app->onBoot(Ui::class, function ($ui) {
    2426        $ui
    2527            ->renderer(namespace\Model\Event::class, namespace\Ui\Renderer\EventRenderer::class)
    2628        ;
    27     },
     29    });
    2830
    29     Router::class => function (Router $router) {
     31    $app->onBoot(Router::class, function ($router) {
    3032        if (is_admin()) {
    3133            $router
    32                 ->whenNot('install')
     34                ->when('')
    3335                    ->middleware(Middleware\CheckInstallMiddleware::class, 25)
    3436                ->when('install')
     
    3739                    ->handle(Controller\UninstallController::class)
    3840
    39                 ->shortcut('', 'admin/event')
     41                ->when('')
     42                    ->shortcutTo('admin/event')
    4043
    41             /* admin/about */
    42                 ->when('')
    43                     ->meta('menu', [Controller\AboutController::class, 'addToMainMenu'])
    44                 ->when('admin/about')
    45                     ->handle(Controller\AboutController::class)
    46 
    47             /* admin/event */
    48                 ->when('')
    49                     ->meta('menu', [Controller\EventController::class, 'addToMainMenu'])
    50                 ->when('admin/event')
    51                     ->handle(Controller\EventController::class)
    52 
    53                 ->when('admin/event/create')
    54                     ->handle(Controller\EventCreateController::class)
    55                 ->when('admin/event/id')
    56                     ->handle(Controller\EventIdController::class)
    57                 ->when('admin/event/id/delete')
    58                     ->handle(Controller\EventIdDeleteController::class)
     44                ->when('admin/event')->handle(Controller\EventController::class)
     45                ->when('admin/event/create')->handle(Controller\EventCreateController::class)
     46                ->when('admin/event/{id}')->handle(Controller\EventIdController::class)
     47                ->when('admin/event/{id}/delete')->handle(Controller\EventIdDeleteController::class)
    5948                ;
    6049        } else {
    6150            $router
     51                ->when('')
     52                    ->shortcutTo('front/event')
    6253                ->when('front/event')
    6354                    ->handle(Controller\Front\EventController::class)
    64                 ->shortcut('', 'front/event')
    6555                ;
    6656        }
    67     },
     57    });
    6858
    69     CommandBus::class => function (CommandBus $b) {
    70         $b
     59    $app->onBoot(PageMap::class, function ($pageMap) {
     60        if (is_admin()) {
     61            $pageMap
     62                ->when('')
     63                    ->addMenuItem((new Link('./admin/event'))->setLabel('__Events__'))
     64                ->when('admin/event')
     65                    ->setBreadcrumbTitle('__Events__')
     66                ->when('admin/event/{id}')
     67                    ->setBreadcrumbTitle([Controller\EventIdController::class, 'title'])
     68                    ->addNavItem((new Link('./delete'))->setLabel('__Delete__')->prependIcon('×'))
     69                ;
     70        } else {
     71        }
     72    });
     73
     74    $app->onBoot(CommandBus::class, function ($commandBus) {
     75        $commandBus
    7176            ->handler(Command\CreateEvent::class, Command\Handler\CreateEventHandler::class)
    7277            ->handler(Command\UpdateEvent::class, Command\Handler\UpdateEventHandler::class)
     
    7479            ->handler(Command\DeleteEvent::class, Command\Handler\DeleteEventHandler::class)
    7580        ;
    76     },
    77 ];
     81    });
     82};
  • plain-event-calendar/trunk/module/app/src/Command/CreateEvent.php

    r3372822 r3394866  
    77class CreateEvent
    88{
    9     private int $d1;
    10     private int $d2;
     9    private \DateTimeInterface $d1;
     10    private \DateTimeInterface $d2;
    1111    private string $title = '';
    1212    private string $description = '';
    1313
    14     public function withStartDate(int $v): self
     14    public function withStartDate(\DateTimeInterface $v): self
    1515    {
    1616        $ret = clone $this;
     
    2020    }
    2121
    22     public function getStartDate(): int
     22    public function getStartDate(): \DateTimeInterface
    2323    {
    2424        return $this->d1;
    2525    }
    2626
    27     public function withEndDate(int $v): self
     27    public function withEndDate(\DateTimeInterface $v): self
    2828    {
    2929        $ret = clone $this;
     
    3333    }
    3434
    35     public function getEndDate(): int
     35    public function getEndDate(): \DateTimeInterface
    3636    {
    37         return $this->d1;
     37        return $this->d2;
    3838    }
    3939
  • plain-event-calendar/trunk/module/app/src/Command/Handler/CreateEventHandler.php

    r3372822 r3394866  
    1111class CreateEventHandler
    1212{
    13     public EventBus $eventBus;
    14     public EventRepo $repo;
     13    public $eventBus = EventBus::class;
     14    public $repo = EventRepo::class;
    1515
    1616    public function __invoke(CreateEvent $command): Event
  • plain-event-calendar/trunk/module/app/src/Command/Handler/DeleteEventHandler.php

    r3372822 r3394866  
    1010class DeleteEventHandler
    1111{
    12     public EventBus $eventBus;
    13     public EventRepo $repo;
     12    public $eventBus = EventBus::class;
     13    public $repo = EventRepo::class;
    1414
    1515    public function __invoke(DeleteEvent $command)
  • plain-event-calendar/trunk/module/app/src/Command/Handler/RescheduleEventHandler.php

    r3372822 r3394866  
    1111class RescheduleEventHandler
    1212{
    13     public EventBus $eventBus;
    14     public CommandBus $commandBus;
     13    public $eventBus = EventBus::class;
     14    public $commandBus = CommandBus::class;
    1515
    1616    public function __invoke(RescheduleEvent $command)
  • plain-event-calendar/trunk/module/app/src/Command/Handler/UpdateEventHandler.php

    r3372822 r3394866  
    1010class UpdateEventHandler
    1111{
    12     public EventBus $eventBus;
    13     public EventRepo $repo;
     12    public $eventBus = EventBus::class;
     13    public $repo = EventRepo::class;
    1414
    1515    public function __invoke(UpdateEvent $command)
  • plain-event-calendar/trunk/module/app/src/Command/RescheduleEvent.php

    r3372822 r3394866  
    88{
    99    private Event $event;
    10     private ?int $d1 = null;
    11     private ?int $d2 = null;
     10    private ?\DateTimeInterface $d1 = null;
     11    private ?\DateTimeInterface $d2 = null;
    1212
    1313    public function __construct(Event $event)
     
    2121    }
    2222
    23     public function withNewStartDate(int $v): self
     23    public function withNewStartDate(\DateTimeInterface $v): self
    2424    {
    2525        $ret = clone $this;
     
    2929    }
    3030
    31     public function withNewEndDate(int $v): self
     31    public function withNewEndDate(\DateTimeInterface $v): self
    3232    {
    3333        $ret = clone $this;
     
    3737    }
    3838
    39     public function getNewStartDate(): ?int
     39    public function getNewStartDate(): ?\DateTimeInterface
    4040    {
    4141        return $this->d1;
    4242    }
    4343
    44     public function getNewEndDate(): ?int
     44    public function getNewEndDate(): ?\DateTimeInterface
    4545    {
    4646        return $this->d2;
  • plain-event-calendar/trunk/module/app/src/Controller/AboutController.php

    r3372822 r3394866  
    1919class AboutController
    2020{
    21     public App $app;
    22     public Migrator $Migrator;
    23 
    24     public function addToMainMenu(Request $request, callable $next): Menu
    25     {
    26         $ret = $next($request);
    27 
    28         $ret
    29             ->add(85, (new Link('admin/about'))->setLabel('__About__'))
    30             ;
    31 
    32         return $ret;
    33     }
     21    public $app = App::class;
     22    public $migrator = Migrator::class;
    3423
    3524    public function __invoke(Request $request)
  • plain-event-calendar/trunk/module/app/src/Controller/EventController.php

    r3372822 r3394866  
    1111use Plainware\Ui\Component\Section;
    1212use Plainware\Ui\Component\Table;
    13 use Plainware\Time\Time;
     13use Plainware\DateTime\DateTimeFormatter;
    1414use PlainEventCalendar\App\Repo\EventRepo;
    1515
    1616class EventController
    1717{
    18     public EventRepo $repo;
    19     public Time $t;
    20 
    21     public function addToMainMenu(Request $request, callable $next): Menu
    22     {
    23         $ret = $next($request);
    24 
    25         $ret
    26             ->add(32, (new Link('admin/event'))->setLabel('__Events__'))
    27             ;
    28 
    29         return $ret;
    30     }
     18    public $repo = EventRepo::class;
     19    public $dtf = DateTimeFormatter::class;
    3120
    3221    public function __invoke(Request $request)
    3322    {
    3423        $ms = $this->repo
    35             ->orderStartDate('DESC')
     24            ->orderStartDateDesc()
    3625            ->read()
    3726            ;
     
    6655
    6756        foreach ($ms as $m) {
    68             $id = $m->id;
     57            $id = $m->getId();
    6958
    7059            $v = $m->getTitle();
    7160            $v = esc_html($v);
    72             $v = (new Link('./id', ['id' => $id]))->setLabel($v);
     61            $v = (new Link('./' . $id))->setLabel($v);
    7362            $table->withCell($id, 'title')->setContent($v);
    7463
    75             $v = $this->t->formatDateRange($m->getStartDate(), $m->getEndDate());
     64            $v = $this->dtf->formatDateRange($m->getStartDate(), $m->getEndDate());
    7665            $v = esc_html($v);
    77             $v = (new Link('./id', ['id' => $id]))->setLabel($v);
     66            $v = (new Link('./' . $id))->setLabel($v);
    7867            $table->withCell($id, 'date')->setContent($v);
    7968        }
  • plain-event-calendar/trunk/module/app/src/Controller/EventCreateController.php

    r3372822 r3394866  
    1515use Plainware\Ui\Component\Form\Button;
    1616use PlainEventCalendar\App\Command\CreateEvent;
    17 use PlainEventCalendar\App\Model\Event;
    1817
    1918class EventCreateController
    2019{
    21     public CommandBus $commandBus;
     20    public $commandBus = CommandBus::class;
    2221
    2322    public function __invoke(Request $request)
     
    6968            }
    7069
    71             $d1 = $values['d1'];
    72             $d2 = $values['d2'];
     70            $d1 = new \DateTimeImmutable($values['d1']);
     71            $d2 = new \DateTimeImmutable($values['d2']);
     72
    7373            if ($d2 < $d1) {
    7474                $form->withInput('d2')->addError('__The end date should be after the start date__');
     
    7878                $command = (new CreateEvent())
    7979                    ->withStartDate($d1)
    80                     ->withEndDate($d1)
     80                    ->withEndDate($d2)
    8181                    ->withTitle($values['title'])
    8282                    ->withDescription($values['description'])
  • plain-event-calendar/trunk/module/app/src/Controller/EventIdController.php

    r3372822 r3394866  
    66use Plainware\Http\Request;
    77use Plainware\Http\Redirect;
     8use Plainware\DateTime\DateTimeFormatter;
    89use Plainware\Ui\Component\Main;
    910use Plainware\Ui\Component\Link;
     
    2021class EventIdController
    2122{
    22     public CommandBus $commandBus;
    23     public EventRepo $repo;
     23    public $dtf = DateTimeFormatter::class;
     24    public $commandBus = CommandBus::class;
     25    public $repo = EventRepo::class;
     26
     27    public function title(Request $request)
     28    {
     29        $id = $request->getQueryParam('id');
     30        $m = $this->repo->getById($id);
     31
     32        $ret = [];
     33        $ret[] = $this->dtf->formatDateRange($m->getStartDate(), $m->getEndDate());
     34        $ret[] = esc_html($m->getTitle());
     35
     36        $ret = join(' &middot; ', $ret);
     37
     38        return $ret;
     39    }
    2440
    2541    public function __invoke(Request $request)
     
    5470
    5571        $form->withButton('submit', new Button('__Save changes__'));
    56         $form->withButton('delete', (new Link('./delete'))->setLabel('__Delete event__')->prependIcon('&times;'));
    5772
    5873        $form = $form->grab($request);
     
    6681            }
    6782
    68             $d1 = $values['d1'];
    69             $d2 = $values['d2'];
     83            $d1 = new \DateTimeImmutable($values['d1']);
     84            $d2 = new \DateTimeImmutable($values['d2']);
     85
    7086            if ($d2 < $d1) {
    7187                $form->withInput('d2')->addError('__The end date should be after the start date__');
  • plain-event-calendar/trunk/module/app/src/Controller/EventIdDeleteController.php

    r3372822 r3394866  
    1616class EventIdDeleteController
    1717{
    18     public CommandBus $commandBus;
    19     public EventRepo $repo;
     18    public $commandBus = CommandBus::class;
     19    public $repo = EventRepo::class;
    2020
    2121    public function __invoke(Request $request)
    2222    {
    23         $id = $request->getQueryParam('-id');
     23        $id = $request->getQueryParam('id');
    2424        $m = $this->repo->getById($id);
    2525
    2626        $form = new Form($request);
    2727
    28         $form->withButton('cancel', (new Link('..'))->setLabel('__No, do not delete event__')->prependIcon('&larr;'));
    2928        $form->withButton('submit', new Button('__Yes, delete event__'));
    3029
  • plain-event-calendar/trunk/module/app/src/Controller/Front/EventController.php

    r3372822 r3394866  
    99use Plainware\Ui\Component\Table;
    1010use Plainware\Ui\Component\Link;
    11 use Plainware\Time\Time;
     11use Plainware\DateTime\DateTimeFormatter;
    1212use PlainEventCalendar\App\Repo\EventRepo;
    1313
    1414class EventController
    1515{
    16     public EventRepo $repo;
    17     public Time $t;
     16    public $repo = EventRepo::class;
     17    public $dtf = DateTimeFormatter::class;
    1818
    1919    public function __invoke(Request $request)
    2020    {
    21         $today = $this->t->getDate($this->t->getNow());
     21        $today = (new \DateTimeImmutable())
     22            ->setTime(0, 0)
     23            ;
    2224
    2325        $ms = $this->repo
    24             ->orderStartDate('ASC')
     26            ->orderStartDateAsc()
    2527            ->whereStartDate('>=', $today)
    2628            ->read()
     
    5052            $jj = 1;
    5153
    52             $dateView = $this->t->formatDateRange($m->getStartDate(), $m->getEndDate());
     54            $dateView = $this->dtf->formatDateRange($m->getStartDate(), $m->getEndDate());
    5355            $dateView = '<p>' . esc_html($dateView) . '</p>';
    5456            $content->add($jj++, $dateView);
  • plain-event-calendar/trunk/module/app/src/Controller/InstallController.php

    r3372822 r3394866  
    1818class InstallController
    1919{
    20     public App $app;
    21     public Migrator $Migrator;
     20    public $app = App::class;
     21    public $migrator = Migrator::class;
    2222
    2323    public function __invoke(Request $request)
     
    3333
    3434        if ($form->isSubmitted() && $form->isValid()) {
    35             $this->Migrator->up();
     35            $this->migrator->up();
    3636
    3737            return new Redirect('');
  • plain-event-calendar/trunk/module/app/src/Controller/UninstallController.php

    r3372822 r3394866  
    1818class UninstallController
    1919{
    20     public App $app;
    21     public Migrator $Migrator;
     20    public $app = App::class;
     21    public $migrator = Migrator::class;
    2222
    2323    public function __invoke(Request $request)
     
    2929
    3030        if ($form->isSubmitted() && $form->isValid()) {
    31             $this->Migrator->down();
     31            $this->migrator->down();
     32
    3233            return new Redirect('');
    3334        }
  • plain-event-calendar/trunk/module/app/src/Event/EventRescheduled.php

    r3372822 r3394866  
    66{
    77    private int $eventId;
    8     private int $oldStartDate;
    9     private int $oldEndDate;
    10     private int $newStartDate;
    11     private int $newEndDate;
     8    private \DateTimeInterface $oldStartDate;
     9    private \DateTimeInterface $oldEndDate;
     10    private \DateTimeInterface $newStartDate;
     11    private \DateTimeInterface $newEndDate;
    1212
    13     public function __construct(int $eventId, int $oldStartDate, int $oldEndDate, int $newStartDate, int $newEndDate)
     13    public function __construct(
     14        int $eventId,
     15        \DateTimeInterface $oldStartDate,
     16        \DateTimeInterface $oldEndDate,
     17        \DateTimeInterface $newStartDate,
     18        \DateTimeInterface $newEndDate
     19        )
    1420    {
    1521        $this->eventId = $eventId;
     
    2531    }
    2632
    27     public function getOldStartDate(): int
     33    public function getOldStartDate(): \DateTimeInterface
    2834    {
    2935        return $this->oldStartDate;
    3036    }
    3137
    32     public function getNewStartDate(): int
     38    public function getNewStartDate(): \DateTimeInterface
    3339    {
    3440        return $this->newStartDate;
    3541    }
    3642
    37     public function getOldEndDate(): int
     43    public function getOldEndDate(): \DateTimeInterface
    3844    {
    3945        return $this->oldEndDate;
    4046    }
    4147
    42     public function getNewEndDate(): int
     48    public function getNewEndDate(): \DateTimeInterface
    4349    {
    4450        return $this->newEndDate;
  • plain-event-calendar/trunk/module/app/src/Middleware/CheckInstallMiddleware.php

    r3372822 r3394866  
    99class CheckInstallMiddleware
    1010{
    11     public Migrator $migrator;
     11    public $migrator = Migrator::class;
    1212
    1313    public function __invoke(Request $request, callable $next)
    1414    {
     15        if ('install' === $request->getRoute()) {
     16            return $next($request);
     17        }
     18
    1519        $installed = $this->migrator->isInstalled();
    1620        if (!$installed) {
  • plain-event-calendar/trunk/module/app/src/Model/Event.php

    r3372822 r3394866  
    55class Event
    66{
    7     public int $id;
    8     public string $title = '';
    9     public string $description = '';
    10     public int $date_start;
    11     public int $date_end;
    12     public string $state = 'active';
     7    private ?int $id = null;
     8    private string $title = '';
     9    private string $description = '';
     10    private \DateTimeImmutable $dateStart;
     11    private \DateTimeImmutable $dateEnd;
     12    private string $state = 'active';
     13
     14    public function __construct(?int $id = null)
     15    {
     16        $this->id = $id;
     17    }
     18
     19    public function withId(int $id): self
     20    {
     21        $ret = clone $this;
     22        $ret->id = $id;
     23
     24        return $ret;
     25    }
    1326
    1427    public function getId(): int
     
    2235    }
    2336
    24     public function setTitle(string $title): self
     37    public function setTitle(string $v): self
    2538    {
    26         $this->title = $title;
     39        $this->title = $v;
    2740
    2841        return $this;
     
    3447    }
    3548
    36     public function setDescription(string $description): self
     49    public function setDescription(string $v): self
    3750    {
    38         $this->description = $description;
     51        $this->description = $v;
    3952
    4053        return $this;
    4154    }
    4255
    43     public function getStartDate(): int
     56    public function getStartDate(): \DateTimeImmutable
    4457    {
    45         return $this->date_start;
     58        return $this->dateStart;
    4659    }
    4760
    48     public function setStartDate(int $d): self
     61    public function setStartDate(\DateTimeImmutable $v): self
    4962    {
    50         $this->date_start = $d;
     63        $this->dateStart = $v;
    5164
    5265        return $this;
    5366    }
    5467
    55     public function getEndDate(): int
     68    public function getEndDate(): \DateTimeImmutable
    5669    {
    57         return $this->date_end;
     70        return $this->dateEnd;
    5871    }
    5972
    60     public function setEndDate(int $d): self
     73    public function setEndDate(\DateTimeImmutable $v): self
    6174    {
    62         $this->date_end = $d;
     75        $this->dateEnd = $v;
    6376
    6477        return $this;
     
    7083    }
    7184
    72     public function setState(string $state): self
     85    public function export(): array
    7386    {
    74         $this->state = $state;
    75 
    76         return $this;
     87        return get_object_vars($this);
    7788    }
    7889}
  • plain-event-calendar/trunk/module/app/src/Repo/EventRepo.php

    r3372824 r3394866  
    33namespace PlainEventCalendar\App\Repo;
    44
    5 use Plainware\Database\Repo\AbstractDatabaseRepo;
     5use Plainware\Database\Database;
     6use PlainEventCalendar\App\Database\EventDatabaseTable;
    67use PlainEventCalendar\App\Model\Event;
    78
    8 class EventRepo extends AbstractDatabaseRepo
     9class EventRepo
    910{
    10     protected $table = '__event';
    11     protected $model = Event::class;
     11    public $db = Database::class;
     12    public $table = EventDatabaseTable::class;
     13    private array $original = [];
    1214
    13     public function up1()
     15    public function limit(int $v): self
    1416    {
    15         $fields = [
    16             'id' => ['type' => 'INTEGER', 'null' => false, 'auto_increment' => true, 'key' => true],
    17             'title' => ['type' => 'VARCHAR(255)', 'null' => false, 'default' => ''],
    18             'date_start' => ['type' => 'INTEGER', 'null' => false],
    19             'date_end' => ['type' => 'INTEGER', 'null' => false],
    20             'state' => ['type' => 'VARCHAR(16)', 'null' => false, 'default' => 1],
    21             'description' => ['type' => 'TEXT', 'null' => false, 'default' => ''],
    22         ];
    23         $this->db->createTable($this->table, $fields);
     17        $this->db->limit($v);
     18
     19        return $this;
    2420    }
    2521
    26     public function down1()
     22    public function offset(int $v): self
    2723    {
    28         $this->db->dropTable($this->table);
     24        $this->db->offset($v);
     25
     26        return $this;
    2927    }
    3028
    31     public function getById(int $id)
     29    public function orderStartDateAsc(): self
    3230    {
    33         return $this->getBy('id', $id);
     31        $this->db->orderAsc('date_start');
     32
     33        return $this;
    3434    }
    3535
    36     public function orderStartDate(string $how)
     36    public function orderStartDateDesc(): self
    3737    {
    38         return $this->order('date_start', $how);
     38        $this->db->orderDesc('date_start');
     39
     40        return $this;
    3941    }
    4042
    41     public function whereStartDate(string $compare, $to)
     43    public function whereId(string $compare, int $v): self
    4244    {
    43         return $this->where('date_start', $compare, $to);
     45        $this->db->where('id', $compare, $v);
     46
     47        return $this;
     48    }
     49
     50    public function whereStartDate(string $compare, \DateTimeInterface $v): self
     51    {
     52        $this->db->where('date_start', $compare, $v);
     53
     54        return $this;
     55    }
     56
     57    public function getById(int $id): ?Event
     58    {
     59        if (isset($this->original[$id])) {
     60            return $this->original[$id];
     61        }
     62
     63        $res = $this->whereId('=', $id)->limit(1)->read();
     64        if (!$res) {
     65            return null;
     66        }
     67
     68        return current($res);
     69    }
     70
     71    public function read(): array
     72    {
     73        $ret = [];
     74
     75        $res = $this->db
     76            ->table($this->table->getName())
     77            ->get()
     78            ;
     79
     80        foreach ($res as $a) {
     81            $m = (new Event($a['id']))
     82                ->setTitle($a['title'])
     83                ->setStartDate(new \DateTimeImmutable($a['date_start']))
     84                ->setEndDate(new \DateTimeImmutable($a['date_end']))
     85                ->setDescription($a['description'])
     86                ;
     87            $ret[] = $m;
     88            $this->original[$m->getId()] = $m;
     89        }
     90
     91        return $ret;
     92    }
     93
     94    public function create(Event $m): ?Event
     95    {
     96        $id = $this->db
     97            ->table($this->table->getName())
     98            ->field('title', $m->getTitle())
     99            ->field('date_start', $m->getStartDate())
     100            ->field('date_end', $m->getEndDate())
     101            ->field('description', $m->getDescription())
     102            ->insert()
     103            ;
     104        $m = $m->withId($id);
     105
     106        return $m;
     107    }
     108
     109    public function delete(Event $m): Event
     110    {
     111        $this->db
     112            ->table($this->table->getName())
     113            ->where('id', '=', $m->getId())
     114            ->delete()
     115            ;
     116
     117        return $m;
    44118    }
    45119}
  • plain-event-calendar/trunk/module/app/src/Ui/Renderer/EventRenderer.php

    r3372822 r3394866  
    44
    55use Plainware\Ui\Ui;
    6 use Plainware\Time\Time;
     6use Plainware\DateTime\DateTimeFormatter;
    77use PlainEventCalendar\App\Model\Event;
    88
    99final class EventRenderer
    1010{
    11     public Time $t;
     11    public $dtf = DateTimeFormatter::class;
    1212
    1313    public function __invoke(Event $m): string
     
    1515        $ret = [];
    1616        $ret[] = $m->getTitle();
    17         $ret[] = $this->t->formatDateRange($m->getStartDate(), $m->getEndDate());
     17        $ret[] = $this->dtf->formatDateRange($m->getStartDate(), $m->getEndDate());
    1818
    1919        array_walk($ret, 'esc_html');
  • plain-event-calendar/trunk/module/wp-hook/boot.php

    r3372822 r3394866  
    66use Plainware\Core\App;
    77
    8 return [
    9     App::class => function (App $app) {
    10         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    11     },
     8return function(App $app) {
     9    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    1210
    13     EventBus::class => function (EventBus $b) {
    14         $b
     11    $app->onBoot(EventBus::class, function($eventBus) {
     12        $eventBus
    1513            ->listener('*', Event\Listener\WordpressDoActionOnAllEvent::class)
    1614        ;
    17     },
    18 ];
     15    });
     16};
  • plain-event-calendar/trunk/plain-event-calendar.php

    r3372908 r3394866  
    33Plugin Name: Plain Event Calendar
    44Description: A simple event calendar to manage and publish your events.
    5 Version: 2.0.3
     5Version: 2.0.5
    66Author: plainware
    77Text Domain: plain-event-calendar
     
    2121    private string $pluginFile;
    2222    private $response = null;
     23    private $restRouteNamespace = 'plain-event-calendar/v2';
    2324
    2425    public static function start()
     
    3839        add_action('init', [$this, 'frontInit']);
    3940        add_action('init', [$this, 'registerBlock']);
     41
     42        add_action('rest_api_init', [$this, 'restInit']);
     43    }
     44
     45    public function restInit()
     46    {
     47    // catch-all route
     48        // register_rest_route($this->wpRouteNamespace, '/(?P<slug>[a-z0-9-\/]+)',
     49        register_rest_route($this->restRouteNamespace, '/([a-z0-9-\/]+)',
     50            [
     51                'methods' => \WP_REST_Server::ALLMETHODS,
     52                'callback' => [$this, 'restHandle'],
     53                'permission_callback' => '__return_true',
     54                // 'permission_callback' => [$this, 'checkAdmin'],
     55            ],
     56        );
     57    }
     58
     59    public function restHandle(\WP_REST_Request $wpRestRequest)
     60    {
     61        $this->init();
     62        $server = $this->app->make(\Plainware\HttpWordpress\WordpressServer::class);
     63
     64        return $server->handleWpRestRequest($wpRestRequest, $this->restRouteNamespace, 'api');
    4065    }
    4166
     
    114139        $dbPrefix = $wpdbPrefix . $myDbPrefix . '_';
    115140
    116         $app->registerBootFunc(
    117             \Plainware\DatabaseWordpress\WordpressDatabase::class,
     141        $app->onBoot(\Plainware\Database\Database::class,
    118142            function ($db) use ($dbPrefix) {
    119143                $db->setPrefix($dbPrefix);
     
    122146    // request prefix
    123147        $prefix = $this->slug;
    124         $app->registerBootFunc(
    125             \Plainware\Http\Server::class,
     148        $app->onBoot(\Plainware\Http\Server::class,
    126149            function ($server) use ($prefix) {
    127150                $server->setPrefix($prefix);
     
    129152
    130153    // uri href func
    131         $app->registerBootFunc(
    132             \Plainware\Http\Uri::class,
     154        $app->onBoot(\Plainware\Http\Uri::class,
    133155            function ($uri) {
    134156                $uri->setHrefFunc([$this, 'uriHref']);
  • plain-event-calendar/trunk/readme.txt

    r3372822 r3394866  
    33Tags: event calendar, event manager, calendar, events, school, university, church
    44License: GPLv2 or later
    5 Stable tag: 2.0.3
     5Stable tag: 2.0.5
    66Requires at least: 4.1
    77Tested up to: 6.8
     
    4949== Changelog ==
    5050
     51= 2.0.5 (2025-11-13) =
     52* Added REST API interface.
     53* Framework code update.
     54
     55= 2.0.4 (2025-10-22) =
     56* BUG: The end date for new events wasn't set properly.
     57* Framework code update.
     58
    5159= 2.0.3 (2025-10-05) =
    5260* Added an option to hook into plugin's domain events.
  • plain-event-calendar/trunk/vendor/plainware/app/boot.php

    r3372822 r3394866  
    55use Plainware\Core\App;
    66
    7 return [
    8     App::class => function (App $app) {
    9         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    10     },
    11 ];
     7return function (App $app) {
     8    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
     9};
  • plain-event-calendar/trunk/vendor/plainware/app/src/CommandBus.php

    r3372822 r3394866  
    77class CommandBus
    88{
    9     public App $app;
     9    public $app = App::class;
    1010    private $handlers = [];
    1111
  • plain-event-calendar/trunk/vendor/plainware/app/src/EventBus.php

    r3372822 r3394866  
    77class EventBus
    88{
    9     public App $app;
     9    public $app = App::class;
    1010    private $listeners = [];
     11    private $events = [];
     12    private bool $defer = false;
     13
     14/* register a listener */
     15    public function listener(string $eventClass, $func): self
     16    {
     17        if (!isset($this->listeners[$eventClass])) {
     18            $this->listeners[$eventClass] = [];
     19        }
     20        $this->listeners[$eventClass][] = $func;
     21
     22        return $this;
     23    }
    1124
    1225    public function emit($event)
     26    {
     27        if ($this->defer) {
     28            $this->events[] = $event;
     29        } else {
     30            $this->process($event);
     31        }
     32
     33        return $this;
     34    }
     35
     36    public function hasEvents(): bool
     37    {
     38        return ($this->events) ? true : false;
     39    }
     40
     41    public function processEvents()
     42    {
     43        foreach ($this->events as $event) {
     44            $this->process($event);
     45        }
     46        $this->events = [];
     47    }
     48
     49    private function process($event)
    1350    {
    1451        $eventClass = is_object($event) ? get_class($event) : $event;
     
    2360        }
    2461    }
    25 
    26 /* register a listener */
    27     public function listener(string $eventClass, $func): self
    28     {
    29         if (!isset($this->listeners[$eventClass])) {
    30             $this->listeners[$eventClass] = [];
    31         }
    32         $this->listeners[$eventClass][] = $func;
    33 
    34         return $this;
    35     }
    3662}
  • plain-event-calendar/trunk/vendor/plainware/app/src/FilterBus.php

    r3372822 r3394866  
    77class FilterBus
    88{
    9     public App $app;
     9    public $app = App::class;
    1010    private $handlers = [];
    1111
  • plain-event-calendar/trunk/vendor/plainware/core/boot.php

    r3372822 r3394866  
    55use Plainware\Core\App;
    66
    7 return [
    8     App::class => function (App $app) {
    9         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    10     },
    11 ];
     7return function (App $app) {
     8    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
     9};
  • plain-event-calendar/trunk/vendor/plainware/core/src/App.php

    r3372822 r3394866  
    33namespace Plainware\Core;
    44
     5/*
     6injects dependencies as ObjectProxy into public properties without type hints that equal to the class name
     7class One
     8{
     9    public $two = Two::class;
     10    public $thee = Three::class;
     11}
     12*/
    513class App
    614{
    715    private array $autoload = [];
    816    private array $env = [];
    9     private string $globalVarName;
    1017
    1118    private string $mainFile;
     
    1320    private $name;
    1421
    15 // functions to call on objects' instantiation
    16     private array $boot = [];
    17 
    18 // implementations map
    19     private $implementation = [];
    20 
    21 // already instantiated real objects
    22     private $instance = [];
    23 
    24 // to build chains of decorated objects
    25     private $decorators = [];
     22// funcs to run on end of request
     23    private array $end = [];
     24
     25// dependency injection container
     26// already made proxies
     27    private array $made = [];
     28
     29// already constructed objects
     30    private array $constructed = [];
     31
     32// decorators
     33    private array $decorator = [];
     34
     35// listeners
     36    private array $listener = [];
    2637
    2738    public function __construct(string $mainFile, array $env = [])
     
    3546        $this->name = File::appNameFromFile($this->mainFile);
    3647
    37     // save it as global
    38         do {
    39             $rand = (string) rand(100, 999);
    40             $this->globalVarName = '__pw_app' . $rand;
    41         } while (isset($GLOBALS[$this->globalVarName]));
    42 
    43         $GLOBALS[$this->globalVarName] = $this;
    44         $this->instance[__CLASS__] = $this;
     48        $this->bind(__CLASS__, $this);
     49
     50        if ('cli' === php_sapi_name()) {
     51            register_shutdown_function([$this, 'shutdown']);
     52        }
     53    }
     54
     55    public function end()
     56    {
     57        foreach ($this->end as $func) {
     58            $this->call($func);
     59        }
     60    }
     61
     62    public function onEnd($func): self
     63    {
     64        $this->end[] = $func;
     65
     66        return $this;
    4567    }
    4668
     
    7597    }
    7698
    77 // register an implementation
    78     public function implement(string $interface, string $class): self
    79     {
    80         $this->implementation[$interface] = $class;
    81 
    82         return $this;
    83     }
    84 
    85 // register a decorator
     99    public function registerModule($moduleId)
     100    {
     101        $prfx = 'vendor/plainware/';
     102        if ($prfx === substr($moduleId, 0, strlen($prfx))) {
     103            $moduleDir = dirname(dirname(__DIR__)) . '/' . substr($moduleId, strlen($prfx));
     104        } else {
     105            $moduleDir = dirname($this->mainFile) . '/' . $moduleId;
     106        }
     107
     108    /* got boot file? */
     109        $moduleBootFile = $moduleDir . '/boot.php';
     110        if (file_exists($moduleBootFile)) {
     111            $moduleBoot = require($moduleBootFile) ?? null;
     112            if (is_callable($moduleBoot)) {
     113                call_user_func($moduleBoot, $this);
     114            }
     115        }
     116
     117        return $this;
     118    }
     119
     120    public function autoload(string $namespace, string $dir): self
     121    {
     122        $this->autoload[] = [$namespace, $dir];
     123
     124        return $this;
     125    }
     126
     127    public function version()
     128    {
     129        return $this->version;
     130    }
     131
     132    public function name()
     133    {
     134        return $this->name;
     135    }
     136
     137// display errors after ob_start too
     138    public function onError($errno, $errstr, $errfile, $errline)
     139    {
     140        $ret = '';
     141        while (ob_get_level()) {
     142            $ret .= ob_get_clean();
     143        }
     144        echo $ret;
     145
     146        return false;
     147    }
     148
     149// makes an ObjectProxy
     150    public function make(string $class, ...$args)
     151    {
     152    // already made?
     153        if (isset($this->made[$class])) {
     154            return $this->made[$class];
     155        }
     156
     157        $ret = new ObjectProxy($class, [$this, 'call']);
     158        $this->made[$class] = $ret;
     159
     160        return $ret;
     161    }
     162
     163    public function call($func, array $args = [])
     164    {
     165        $func = $this->makeFunc($func);
     166
     167        return call_user_func_array($func, $args);
     168    }
     169
     170// register a decorator function: one that wraps an original func
    86171    public function decorate($original, $decorator): self
    87172    {
    88     // func?
    89173        if (is_array($original)) {
    90174            $original = join('::', $original);
    91175        }
    92176
    93         if (!isset($this->decorators[$original])) {
    94             $this->decorators[$original] = [];
    95         }
    96         $this->decorators[$original][] = $decorator;
     177        if (!isset($this->decorator[$original])) {
     178            $this->decorator[$original] = [];
     179        }
     180        $this->decorator[$original][] = $decorator;
     181
     182        return $this;
     183    }
     184
     185// register a listener function: one that runs after the original func, gets its return value as 1st arg
     186    public function listen($original, $listener): self
     187    {
     188        if (is_array($original)) {
     189            $original = join('::', $original);
     190        }
     191
     192        if (!isset($this->listener[$original])) {
     193            $this->listener[$original] = [];
     194        }
     195        $this->listener[$original][] = $listener;
    97196
    98197        return $this;
     
    105204            throw new \InvalidArgumentException(get_class($instance) . ' should be ' . $class);
    106205        }
    107         $this->instance[$class] = $instance;
    108 
    109         return $this;
    110     }
    111 
    112     public function call($func, array $args = [])
    113     {
    114         $func = $this->makeFunc($func);
    115 
    116         return call_user_func_array($func, $args);
     206        $this->made[$class] = $instance;
     207
     208        return $this;
    117209    }
    118210
     
    139231        }
    140232
    141     // check decorators
     233    // construct if needed
     234        if (is_array($func)) {
     235            if (!is_object($func[0])) {
     236                $func[0] = $this->construct($func[0]);
     237            }
     238        } else {
     239            if (!is_object($func)) {
     240                $func = $this->construct($func);
     241            }
     242        }
     243
     244    // decorators? build chain of functions, each one gets previus func appended to args list
     245// echo "CHECK '$funcName'<br>";
     246// _print_r(array_keys($this->decorators));
    142247        list($className, $methodName) = is_array($func) ? $func : [$func, null];
    143248        if (is_object($className)) {
     
    146251        $funcName = (null === $methodName) ? $className : $className . '::' . $methodName;
    147252
    148         if (is_array($func)) {
    149             if (!is_object($func[0])) {
    150                 $func[0] = $this->make($func[0]);
    151             }
    152         } else {
    153             if (!is_object($func)) {
    154                 $func = $this->make($func);
    155             }
    156         }
    157 
    158     // decorators?
    159 // echo "CHECK '$funcName'<br>";
    160 // _print_r(array_keys($this->decorators));
    161         if (isset($this->decorators[$funcName])) {
    162             foreach ($this->decorators[$funcName] as $decoratorFunc) {
     253        if (isset($this->decorator[$funcName])) {
     254            foreach ($this->decorator[$funcName] as $decoratorFunc) {
    163255                $decoratorFunc = $this->makeFunc($decoratorFunc);
    164256                $func = function (...$args) use ($decoratorFunc, $func) {
     
    172264    }
    173265
    174     public function make($class, ...$args)
    175     {
    176     // is already constructed?
    177         if (isset($this->instance[$class])) {
    178             return $this->instance[$class];
    179         }
    180 
    181     // is interface?
    182         $concreteClass = $this->implementation[$class] ?? $class;
    183 
    184         if ($concreteClass !== $class) {
    185             $ret = $this->make($concreteClass, ...$args);
    186         } else {
    187             $ret = new $class(...$args);
    188 
    189         // inject through public properties
    190             $vars = $this->getClassProperties($concreteClass);
    191             foreach ($vars as $propName => $propClass) {
    192                 if ('self' === $propName) {
    193                     $ret->self = $ret;
    194                 } else {
    195                     if (!isset($ret->{$propName})) {
    196                         $ret->{$propName} = $this->make($propClass);
    197                     }
     266/*
     267    constructs a real object
     268*/
     269    private function construct(string $class)
     270    {
     271    // already constructed?
     272        if (isset($this->constructed[$class])) {
     273            return $this->constructed[$class];
     274        }
     275
     276// echo "CLASS = '$class'<br>";
     277        // $ret = new $class(...$args);
     278        $ret = new $class();
     279
     280    // inject through public properties
     281    // assume they contain required class names
     282        $vars = get_class_vars($class);
     283// _print_r($vars);
     284
     285        foreach ($vars as $propName => $propClass) {
     286            if ('self' === $propName){
     287                $propClass = $class;
     288            } else {
     289                if (!is_string($propClass)) {
     290                    continue;
    198291                }
    199292            }
    200         }
    201 
    202         $this->instance[$class] = $ret;
    203 
    204     // should we decorate?
    205         $decorators = $this->decorators[$class] ?? [];
    206         foreach ($decorators as $decoratorClass) {
    207             // echo "DECORATE '$class' BY '$decoratorClass'<br>";
    208             $ret = $this->make($decoratorClass, ...$args);
    209             if (!($ret instanceof $class)) {
    210                 throw new \InvalidArgumentException(esc_html($decoratorClass) . ' should be ' . esc_html($class));
    211             }
    212         // reset self property to decorated objects
    213             if (property_exists($this->instance[$class], 'self')) {
    214                 $this->instance[$class]->self = $ret;
    215             }
    216             $this->instance[$class] = $ret;
    217         }
     293            $ret->{$propName} = $this->make($propClass);
     294        }
     295
     296        $this->constructed[$class] = $ret;
    218297
    219298    // any boot calls?
    220         if (isset($this->boot[$class])) {
    221             foreach ($this->boot[$class] as $bootFunc) {
    222                 $this->call($bootFunc, [$ret]);
     299       if (isset($this->listener[$class . '::__construct'])) {
     300            $proxy = $this->make($class);
     301            foreach ($this->listener[$class . '::__construct'] as $bootFunc) {
     302                $this->call($bootFunc, [$proxy]);
    223303            }
    224304        }
     
    227307    }
    228308
    229     private function getClassProperties($class)
    230     {
    231         $ret = [];
    232 
    233         $vars = get_class_vars($class);
    234         if (!$vars) {
    235             return $ret;
    236         }
    237 
    238         foreach (array_keys($vars) as $propName) {
    239             $rp = new \ReflectionProperty($class, $propName);
    240             if (!$rp->hasType()) {
    241                 continue;
    242             }
    243             $propClass = $rp->getType()->getName();
    244             $ret[$propName] = $propClass;
    245         }
    246 
    247         return $ret;
    248     }
    249 
    250     public function registerModule($moduleId)
    251     {
    252         $prfx = 'vendor/plainware/';
    253         if ($prfx === substr($moduleId, 0, strlen($prfx))) {
    254             $moduleDir = dirname(dirname(__DIR__)) . '/' . substr($moduleId, strlen($prfx));
    255         } else {
    256             $moduleDir = dirname($this->mainFile) . '/' . $moduleId;
    257         }
    258 
    259     /* got boot file? */
    260         $moduleBootFile = $moduleDir . '/boot.php';
    261         if (file_exists($moduleBootFile)) {
    262             $moduleBoot = require($moduleBootFile) ?? [];
    263 
    264             foreach ($moduleBoot as $className => $bootFunc) {
    265                 $this->registerBootFunc($className, $bootFunc);
    266 
    267             // already instantiated? call it now
    268                 if (isset($this->instance[$className])) {
    269                     if (!is_object($this->instance[$className])) {
    270                         $this->instance[$className] = $this->make($this->instance[$className]);
    271                     }
    272                     $this->call($bootFunc, [$this->instance[$className]]);
    273                 }
    274             }
    275         }
    276 
    277         return $this;
    278     }
    279 
    280     public function registerBootFunc(string $className, $bootFunc): self
    281     {
    282         $this->boot[$className][] = $bootFunc;
    283 
    284         return $this;
    285     }
    286 
    287     public function autoload(string $namespace, string $dir): self
    288     {
    289         $this->autoload[] = [$namespace, $dir];
    290 
    291         return $this;
    292     }
    293 
    294     public function version()
    295     {
    296         return $this->version;
    297     }
    298 
    299     public function name()
    300     {
    301         return $this->name;
    302     }
    303 
    304 // display errors after ob_start too
    305     public function onError($errno, $errstr, $errfile, $errline)
    306     {
    307         $ret = '';
    308         while (ob_get_level()) {
    309             $ret .= ob_get_clean();
    310         }
    311         echo $ret;
    312 
    313         return false;
     309    public function onBoot(string $class, $func): self
     310    {
     311        $this->listen([$class, '__construct'], $func);
     312
     313    // already instantiated? call it now
     314        if (isset($this->made[$class])) {
     315            $this->call($bootFunc, [$this->made[$class]]);
     316        }
     317
     318        return $this;
     319    }
     320
     321    public function getMainFile(): string
     322    {
     323        return $this->mainFile;
    314324    }
    315325}
  • plain-event-calendar/trunk/vendor/plainware/database-wordpress/boot.php

    r3372822 r3394866  
    44
    55use Plainware\Core\App;
    6 use Plainware\Database\DatabaseInterface;
     6use Plainware\Database\Database;
    77
    8 return [
    9     App::class => function (App $app) {
    10         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    11         $app
    12             ->implement(DatabaseInterface::class, WordpressDatabase::class)
    13             ;
    14     },
    15 ];
     8return function (App $app) {
     9    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
     10    $app->onBoot(Database::class, function ($db) {
     11        $adapter = new WordpressDatabaseAdapter();
     12        $db->setAdapter($adapter);
     13    });
     14};
  • plain-event-calendar/trunk/vendor/plainware/database/boot.php

    r3372822 r3394866  
    44
    55use Plainware\Core\App;
     6use Plainware\Core\EventBus;
     7use Plainware\Database\App\AppOnEnd;
    68
    7 return [
    8     App::class => function (App $app) {
    9         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    10     },
    11 ];
     9return function (App $app) {
     10    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
     11    $app->onEnd(AppOnEnd::class);
     12    $app->onBoot(EventBus::class, function ($eventBus) {
     13        $eventBus->defer();
     14    });
     15};
  • plain-event-calendar/trunk/vendor/plainware/database/src/Migrator.php

    r3372822 r3394866  
    44
    55use Plainware\Core\App;
    6 use Plainware\Database\DatabaseInterface;
     6use Plainware\Database\Database;
    77use Plainware\Database\Exception\DatabaseException;
    88
    99class Migrator
    1010{
    11     public DatabaseInterface $db;
    12     public App $app;
     11    public $db = Database::class;
     12    public $app = App::class;
    1313    private array $migrations = [];
    1414    private ?array $versions = null;
    15     private $table = '__migration';
    1615
    1716    public function __construct()
     
    2019        $this->registerMigration('migration', 1, [get_class($this), 'up1'], [get_class($this), 'down1']);
    2120    }
     21
     22    public function getDatabaseTable(): string
     23    {
     24        return '__migration';
     25    }
     26
     27    public function up1()
     28    {
     29        $this->db
     30            ->table($this->getDatabaseTable())
     31            ->field('module', ['type' => 'VARCHAR(32)', 'null' => false, 'primaryKey' => true])
     32            ->field('version', ['type' => 'INTEGER', 'null' => false])
     33            ->createTable()
     34            ;
     35    }
     36
     37    public function down1()
     38    {
     39        $this->db
     40            ->table($this->getDatabaseTable())
     41            ->dropTable()
     42            ;
     43    }
     44
     45    // public function up2()
     46    // {
     47        // $this->db
     48            // ->table($this->getDatabaseTable())
     49            // ->field('title')
     50            // ->addIndex()
     51            // ;
     52    // }
     53
    2254
    2355    public function isInstalled()
     
    3668    }
    3769
    38     public function registerMigration(string $module, int $version, $funcUp, $funcDown = null)
     70    public function registerMigration(string $module, int $version, $funcUp, $funcDown = null): self
     71    {
     72        return $this->register($module, $version, $funcUp, $funcDown);
     73    }
     74
     75    public function register(string $module, int $version, $funcUp, $funcDown = null): self
    3976    {
    4077        if (!isset($this->migrations[$version])) {
     
    5491    public function up()
    5592    {
    56         $this->db->start();
    57 
    5893        ksort($this->migrations);
    5994
     
    77112    public function down()
    78113    {
    79         $this->db->stop();
    80 
    81114        $migrations = $this->migrations[1] ?? [];
    82115
     
    99132    }
    100133
    101     public function up1()
    102     {
    103         $fields = [
    104             'module' => ['type' => 'VARCHAR(32)', 'null' => false],
    105             'version' => ['type' => 'INTEGER', 'null' => false],
    106         ];
    107         $this->db->createTable($this->table, $fields);
    108     }
    109 
    110     public function down1()
    111     {
    112         $this->db->dropTable($this->table);
    113     }
    114 
    115134    private function getCurrentVersions(): array
    116135    {
     
    122141
    123142        try {
    124             $q = [];
    125             $props = ['module', 'version'];
    126             $res = $this->db->select($this->table, $props, $q);
     143            $res = $this->db
     144                ->table($this->getDatabaseTable())
     145                ->get()
     146                ;
     147
    127148            if ($res) {
    128149                foreach ($res as $a) {
     
    132153                }
    133154            }
    134         } catch (DatabaseException $e) {
     155        } catch (\Exception $e) {
    135156        }
    136157
     
    140161    private function setCurrentVersion(string $module, int $version)
    141162    {
     163        $table = $this->getDatabaseTable();
     164
    142165        if ($version < 1) {
    143             $q = [];
    144             $q[] = ['module', '=', $module];
    145             $this->db->delete($this->table, $q);
     166            $this->db
     167                ->table($table)
     168                ->where('module', '=', $module)
     169                ->delete()
     170                ;
    146171        } elseif ($version > 1) {
    147             $q = [];
    148             $a = ['version' => $version];
    149             $q[] = ['module', '=', $module];
    150             $this->db->update($this->table, $a, $q);
     172            $this->db
     173                ->table($table)
     174                ->field('version', $version)
     175                ->where('module', '=', $module)
     176                ->update()
     177                ;
    151178        } else {
    152             $a = ['module' => $module, 'version' => $version];
    153             $this->db->insert($this->table, $a);
     179            $this->db
     180                ->table($table)
     181                ->field('module', $module)
     182                ->field('version', $version)
     183                ->insert()
     184                ;
    154185        }
    155186        $this->versions[$module] = $version;
  • plain-event-calendar/trunk/vendor/plainware/http/boot.php

    r3372822 r3394866  
    55use Plainware\Core\App;
    66
    7 return [
    8     App::class => function (App $app) {
    9         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    10     },
    11 ];
     7return function (App $app) {
     8    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
     9};
  • plain-event-calendar/trunk/vendor/plainware/http/src/Redirect.php

    r3372822 r3394866  
    55class Redirect
    66{
    7     private array $slug = [];
     7    private string $slug = '';
    88    private array $params = [];
    99    private string $message = '';
     
    1111    public function __construct(string $slug, array $params = [])
    1212    {
    13         $this->slug = explode('/', $slug);
     13        $this->slug = $slug;
    1414        $this->params = $params;
    1515    }
    1616
    17     public function getSlug(): array
     17    public function getSlug(): string
    1818    {
    1919        return $this->slug;
  • plain-event-calendar/trunk/vendor/plainware/http/src/Request.php

    r3372822 r3394866  
    55class Request
    66{
    7     private $requestMethod;
    8     private $queryParams = [];
     7    private string $requestMethod;
     8    private array $queryParams = [];
     9    private array $routeParams = [];
     10    private array $headers = [];
     11    private $body = null;
     12    private $parsedBody = [];
    913    private array $attributes = [];
    10     private array $slug = [];
     14    private string $route = '';
    1115    private string $prefix = '';
    1216    private $currentUserId = null;
     
    2529    }
    2630
     31    public function getBody()
     32    {
     33        return $this->body;
     34    }
     35
     36    public function getParsedBody(): array
     37    {
     38        return $this->parsedBody;
     39    }
     40
     41    public function withParsedBody(array $data)
     42    {
     43        $ret = clone $this;
     44        $ret->parsedBody = $data;
     45
     46        return $ret;
     47    }
     48
    2749    public function getParamName(string $name): string
    2850    {
     
    4567    }
    4668
    47     public function getRequestMethod()
     69    public function getRequestMethod(): string
    4870    {
    4971        return $this->requestMethod;
     
    5476    }
    5577
    56     public function getSlug(): array
    57     {
    58         return $this->slug;
     78    public function getSlug(): string
     79    {
     80        return $this->getRoute();
     81    }
     82
     83    public function getRoute(): string
     84    {
     85        return $this->route;
    5986    }
    6087
     
    6794    }
    6895
     96    public function getRouteParam($k)
     97    {
     98        return $this->routeParams[$k] ?? null;
     99    }
     100
     101    public function getHeader(string $name)
     102    {
     103        return $this->headers[$this->prepareHeaderName($name)] ?? null;
     104    }
     105
     106    public function withHeader(string $name, $value): self
     107    {
     108        $ret = clone $this;
     109        $ret->headers[$this->prepareHeaderName($name)] = $value;
     110
     111        return $ret;
     112    }
     113
     114    private function prepareHeaderName(string $name): string
     115    {
     116        $ret = $name;
     117        $ret = strtolower($ret);
     118        $ret = str_replace(' ', '-', $ret);
     119        $ret = str_replace('_', '-', $ret);
     120
     121        return $ret;
     122    }
     123
    69124    public function getQueryParam($k, $default = null)
    70125    {
     126        if (isset($this->routeParams[$k])) {
     127            return $this->routeParams[$k];
     128        }
     129
    71130        if (!isset($this->queryParams[$k])) {
    72131            $this->queryParams[$k] = $default;
     
    96155    private function fromGlobals(): self
    97156    {
     157    // headers
     158        foreach ($_SERVER as $name => $value) {
     159            if (substr($name, 0, 5) == 'HTTP_') {
     160                // $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
     161                $name = substr($name, strlen('HTTP_'));
     162                $this->headers[$this->prepareHeaderName($name)] = $value;
     163            }
     164        }
     165
    98166    // query params
    99167        $ret = [];
    100 
    101168        $names = array_keys($_GET);
    102169        if (!$names) {
     
    125192        $this->queryParams = $ret;
    126193
     194    // body
     195        $this->body = file_get_contents('php://input');
     196
     197    // json params
     198        if (strlen($this->body)){
     199            $parsedBody = json_decode($this->body, true);
     200            if ((null === $parsedBody) && (JSON_ERROR_NONE !== json_last_error())) {
     201                // Ensure subsequent calls receive error instance.
     202                // $this->parsed_json = false;
     203
     204                $error = [
     205                    'json_error_code'    => json_last_error(),
     206                    'json_error_message' => json_last_error_msg(),
     207                ];
     208
     209                $parsedBody = [];
     210                // return new WP_Error( 'rest_invalid_json', __( 'Invalid JSON body passed.' ), $error_data );
     211            }
     212            $this->parsedBody = $parsedBody;
     213        }
     214
    127215        return $this;
    128216    }
     
    141229    }
    142230
    143     public function withSlug(array $slug): self
    144     {
    145         $ret = clone $this;
    146         $ret->slug = $slug;
     231    public function withSlug(string $v): self
     232    {
     233        $ret = clone $this;
     234        $ret->route = $v;
     235
     236        return $ret;
     237    }
     238
     239    public function withRouteParam(string $k, $v): self
     240    {
     241        $ret = clone $this;
     242        $ret->routeParams[$k] = $v;
    147243
    148244        return $ret;
     
    176272    // }
    177273
    178     public function makeTo($slug, array $params = []): self
    179     {
    180         if (!is_array($slug)) {
    181             $slug = explode('/', $slug);
    182         }
    183 
    184         $currentSlug = $this->getSlug();
     274    public function resolveRoute(string $route, string $currentRoute)
     275    {
     276        $routeArray = strlen($route) ? explode('/', $route) : [];
     277       
     278        $currentRouteArray = explode('/', $currentRoute);
     279        $currentRouteArray = strlen($currentRoute) ? explode('/', $currentRoute) : [];
     280
     281        $finalRouteArray = [];
     282        $copyCurrentRouteArray = $currentRouteArray;
     283
     284        while ($p = array_shift($routeArray)) {
     285            if ('.' === $p) {
     286                $finalRouteArray = $currentRouteArray;
     287            } elseif ('..' === $p) {
     288                array_pop($copyCurrentRouteArray);
     289                $finalRouteArray = $copyCurrentRouteArray;
     290            } else {
     291                $finalRouteArray[] = $p;
     292            }
     293        }
     294
     295        $ret = join('/', $finalRouteArray);
     296
     297        return $ret;
     298    }
     299
     300    public function makeTo(string $route, array $params = []): self
     301    {
     302        $currentRoute = $this->getRoute();
    185303        $currentParams = $this->getQueryParams();
    186304
    187         $finalSlug = [];
    188         $copyCurrentSlug = $currentSlug;
    189 
    190         while ($p = array_shift($slug)) {
    191             if ('.' === $p) {
    192                 $finalSlug = $currentSlug;
    193             } elseif ('..' === $p) {
    194                 array_pop($copyCurrentSlug);
    195                 $finalSlug = $copyCurrentSlug;
    196             } else {
    197                 $finalSlug[] = $p;
    198             }
    199         }
    200 
    201         $passParams = $this->passParams($currentSlug, $finalSlug, $currentParams);
     305        $finalRoute = $this->resolveRoute($route, $currentRoute);
     306
     307        $passParams = $this->passParams($currentRoute, $finalRoute, $currentParams);
    202308        foreach ($passParams as $k => $v) {
    203309            if (!array_key_exists($k, $params)) {
     
    207313        }
    208314
    209 
    210         $ret = clone $this;
    211         $ret->slug = $finalSlug;
     315        // $routeParams = $this->routeParams;
     316        // if ($routeParams) {
     317            // $routeParams = $this->passParams($currentSlug, $finalSlug, $routeParams);
     318        // }
     319
     320        $routeParams = [];
     321        $ret = clone $this;
     322        $ret->route = $finalRoute;
    212323        $ret->queryParams = $params;
     324        $ret->routeParams = $routeParams;
    213325
    214326        return $ret;
     
    252364    }
    253365
    254     private function passParams(array $fromSlug, array $toSlug, array $params)
     366    private function passParams(string $fromSlug, string $toSlug, array $params)
    255367    {
    256368        $ret = [];
     
    312424        }
    313425
    314 
    315         // if ($ret){
    316             // echo "$fromSlug -> $toSlug<br>";
    317             // _print_r($params);
    318             // _print_r($ret);
    319             // exit;
    320         // }
    321         // echo "PASS: $fromSlug -> $toSlug<br>";
    322         // echo "COMMONPARENT: '$commonParent'<br>";
    323         // _print_r($params);
    324         // _print_r($ret);
    325 
    326         return $ret;
    327     }
    328 
    329     private static function determineCommonParent(array $fromSlug, array $toSlug): array
     426        return $ret;
     427    }
     428
     429    private static function determineCommonParent(string $fromSlug, string $toSlug): string
    330430    {
    331431    // the same slug
     
    334434        }
    335435
    336         $ret = [];
    337 
    338         $len = min(count($fromSlug), count($toSlug));
     436        $fromSlugArray = explode('/', $fromSlug);
     437        $toSlugArray = explode('/', $toSlug);
     438
     439        $ret = '';
     440
     441        $len = min(count($fromSlugArray), count($toSlugArray));
    339442        $matchLen = 0;
    340443        for ($i = 0; $i < $len; $i++) {
    341             if ($fromSlug[$i] === $toSlug[$i]) {
     444            if ($fromSlugArray[$i] === $toSlugArray[$i]) {
    342445                $matchLen = $i + 1;
    343446            } else {
     
    350453        }
    351454
    352         $ret = array_slice($fromSlug, 0, $matchLen);
    353 
    354         return $ret;
    355     }
    356 
    357     private static function determineStepsToOtherSlug(array $fromSlug, array $toSlug)
     455        $ret = array_slice($fromSlugArray, 0, $matchLen);
     456        $ret = join('/', $ret);
     457
     458        return $ret;
     459    }
     460
     461    private static function determineStepsToOtherSlug(string $fromSlug, string $toSlug): ?int
    358462    {
    359463    // the same slug
     
    362466        }
    363467
    364         $countFrom = count($fromSlug);
    365         $countTo = count($toSlug);
     468        $fromSlugArray = explode('/', $fromSlug);
     469        $toSlugArray = explode('/', $toSlug);
     470
     471        $countFrom = count($fromSlugArray);
     472        $countTo = count($toSlugArray);
    366473
    367474    // toSlug is child
     
    369476            $ok = true;
    370477            for ($i = 0; $i < $countFrom; $i++) {
    371                 if ($fromSlug[$i] !== $toSlug[$i]) {
     478                if ($fromSlugArray[$i] !== $toSlugArray[$i]) {
    372479                    $ok = false;
    373480                    break;
     
    382489            $ok = true;
    383490            for ($i = 0; $i < $countTo; $i++) {
    384                 if ($fromSlug[$i] !== $toSlug[$i]) {
     491                if ($fromSlugArray[$i] !== $toSlugArray[$i]) {
    385492                    $ok = false;
    386493                    break;
     
    393500        return null;
    394501    }
     502
     503    public function toString(): string
     504    {
     505        $ret = $this->getSlug();
     506        $params = $this->getQueryParams();
     507        if ($params) {
     508            $paramsString = http_build_query($params);
     509            if ($paramsString) {
     510                $ret .= $paramsString;
     511            }
     512        }
     513
     514        return $ret;
     515    }
    395516}
  • plain-event-calendar/trunk/vendor/plainware/http/src/Response.php

    r3372822 r3394866  
    2424        $ret = clone $this;
    2525        $ret->body = $body;
     26
    2627        return $ret;
    2728    }
  • plain-event-calendar/trunk/vendor/plainware/http/src/Router.php

    r3372822 r3394866  
    99    private $handler = [];
    1010    private $middleware = [];
    11     private $meta = [];
    1211    private $shortcut = [];
    1312    private $bridge = [];
    14     private string $slugSeparator = '/';
    15     private string $key = '';
    16 
    17     public function when(string $route): self
    18     {
    19         $this->key = $route;
    20 
    21         return $this;
    22     }
    23 
    24     public function whenAny(): self
    25     {
    26         return $this->when('*');
    27     }
    28 
    29     public function whenNot(string $route): self
    30     {
    31         return $this->when('!' . $route);
    32     }
    33 
     13    private $routeWithPlaceholder = [];
     14    private string $routeSeparator = '/';
     15    private string $tempRoute = '';
     16    private string $tempMethod = '';
     17
     18    private function getAllBridges(): array
     19    {
     20        $ret = [];
     21
     22        foreach ($this->bridge as $routePrefixPatternFrom => $routePrefixTo) {
     23            $routePrefixToLen = strlen($routePrefixTo);
     24            foreach (array_keys($this->handler) as $routePattern) {
     25                $from = null;
     26                if ($routePrefixTo === $routePattern) {
     27                    $from = $routePrefixPatternFrom;
     28                } elseif (($routePrefixTo . '/') === (substr($routePattern, 0, $routePrefixToLen) . '/')) {
     29                    $from = $routePrefixPatternFrom . substr($routePattern, $routePrefixToLen);
     30                }
     31                if (null !== $from) {
     32                    $ret[$from] = $routePattern;
     33                }
     34            }
     35        }
     36
     37        return $ret;
     38    }
     39
     40/**
     41 * Finds the route pattern with array of parameters from an input route.
     42 * Example:
     43 * customer/12/edit => [customer/{id}/edit, [id] => 12]
     44 *
     45 * @param string
     46 * @return array
     47 */
     48    public function parseRoute(string $route): array
     49    {
     50        foreach (array_keys($this->handler) as $routePattern) {
     51            list($matchedRoute, $params) = $this->getParsedRouteWithParams($route, $routePattern);
     52            if (false !== $matchedRoute) {
     53                return [$routePattern, $params];
     54            }
     55        }
     56
     57    // direct routes not found, try bridged ones
     58        $bridgedHanlers = $this->getAllBridges();
     59        foreach (array_keys($bridgedHanlers) as $routePattern) {
     60            list($matchedRoute, $params) = $this->getParsedRouteWithParams($route, $routePattern);
     61            if (false !== $matchedRoute) {
     62                return [$routePattern, $params];
     63            }
     64        }
     65
     66        return [false, []];
     67    }
     68
     69/**
     70 * Finds the parameters from an input route against pattern.
     71 * Example:
     72 * like user/12/order/24, user/{user}/order/{order} => ['user' => 12, 'order' => 24]
     73 *
     74 * @param string Requested route like user/12/order/24
     75 * @param string Route pattern like user/{user}/order/{order}
     76 * @param bool If true then route pattern can match prefix only, otherwise should fully match
     77 * @return array ['user/12/order/24', ['user' => 12, 'order' => 24]]
     78 */
     79    private function getParsedRouteWithParams(string $route, string $routePattern, bool $asPrefix = false)
     80    {
     81        if ($route === $routePattern) {
     82            return [$route, []];
     83        }
     84
     85        $routeArray = strlen($route) ? explode('/', $route) : [];
     86        $routePatternArray = strlen($routePattern) ? explode('/', $routePattern) : [];
     87
     88        $len = count($routeArray);
     89        $lenPattern = count($routePatternArray);
     90
     91        if (!$asPrefix) {
     92            if ($lenPattern !== $len) {
     93                return [false, []];
     94            }
     95        }
     96
     97        $params = [];
     98        for ($i = 0; $i < $lenPattern; $i++) {
     99            // with parameter?
     100            if ('{' === substr($routePatternArray[$i], 0, 1)) {
     101                $paramName = substr($routePatternArray[$i], 1, -1);
     102                $params[$paramName] = $routeArray[$i];
     103            } else {
     104                if ($routeArray[$i] !== $routePatternArray[$i]) {
     105                    return [false, []];
     106                }
     107            }
     108        }
     109
     110        $retRoute = join('/', array_slice($routeArray, 0, $lenPattern));
     111        $ret = [$retRoute, $params];
     112
     113        return $ret;
     114    }
     115
     116    public function when(string $route, string $method = 'ALL'): self
     117    {
     118        $this->tempRoute = $route;
     119        $this->tempMethod = $method;
     120
     121        if (false !== strpos($route, '{')) {
     122            $this->routeWithPlaceholder[$route] = explode('/', $route);
     123        }
     124
     125        return $this;
     126    }
     127
     128    public function whenPost(string $route): self
     129    {
     130        return $this->when($route, 'POST');
     131    }
     132
     133    public function whenGet(string $route): self
     134    {
     135        return $this->when($route, 'GET');
     136    }
     137
     138    public function whenPut(string $route): self
     139    {
     140        return $this->when($route, 'PUT');
     141    }
     142
     143    public function whenDelete(string $route): self
     144    {
     145        return $this->when($route, 'DELETE');
     146    }
     147
     148    // public function whenAny(): self
     149    // {
     150        // return $this->when('*');
     151    // }
     152
     153    // public function whenNot(string $route): self
     154    // {
     155        // return $this->when('!' . $route);
     156    // }
     157
     158/**
     159 * Handles all methods, usually used for web UI pages.
     160 *
     161 * @param string|array|callable $func
     162 * @return self
     163 */
    34164    public function handle($func): self
    35165    {
    36         $k = $this->key;
    37         $this->handler[$k] = $func;
    38 
    39         return $this;
    40     }
    41 
    42     public function middleware($func, int $order): self
     166        $k = $this->tempRoute;
     167        $method = $this->tempMethod;
     168        $this->handler[$k]['ALL'] = $func;
     169
     170        return $this;
     171    }
     172
     173    public function middleware($func, int $order = 50): self
    43174    {
    44175        if (($order < 9) or ($order > 99)) {
    45176            throw new \InvalidArgumentException(
    46                 __METHOD__ . '::router order should be > 9 and < 99, input was: ' . $order
     177                __METHOD__ . ': router order should be > 9 and < 99, input was: ' . $order
    47178            );
    48179        }
    49180
    50         $k = $this->key;
     181        $k = $this->tempRoute;
    51182        if (!isset($this->middleware[$k])) {
    52183            $this->middleware[$k] = [];
    53184        }
    54         $this->middleware[$k][] = [$func, $order];
    55 
    56         return $this;
    57     }
    58 
    59     public function meta(string $metaName, $func): self
    60     {
    61         $k = $this->key;
    62         if (!isset($this->meta[$k][$metaName])) {
    63             $this->meta[$k][$metaName] = [];
    64         }
    65         $this->meta[$k][$metaName][] = $func;
    66 
    67         return $this;
    68     }
    69 
    70     public function isShortcut(array $slugArray)
    71     {
    72         $slugString = join($this->slugSeparator, $slugArray);
    73         if (isset($this->shortcut[$slugString])) {
    74             $ret = $this->shortcut[$slugString];
    75             $ret = explode($this->slugSeparator, $ret);
    76         } else {
    77             return $this->shortcut[$slugString] ?? false;
    78         }
    79 
    80         return $ret;
    81     }
    82 
    83     public function shortcut(string $slug, string $realSlug): self
    84     {
    85         $this->shortcut[$slug] = $realSlug;
    86 
    87         return $this;
    88     }
    89 
    90     public function bridge(string $slugPrefix, string $realSlugPrefix, $func = null): self
    91     {
    92         $this->bridge[$slugPrefix] = $realSlugPrefix;
    93 
    94         return $this;
    95     }
    96 
    97     private function findAllSlugStrings(string $slug)
     185        $this->middleware[$k][] = ['handler' => $func, 'order' => $order];
     186
     187        return $this;
     188    }
     189
     190    public function isShortcut(string $slug)
     191    {
     192        return $this->shortcut[$slug] ?? false;
     193    }
     194
     195    public function shortcutTo(string $realRoute): self
     196    {
     197        $k = $this->tempRoute;
     198        $this->shortcut[$k] = $realRoute;
     199
     200        return $this;
     201    }
     202
     203    public function bridgeTo(string $realRoute): self
     204    {
     205        $route = $this->tempRoute;
     206        $this->bridge[$route] = $realRoute;
     207
     208        return $this;
     209    }
     210
     211    private function findHandler(string $slug, string $method)
     212    {
     213        if (isset($this->handler[$slug][$method])) {
     214            return $this->handler[$slug][$method];
     215        }
     216
     217        return $this->handler[$slug]['ALL'] ?? null;
     218    }
     219
     220    // the requested route may be a bridge to another so get all:
     221    // requested one and the one that will actually handle
     222    public function findAllRoutePatterns(string $routePattern): array
    98223    {
    99224        $ret = [];
    100         $ret[] = $slug;
    101 
    102     // check bridges
    103         foreach ($this->bridge as $prefixSlug => $prefixRealSlug) {
    104             $newSlug = null;
    105 
    106         // exact slug matched
    107             if ($prefixSlug === $slug) {
    108                 $newSlug = $prefixRealSlug;
    109         // prefix matched
    110             } elseif (($prefixSlug . $this->slugSeparator) === substr($slug, 0, strlen($prefixSlug) + 1)) {
    111                 $newSlug = $prefixRealSlug . substr($slug, strlen($prefixSlug));
    112                 // echo "BRIDGE '$slug' -> '$newSlug'<br>";
    113             }
    114 
    115         // have bridge!
    116             if (null !== $newSlug) {
    117                 $ret_ = $this->findAllSlugStrings($newSlug);
    118                 $ret = array_merge($ret, $ret_);
    119                 break;
    120             }
    121         }
    122 
    123         return $ret;
    124     }
    125 
    126     private function slugStringsWithWildcards(string $slug): array
     225        $ret[] = $routePattern;
     226
     227        $bridgedHanlers = $this->getAllBridges();
     228        $bridgedKey = $routePattern;
     229        while(isset($bridgedHanlers[$bridgedKey])) {
     230            $ret[] = $bridgedHanlers[$bridgedKey];
     231            $bridgedKey = $bridgedHanlers[$bridgedKey];
     232        }
     233
     234        return $ret;
     235    }
     236
     237    /**
     238    *
     239    * Gets a list of handlers for the route
     240    *
     241    * @return array Example: [['route' => admin/user, 'handler' => $func]]
     242    */
     243    public function getHandlerChain(string $routePattern, string $method): array
    127244    {
    128245        $ret = [];
    129         $ret[] = $slug;
    130 
    131         $slugArray = explode($this->slugSeparator, $slug);
    132 
    133         for ($i = count($slugArray) - 1; $i >= 0; $i--) {
    134             $ret_ = array_slice($slugArray, 0, $i);
    135             $ret_[] = '*';
    136             $ret[] = join($this->slugSeparator, $ret_);
    137         }
    138 
    139         return $ret;
    140     }
    141 
    142     public function getHandlerChain(array $slugArray): array
    143     {
    144         $ret = [];
    145 
    146         $slug = join($this->slugSeparator, $slugArray);
    147         $testSlugs = $this->findAllSlugStrings($slug);
    148         if (!$testSlugs) {
    149             return $ret;
     246
     247    // the requested route may be a bridge to another so get all:
     248    // requested one and the one that will actually handle
     249        $allRoutePatterns = $this->findAllRoutePatterns($routePattern);
     250
     251    // find all parent routes, it will be used for middleware
     252        $routeStack = [];
     253        foreach ($allRoutePatterns as $route_) {
     254            $routeArray = strlen($route_) ? explode($this->routeSeparator, $route_) : [];
     255            for ($i = 0; $i <= count($routeArray); $i++) {
     256                $parentRoute_ = join($this->routeSeparator, array_slice($routeArray, 0, $i));
     257                $routeStack[$parentRoute_] = $parentRoute_;
     258            }
    150259        }
    151260
    152261    // main handler
    153         foreach ($testSlugs as $k) {
    154             if (isset($this->handler[$k])) {
    155                 $ret[] = $this->handler[$k];
     262        foreach ($allRoutePatterns as $k) {
     263            $h = $this->findHandler($k, $method);
     264            if ($h) {
     265                $ret[] = ['route' => $routePattern, 'handler' => $h, 'order' => 100];
    156266                break;
    157267            }
     
    162272        }
    163273
    164     // middleware
     274    // for middleware check all parent routes
    165275        $retMiddleware = [];
    166 
    167         $testSlugsWithWildcards = [];
    168         foreach ($testSlugs as $slug_) {
    169             $testSlugsWithWildcards = array_merge($testSlugsWithWildcards, $this->slugStringsWithWildcards($slug_));
    170         }
    171         $testSlugs = $testSlugsWithWildcards;
    172 
    173         foreach (array_keys($this->middleware) as $k) {
    174             $ok = false;
    175             if (in_array($k, $testSlugs)) {
    176                 $ok = true;
    177             } else {
    178                 if ('!' === substr($k, 0, 1)) {
    179                     $k_ = substr($k, 1);
    180                     if (!in_array($k_, $testSlugs)) {
    181                         $ok = true;
    182                     }
    183                 }
    184             }
    185             if ($ok) {
    186                 $retMiddleware = array_merge($retMiddleware, $this->middleware[$k]);
    187             }
    188         }
    189 
    190         if ($retMiddleware) {
    191             usort($retMiddleware, [$this, 'sortRoutes']);
    192             $retMiddleware = array_column($retMiddleware, 0);
    193             $ret = array_merge($ret, $retMiddleware);
    194         }
    195 
    196         return $ret;
    197     }
    198 
    199     public function getMetaChain(array $slugArray, string $metaName): array
    200     {
    201         $ret = [];
    202 
    203         $slug = join($this->slugSeparator, $slugArray);
    204         $testSlugs = $this->findAllSlugStrings($slug);
    205         if (!$testSlugs) {
    206             return $ret;
    207         }
    208 
    209         $testSlugsWithWildcards = [];
    210         foreach ($testSlugs as $slug_) {
    211             $testSlugsWithWildcards = array_merge($testSlugsWithWildcards, $this->slugStringsWithWildcards($slug_));
    212         }
    213         $testSlugs = $testSlugsWithWildcards;
    214 
    215         $ret = [];
    216         foreach ($testSlugs as $k) {
    217             if (isset($this->meta[$k][$metaName])) {
    218                 $ret = array_merge($this->meta[$k][$metaName], $ret);
    219             }
    220         }
    221 // _print_r($this->meta);
    222 // _print_r($ret);
    223 
    224         // if ($ret) {
    225             // usort($ret, [$this, 'sortRoutes']);
    226             // $ret = array_column($ret, 0);
    227         // }
     276        foreach ($routeStack as $route_) {
     277            if (!isset($this->middleware[$route_])) {
     278                continue;
     279            }
     280            foreach ($this->middleware[$route_] as $h_) {
     281                $ret[] = ['route' => $route_] + $h_;
     282            }
     283        }
     284
     285        usort($ret, [$this, 'sortRoutes']);
    228286
    229287        return $ret;
     
    232290    private function sortRoutes(array $a, array $b)
    233291    {
    234         return ($b[1] - $a[1]);
     292        return ($b['order'] - $a['order']);
    235293    }
    236294}
  • plain-event-calendar/trunk/vendor/plainware/http/src/Server.php

    r3372822 r3394866  
    1212class Server
    1313{
    14     public App $app;
    15     public Router $router;
    16     public Uri $uri;
    17     public Server $self;
     14    public $self;
     15    public $app = App::class;
     16    public $router = Router::class;
     17    public $uri = Uri::class;
    1818    private string $prefix = '';
    1919
     
    2929        $request = $this->buildRequest();
    3030        $ret = $this->handle($request);
    31         $response = $this->prepareResponse($ret, $request);
    32 
    33         return $this->emitResponse($response);
    34     }
    35 
    36     protected function buildRequest(): Request
     31        $this->app->end();
     32        $response = $this->self->prepareResponse($ret, $request);
     33
     34        return $this->self->emitResponse($response);
     35    }
     36
     37    private function buildRequest(): Request
    3738    {
    3839        $request = new Request($this->prefix);
     
    4041    // determine and set slug
    4142        $slugParam = $this->uri->getSlugParam();
    42         $slugString = $request->getQueryParam($slugParam) ?? '';
     43        $slugValue = $request->getQueryParam($slugParam) ?? '';
     44        $slug = $this->uri->normalizeSlug($slugValue);
     45
     46    // dont't need slug as param anymore
    4347        $request = $request->withQueryParam($slugParam, null);
    4448
    45         $slug = $this->uri->slugFromString($slugString);
    4649        $request = $request->withSlug($slug);
    47 
    48         $shortcutSlug = $this->router->isShortcut($slug);
    49         if (false !== $shortcutSlug) {
    50             $request = $request->makeTo($shortcutSlug);
     50        while ($slug = $this->router->isShortcut($slug)) {
     51            $request = $request->makeTo($slug);
    5152        }
    5253
     
    5657    }
    5758
    58     public function handle(Request $request, ...$args)
    59     {
    60         $slug = $request->getSlug();
    61         $chain = $this->router->getHandlerChain($slug);
     59    public function handle(Request $request)
     60    {
     61        $route = $request->getRoute();
     62        $method = $request->getRequestMethod();
     63
     64        list($routePattern, $routeParams) = $this->router->parseRoute($route);
     65        if (false === $routePattern) {
     66            return null;
     67        }
     68
     69        if ($routePattern !== $route) {
     70            foreach ($routeParams as $k => $v) {
     71                $request = $request->withRouteParam($k, $v);
     72            }
     73        }
     74
     75        $chain = $this->router->getHandlerChain($routePattern, $method);
    6276        if (!$chain) {
    6377            return null;
    6478        }
    6579
    66 // _print_r($chain);
    67         $handler = $this->buildHandler($chain);
    68         $ret = call_user_func($handler, $request, ...$args);
    69 
    70         return $ret;
    71     }
    72 
    73     public function meta(Request $request, string $metaName, $default = null)
    74     {
    75         $slug = $request->getSlug();
    76         $chain = $this->router->getMetaChain($slug, $metaName);
    77 
    78 // if ('can' === $metaName) {
    79 // echo count($chain);
    80     // if ($chain) {
    81         // _print_r($chain);
    82     // }
    83 // }
    84         $func = function (Request $request) use ($default) {
    85             return $default;
    86         };
    87         array_unshift($chain, $func);
    88 
    89         if (!$chain) {
    90             return null;
    91         }
    92 
    9380        $handler = $this->buildHandler($chain);
    9481        $ret = call_user_func($handler, $request);
     
    10087    private function buildHandler(array $chain): callable
    10188    {
    102         $func = array_shift($chain);
     89        $firstElement = array_shift($chain);
     90        $func = $firstElement['handler'];
    10391        $func = $this->factory($func);
    10492
    105         foreach ($chain as $decorator) {
     93        foreach ($chain as $chainElement) {
     94            $decorator = $chainElement['handler'];
    10695            $decorator = $this->factory($decorator);
    107             $func = function (Request $request, ...$args) use ($decorator, $func) {
    108                 $args[] = $func;
    109                 return call_user_func($decorator, $request, ...$args);
     96            $func = function (Request $request) use ($decorator, $func) {
     97                return call_user_func($decorator, $request, $func);
    11098            };
    11199        }
     
    117105    {
    118106        if ($ret instanceof Response) {
     107            $body = $ret->getBody();
     108            if (is_array($body)) {
     109                $body = json_encode($body);
     110                $ret = $ret->withBody($body);
     111            }
     112
    119113            return $ret;
    120114        }
     
    156150                ->withHeader('Location', $to)
    157151                ;
     152
    158153            return $resp;
    159154        }
     
    176171                ->withHeader('content-type', 'application/json')
    177172                ;
     173
    178174            return $resp;
    179175        }
     
    225221        if (!$bufferLength) {
    226222            $body = $response->getBody();
    227             return strlen($body) ? $body : $statusCode;
     223            // return ((null !== $body) && strlen($body)) ? $body : $statusCode;
     224            return $body;
    228225        }
    229226
  • plain-event-calendar/trunk/vendor/plainware/http/src/Uri.php

    r3372822 r3394866  
    77class Uri
    88{
    9     public App $app;
     9    public $app = App::class;
    1010    private $slugParam = 'a';
    1111    private $paramPrefix = '';
     
    2020    public const CONTEXT_SYSTEM = 'system';
    2121
    22     public function slugFromString(string $slugString): array
    23     {
    24         return explode($this->slugSeparator, $slugString);
    25     }
    26 
    27     public function slugToString(array $slug): string
    28     {
    29         return join($this->slugSeparator, $slug);
    30     }
    31 
    3222    public function setParamPrefix(string $prefix): self
    3323    {
     
    4737    }
    4838
    49     public function to(array $slug, array $params = [], string $context = ''): string
    50     {
    51         $slugString = join($this->slugSeparator, $slug);
     39    public function normalizeSlug(string $slugValue): string
     40    {
     41        if ('/' !== $this->slugSeparator) {
     42            $slugValue = str_replace($this->slugSeparator, '/', $slugValue);
     43        }
     44
     45        return $slugValue;
     46    }
     47
     48    public function to(string $slug, array $params = [], string $context = ''): string
     49    {
    5250        $slugParam = $this->getSlugParam();
    53         $params[$slugParam] = $slugString;
     51
     52        if ('/' !== $this->slugSeparator) {
     53            $slugValue = str_replace('/', $this->slugSeparator, $slug);
     54        } else {
     55            $slugValue = $slug;
     56        }
     57        $params[$slugParam] = $slugValue;
    5458
    5559        $ks = array_keys($params);
  • plain-event-calendar/trunk/vendor/plainware/ui-ajax/boot.php

    r3372822 r3394866  
    77use Plainware\Ui\Component\Main;
    88
    9 return [
    10     App::class => function (App $app) {
    11         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    12     },
     9return function (App $app) {
     10    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    1311
    14     Ui::class => function (Ui $ui) {
     12    $app->onBoot(Ui::class, function ($ui) {
    1513        $ui
    1614            ->renderer(Main::class, Renderer\MainRendererDecorator::class)
    1715            ;
    18     },
    19 ];
     16    });
     17};
  • plain-event-calendar/trunk/vendor/plainware/ui-ajax/src/Renderer/MainRendererDecorator.php

    r3372822 r3394866  
    44
    55use Plainware\Http\Uri;
     6use Plainware\Http\Request;
    67use Plainware\Ui\Component\Main;
    78use Plainware\Ui\Component\HtmlElement;
     
    910final class MainRendererDecorator
    1011{
    11     public Uri $uri;
     12    public $uri = Uri::class;
    1213
    13     public function __invoke(Main $el, callable $next)
     14    public function __invoke(Main $el, Request $request, callable $next)
    1415    {
    1516        if ($el->getLayoutId()) {
    16             return ($next)($el);
     17            return ($next)($el, $request);
    1718        }
    1819
     
    2930        $el->wrapBy($wrapper);
    3031
    31         return ($next)($el);
     32        return ($next)($el, $request);
    3233    }
    3334}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/boot.php

    r3372822 r3394866  
    1515use Plainware\Ui\Component\Form\Button;
    1616
    17 return [
    18     App::class => function (App $app) {
    19         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    20     },
     17return function (App $app) {
     18    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    2119
    22     Ui::class => function (Ui $ui) {
     20    $app->onBoot(Ui::class, function ($ui) {
    2321        $ui
    2422            ->renderer(Main::class, Renderer\MainRendererDecorator::class)
    25         ;
     23            ;
    2624        if (is_admin()) {
    2725            $ui
     
    3634                ;
    3735        }
    38     },
    39 ];
     36    });
     37};
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminLinkRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Link;
    67
    78class AdminLinkRenderer
    89{
    9     public function __invoke(Link $el, callable $next)
     10    public function __invoke(Link $el, Request $request, callable $next)
    1011    {
    1112        if ($el->isMenu()) {
     
    1314        }
    1415
    15         return $next($el);
     16        return $next($el, $request);
    1617    }
    1718}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminMainMenuRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Core\Translate;
    6 use Plainware\Http\Request;
    77use Plainware\Http\Uri;
    88use Plainware\Ui\Ui;
     
    1515class AdminMainMenuRenderer
    1616{
    17     public Ui $ui;
    18     public Uri $uri;
     17    public $ui = Ui::class;
     18    public $uri = Uri::class;
    1919    public Translate $translate;
    2020    public TabMenuRenderer $tabMenuRenderer;
    2121    private $wpAdminPageSlug = 'sh5';
    2222
    23     public function __invoke(MainMenu $el, callable $next)
     23    public function __invoke(MainMenu $el, Request $request, callable $next)
    2424    {
    2525        $ret = '';
     
    3535        }
    3636
    37         $currentSlug = $el->getCurrentSlug() ?? [];
     37        $currentSlug = $el->getCurrentSlug() ?? '';
     38        $currentSlugArray = strlen($currentSlug) ? explode('/', $currentSlug) : [];
    3839
    3940        $items = $el->getItems();
     
    4647
    4748            if ($item instanceof Link) {
    48                 $thisSlug = $item->getSlug();
     49                $request_ = $request->makeTo($item->getSlug(), $item->getParams());
     50                $thisSlug = $request_->getSlug();
     51                $thisSlugArray = strlen($thisSlug) ? explode('/', $thisSlug) : [];
    4952
    50                 $len = min(count($thisSlug), count($currentSlug));
     53                $len = min(count($thisSlugArray), count($currentSlugArray));
    5154                $isOn = true;
    5255                for ($i_ = 0; $i_ < $len; $i_++) {
    53                     if ($thisSlug[$i_] !== $currentSlug[$i_]) {
     56                    if ($thisSlugArray[$i_] !== $currentSlugArray[$i_]) {
    5457                        $isOn = false;
    5558                        break;
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminMenuRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Menu;
    67use Plainware\Ui\Component\Link;
     
    910class AdminMenuRenderer
    1011{
    11     public function __invoke(Menu $el, callable $next)
     12    public function __invoke(Menu $el, Request $request, callable $next)
    1213    {
    1314        $items = $el->getItems();
     
    2526        }
    2627
    27         return $next($el);
     28        return $next($el, $request);
    2829    }
    2930}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminNavRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
    5 use Plainware\Ui\Ui;
    6 use Plainware\Ui\Component\Nav;
     5use Plainware\Http\Request;
    76use Plainware\Ui\Component\Link;
    87
    98class AdminNavRenderer
    109{
    11     public Ui $ui;
    12 
    13     public function __invoke(Nav $el, callable $next)
     10    public function __invoke(Nav $el, Request $request, callable $next)
    1411    {
    1512        $items = $el->getItems();
     
    2017        }
    2118
    22         return $next($el);
     19        return $next($el, $request);
    2320    }
    2421}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminTabMenuRenderer.php

    r3372822 r3394866  
    1212class AdminTabMenuRenderer
    1313{
    14     public Ui $ui;
    15     public Uri $uri;
     14    public $ui = Ui::class;
     15    public $uri = Uri::class;
    1616
    17     public function __invoke(TabMenu $el)
     17    public function __invoke(TabMenu $el, Request $request)
    1818    {
    1919        $items = $el->getItems();
     
    2828        $ret = [];
    2929
     30        $ret[] = '<div class="pw-header-tabmenu">';
    3031        $ret[] = '<div class="nav-tab-wrapper">';
    3132        foreach ($items as $itemId => $item) {
     
    3738                }
    3839
    39                 $v = $this->ui->render($item);
     40                $v = $this->ui->render($item, $request);
    4041                if (!strlen($v)) {
    4142                    continue;
     
    4546            } else {
    4647                $ret[] = '<span>';
    47                 $v = $this->ui->render($item);
     48                $v = $this->ui->render($item, $request);
    4849                $ret[] = $v;
    4950                $ret[] = '</span>';
    5051            }
    5152        }
     53        $ret[] = '</div>';
    5254        $ret[] = '</div>';
    5355
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminTableRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Table;
    67
    78class AdminTableRenderer
    89{
    9     public function __invoke(Table $el, callable $next)
     10    public function __invoke(Table $el, Request $request, callable $next)
    1011    {
    1112        // return $next($el);
     
    1415        // $el->withAttr('class', 'striped');
    1516
    16         return $next($el);
     17        return $next($el, $request);
    1718    }
    1819}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/AdminUlRenderer.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Ul;
    67use Plainware\Ui\Component\Link;
     
    89class AdminUlRenderer
    910{
    10     public function __invoke(Ul $el, callable $next): string
     11    public function __invoke(Ul $el, Request $request, callable $next): string
    1112    {
    1213        if (!$el->isMenu()) {
    13             return $next($el);
     14            return $next($el, $request);
    1415        }
    1516
     
    2122        }
    2223
    23         return $next($el);
     24        return $next($el, $request);
    2425    }
    2526}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/Form/AdminButtonRendererDecorator.php

    r3333400 r3394866  
    33namespace Plainware\UiWordpress\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\Button;
    67
    78class AdminButtonRendererDecorator
    89{
    9     public function __invoke(Button $el, callable $next)
     10    public function __invoke(Button $el, Request $request, callable $next)
    1011    {
    1112        $el->withAttr('class', 'button');
     
    1617        }
    1718
    18         return $next($el);
     19        return $next($el, $request);
    1920    }
    2021}
  • plain-event-calendar/trunk/vendor/plainware/ui-wordpress/src/Renderer/MainRendererDecorator.php

    r3372822 r3394866  
    33namespace Plainware\UiWordpress\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Http\Uri;
    67use Plainware\Ui\Ui;
     
    910final class MainRendererDecorator
    1011{
    11     public Ui $ui;
    12     public Uri $uri;
     12    public $ui = Ui::class;
     13    public $uri = Uri::class;
    1314
    14     public function __invoke(Main $el, callable $next)
     15    public function __invoke(Main $el, Request $request, callable $next)
    1516    {
    1617// echo __METHOD__ . '<br>';
    17         $nextRet = ($next)($el);
     18        $nextRet = ($next)($el, $request);
    1819
    1920        if ($el->getLayoutId()) {
     
    5859
    5960        $ret[] = '<div class="wrap">';
    60         $ret[] = $this->ui->render($nextRet);
     61        $ret[] = $this->ui->render($nextRet, $request);
    6162        $ret[] = '</div>';
    6263
  • plain-event-calendar/trunk/vendor/plainware/ui/assets/core.css

    r3372822 r3394866  
    228228#pw2 i > img { display: block; margin: 0; padding: 0; }
    229229#pw2 i > svg { vertical-align: baseline; display: inline-block; }
    230 #pw2 span + i, #pw2 i + span, #pw2 i + i { margin-inline-start: .25em; }
     230#pw2 span + i, #pw2 i + span, #pw2 i + i {margin-inline-start: .25em;}
     231#pw2 a > span:not(:only-child), #pw2 a > i:not(:only-child) {display: inline-block;}
    231232
    232233/* inputs */
     
    414415#pw2 li strong > a { color: inherit; }
    415416#pw2 li strong > a:hover { background-color: var(--nav-bg-hover-strong); }
    416 #pw2 .pw-menu a, #pw2 a.pw-menu {display: block;}
     417#pw2 .pw-menu a, #pw2 a.pw-menu {display: block; margin: 0;}
    417418#pw2 th details[open] summary, #pw2 details[open] summary {margin-bottom: .25em;}
    418419#pw2 td.pw-danger, #pw th.pw-danger {background-color: #fcc;}
     
    426427#pw2 .pw-header-user {margin: 0 0 .5em 0; padding: 0 0 .25em 0; border-bottom: var(--border-color) 1px solid;}
    427428#pw2 .pw-header-mainmenu {margin: 0 0 .5em 0;}
    428 #pw2 .pw-header-breadcrumbs {margin: 0 0 .25em 0; font-size: .9em;}
     429#pw2 .pw-header-tabmenu {margin: 0 0 1em 0;}
     430#pw2 .pw-header-breadcrumbs {margin: 0 0 .25em 0; font-size: .9em; padding: 0 0;}
    429431#pw2 .pw-header-title {margin: 0 0 1em 0;}
    430432#pw2 .pw-header-flashmessage {margin: 0 0 1em 0;}
     433#pw2 .pw-footer-pagemenu {margin: .5em 0 0 0;}
    431434
    432435#pw2 label[for] {display: block; width: 100%; padding: 0; margin: 0;}
  • plain-event-calendar/trunk/vendor/plainware/ui/boot.php

    r3372822 r3394866  
    77use Plainware\Ui\Ui;
    88
    9 return [
    10     App::class => function (App $app) {
    11         $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    12     },
     9return function (App $app) {
     10    $app->autoload(__NAMESPACE__, __DIR__ . '/src/');
    1311
    14     Router::class => function (Router $router) {
     12    $app->onBoot(Router::class, function ($router) {
    1513        $router
    16             ->whenAny()
     14            // ->whenAny()
     15                // ->middleware(Middleware\UiMiddleware::class, 85)
     16                // ->middleware(Middleware\ExceptionMiddleware::class, 14)
     17                // ->middleware(Middleware\MainFlashMessageMiddleware::class, 90)
     18
     19            ->when('')
    1720                ->middleware(Middleware\UiMiddleware::class, 85)
    1821                ->middleware(Middleware\ExceptionMiddleware::class, 14)
    19                 ->middleware(Middleware\MainFlashMessageMiddleware::class, 90)
     22                // ->middleware(Middleware\MainFlashMessageMiddleware::class, 90)
     23                ->middleware(Middleware\PageLayoutMiddleware::class, 90)
    2024
    21             ->whenNot('install')
    22                 ->middleware(Middleware\NavMiddleware::class, 90)
    23                 ->middleware(Middleware\MainMenuMiddleware::class, 90)
    24                 ->middleware(Middleware\MainBreadcrumbsMiddleware::class, 90)
     25            // ->whenNot('install')
     26                // ->middleware(Middleware\PageLayoutMiddleware::class, 90)
     27            ;
     28    });
    2529
    26         /* init main menu */
    27             ->when('')
    28                 ->meta('menu', [Middleware\MainMenuMiddleware::class, 'initMainMenu'])
    29             ;
    30     },
    31 
    32     Ui::class => function (Ui $ui) {
     30    $app->onBoot(Ui::class, function ($ui) {
    3331        $ui
    3432            ->renderer(Component\AbstractTag::class, Renderer\HtmlElementRenderer::class)
     
    4341            ->renderer(Component\StartEnd::class, Renderer\StartEndRenderer::class)
    4442            ->renderer(Component\Dl::class, Renderer\DlRenderer::class)
    45             ->renderer(Component\DateLink::class, Renderer\DateLinkRenderer::class)
    4643            ->renderer(Component\FlashMessage::class, Renderer\FlashMessageRenderer::class)
    47             ->renderer(Component\TimeLink::class, Renderer\TimeLinkRenderer::class)
    4844            ->renderer(Component\Pager::class, Renderer\PagerRenderer::class)
    4945            ->renderer(Component\Nav::class, Renderer\NavRenderer::class)
     
    5349            ->renderer(Component\TabMenu::class, Renderer\TabMenuRenderer::class)
    5450            ->renderer(Component\Grid::class, Renderer\GridRenderer::class)
    55             ->renderer(Component\MetaRequest::class, Renderer\MetaRequestRenderer::class)
    5651            ->renderer(Component\MainMenu::class, Renderer\MainMenuRenderer::class)
    5752            ->renderer(Component\TabbedMenu::class, Renderer\TabbedMenuRenderer::class)
     
    7772            ->renderer(Component\Form\TimeRangeInput::class, Renderer\Form\TimeRangeInputRenderer::class)
    7873            ;
    79     },
    80 ];
     74    });
     75};
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Component/Form/DateInput.php

    r3332867 r3394866  
    1212    {
    1313        $ret = $request->getPostParam($this->getName());
     14        // $ret = new \DateTimeImmutable($ret);
    1415
    1516        return $ret;
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Component/Form/DatePeriodInput.php

    r3372822 r3394866  
    2828    }
    2929
     30    public function setValue($v): self
     31    {
     32        $qty = (int) substr($v, 0, -1);
     33        $unit = substr($v, -1);
     34
     35        $this->inputQty->setValue($qty);
     36        $this->inputUnit->setValue($unit);
     37
     38        return parent::setValue($v);
     39    }
     40
    3041    public function grab(Request $request)
    3142    {
     
    4253            ;
    4354
    44         $d1 = 20250820;
    45         $d2 = 20250820;
    46         $ret = new DatePeriod($d1, $d2, $retUnit, $retQty);
     55        $ret = $retQty . $retUnit;
    4756
    4857        return $ret;
     
    5867        return $this->inputUnit;
    5968    }
     69
     70    public static function expand(string $v): array
     71    {
     72        $qty = (int) substr($v, 0, -1);
     73        $range = substr($v, -1);
     74        $match = ['d' => 'day', 'w' => 'week', 'm' => 'month'];
     75        $period = $match[$range] ?? $match[current(array_keys($match))];
     76
     77        return [$qty, $period];
     78    }
    6079}
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Component/Link.php

    r3372822 r3394866  
    55final class Link extends AbstractTag
    66{
    7     private array $slug = [];
     7    private ?string $slug = null;
    88    private array $params = [];
    99    private $label;
     
    3535    }
    3636
    37     public function getSlug(): array
     37    public function getSlug(): string
    3838    {
    3939        return $this->slug;
     
    4242    public function setSlug(string $slug): self
    4343    {
    44         $this->slug = explode('/', $slug);
     44        $this->slug = $slug;
    4545
    4646        return $this;
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Component/Menu.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Component;
    44
     5use Plainware\Ui\Component\Link;
    56use Plainware\Ui\Component\Container;
    67
     
    89{
    910    private bool $isVertical = false;
     11    private $currentSlug = null;
     12
     13    public function addLink(int $order, string $to, array $params = [])
     14    {
     15        $link = new Link($to, $params);
     16
     17        return $this->add($order, $link);
     18    }
     19
     20    public function setCurrentSlug($currentSlug): self
     21    {
     22        $this->currentSlug = $currentSlug;
     23
     24        return $this;
     25    }
     26
     27    public function getCurrentSlug()
     28    {
     29        return $this->currentSlug;
     30    }
    1031
    1132    public function setVertical(bool $on = true): self
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Component/TabMenu.php

    r3372822 r3394866  
    77    private array $items = [];
    88    private string $currentItemId;
     9    private ?string $currentRoute = null;
    910
    1011    public function setActive(string $id): self
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Middleware/ExceptionMiddleware.php

    r3372822 r3394866  
    99class ExceptionMiddleware
    1010{
    11     public Ui $ui;
     11    public $ui = Ui::class;
    1212
    1313    public function __invoke(Request $request, callable $next)
     
    2121            $ret->setTitle('__Error__');
    2222
    23             $ret = $this->ui->render($ret);
     23            // $ret = $this->ui->render($ret, $request);
    2424        }
    2525
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Middleware/MainFlashMessageMiddleware.php

    r3372822 r3394866  
    1111final class MainFlashMessageMiddleware
    1212{
    13     public Ui $ui;
    14     public Uri $uri;
     13    public $ui = Ui::class;
     14    public $uri = Uri::class;
    1515
    1616    public function __invoke(Request $request, callable $next)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Middleware/MainMenuMiddleware.php

    r3372822 r3394866  
    55use Plainware\Http\Request;
    66use Plainware\Ui\Ui;
     7use Plainware\Ui\PageMap;
    78use Plainware\Ui\Component\Link;
    89use Plainware\Ui\Component\Main;
    910use Plainware\Ui\Component\HtmlElement;
    10 use Plainware\Ui\Component\MainMenu;
     11use Plainware\Ui\Component\Menu;
    1112use Plainware\Ui\Component\MetaRequest;
    1213
    1314final class MainMenuMiddleware
    1415{
    15     public Ui $ui;
    16 
    17     public function initMainMenu(Request $request): MainMenu
    18     {
    19         return new MainMenu();
    20     }
     16    public $ui = Ui::class;
     17    public PageMap $pageMap;
    2118
    2219    public function __invoke(Request $request, callable $next)
    2320    {
    2421        $ret = $next($request);
    25 
    2622        if (!($ret instanceof Main)) {
    2723            return $ret;
    2824        }
    2925
     26    // main menu
     27        $indexRequest = $request->makeTo([]);
     28
     29        $indexSlugString = join('/', $indexRequest->getSlug());
     30        $mainMenuItems = $this->pageMap->getMenuItems($indexSlugString);
     31       
     32        // echo __METHOD__;
     33        // _print_r($mainMenuItems);
     34       
     35        return $ret;
     36
     37
     38
    3039        $currentSlug = $request->getSlug();
    3140
    32     // main menu
    3341        $indexRequest = $request->makeTo([]);
    3442        $mainMenu = (new MetaRequest($indexRequest, 'menu'))
    3543            ->addCallback(
    36                 function (MainMenu $mainMenu) use ($currentSlug) {
     44                function (Menu $mainMenu) use ($currentSlug) {
    3745                    $mainMenu->setCurrentSlug($currentSlug);
    3846                }
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Middleware/UiMiddleware.php

    r3372822 r3394866  
    66use Plainware\Http\Redirect;
    77use Plainware\Http\Response;
    8 use Plainware\Http\Server;
    98use Plainware\Ui\Ui;
    109use Plainware\Ui\Component\Main;
     
    1211class UiMiddleware
    1312{
    14     public Ui $ui;
    15     public Server $server;
     13    public $ui = Ui::class;
    1614    private $layoutParamName = 'layout-';
    1715
    1816    public function __invoke(Request $request, callable $next)
    1917    {
    20         $this->ui->withRequest($request);
    21 
    2218        $ret = $next($request);
    2319        if ($ret instanceof Response) {
     
    4945        }
    5046
    51         $ret = $this->ui->render($ret);
     47        $ret = $this->ui->render($ret, $request);
    5248
    5349        return $ret;
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/BreadcrumbsRenderer.php

    r3372822 r3394866  
    1616        }
    1717
    18         $items = array_reverse($items);
     18        // $items = array_reverse($items);
    1919
    2020        $ret = new Menu();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/DetailsRenderer.php

    r3372822 r3394866  
    88final class DetailsRenderer
    99{
    10     public Ui $ui;
     10    public $ui = Ui::class;
    1111
    1212    public function __invoke(Details $el)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/DlRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Ui;
    6 use Plainware\Http\Request;
    77use Plainware\Ui\Component\Dl;
    88use Plainware\Ui\Component\Table;
     
    1010class DlRenderer
    1111{
    12     public Ui $ui;
     12    public $ui = Ui::class;
    1313
    14     public function __invoke(Dl $el)
     14    public function __invoke(Dl $el, Request $request)
    1515    {
    1616        $items = $el->getItems();
     
    3232            $j_ = 0;
    3333            foreach ($item as $item2) {
    34                 $v = $this->ui->render($item2);
     34                $v = $this->ui->render($item2, $request);
    3535                if (!strlen($v)) {
    3636                    continue;
     
    4141                $countItem = count($item);
    4242                if (1 === $j_) {
    43                     $k = $this->ui->render($label);
     43                    $k = $this->ui->render($label, $request);
    4444
    4545                    $ret->withCell($rowId, 'head')
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/FlashMessageRenderer.php

    r3372822 r3394866  
    1010final class FlashMessageRenderer
    1111{
    12     public Ui $ui;
     12    public $ui = Ui::class;
    1313
    1414    public function __invoke(FlashMessage $el)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/ButtonRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\HtmlElement;
    67use Plainware\Ui\Component\Form\Button;
     
    910class ButtonRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(Button $el)
     14    public function __invoke(Button $el, Request $request)
    1415    {
    15         $name = $this->ui->getRequest()->getParamName($el->getName());
     16        $name = $request->getParamName($el->getName());
    1617
    1718        $isDanger = $el->isDanger();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/CheckboxInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Ui;
    67use Plainware\Ui\Component\HtmlElement;
     
    910class CheckboxInputRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(CheckboxInput $el)
     14    public function __invoke(CheckboxInput $el, Request $request)
    1415    {
    1516        // $name = $el->getName();
    16         $name = $this->ui->getRequest()->getParamName($el->getName());
     17        $name = $request->getParamName($el->getName());
    1718
    1819        $value = (string) $el->getValue();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/ColorPickerInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\ColorPickerInput;
    67use Plainware\Ui\Component\Form\RadioInput;
    78use Plainware\Ui\HtmlHelper;
    89use Plainware\Ui\Ui;
    9 use Plainware\Time\Time;
    1010
    1111class ColorPickerInputRenderer
    1212{
    13     public Ui $ui;
    14     public Time $t;
     13    public $ui = Ui::class;
    1514
    1615    private $colors = [
     
    4645*/
    4746
    48     public function __invoke(ColorPickerInput $el): string
     47    public function __invoke(ColorPickerInput $el, Request $request): string
    4948    {
    5049        $ret = [];
     
    8079            $attr['title'] = $color;
    8180            $ret[] = '<label ' . HtmlHelper::attr($attr) . '>';
    82             $ret[] = $this->ui->render($input);
     81            $ret[] = $this->ui->render($input, $request);
    8382            $ret[] = '</label>';
    8483            $ret[] = '</li>';
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/ContentInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\ContentInput;
    6 use Plainware\Ui\Ui;
    77
    88final class ContentInputRenderer
    99{
    10     public Ui $ui;
    11 
    12     public function __invoke(ContentInput $el): string
     10    public function __invoke(ContentInput $el, Request $request)
    1311    {
    1412        $val = $el->getValue();
    15         if (null === $val) {
    16             return '';
    17         }
    1813
    19         return $this->ui->render($el->getValue());
     14        return $val ?? '';
    2015    }
    2116}
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/DateInputRenderer.php

    r3333400 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
    5 use Plainware\Time\Time;
     5use Plainware\Http\Request;
     6use Plainware\DateTime\DateTimeFormatter;
    67use Plainware\Ui\Component\Form\Button;
    78use Plainware\Ui\Component\Form\DateInput;
     
    1112class DateInputRenderer
    1213{
    13     public Time $t;
    14     public Ui $ui;
    15 
    16     public function __invoke(DateInput $el): string
     14    public $dtf = DateTimeFormatter::class;
     15    public $ui = Ui::class;
     16
     17    public function __invoke(DateInput $el, Request $request): string
    1718    {
    18         $name = $this->ui->getRequest()->getParamName($el->getName());
     19        $name = $request->getParamName($el->getName());
    1920        $value = $el->getValue();
     21
    2022
    2123        if (null === $value) {
    2224            $value = '';
     25        }
     26        if ($value instanceof \DateTimeInterface) {
     27            $value = $value->format('Ymd');
    2328        }
    2429        if (strlen($value) < 8) {
     
    3035        $nameD = $name . '_d';
    3136
    32         if (!strlen($value)) {
    33             $value = $this->t->getDate($this->t->getNow());
    34         }
    35 
    36         $valueY = $this->t->getYear($value);
    37         $valueM = $this->t->getMonth($value);
    38         $valueD = $this->t->getDay($value);
     37        $dt = strlen($value) ? new \DateTimeImmutable($value) : new \DateTimeImmutable();
     38        $value = $dt->format('Ymd');
    3939
    4040        $attr = [];
     
    4242        $attr['name'] = $name;
    4343        $attr['value'] = $value;
    44         $attr['title'] = $this->t->formatDateFull($value);
     44        $attr['title'] = $this->dtf->formatDateFull($dt);
    4545        $attr['data-pw-input-date'] = true;
    4646
     
    5454        $ret = join('', $ret);
    5555
    56         $ret = $this->renderStyle($name) . $ret . $this->renderJs($name, $value);
     56        $ret = $this->renderStyle($name) . $ret . $this->renderJs($name, $value, $request);
    5757
    5858        return $ret;
     
    7979    }
    8080
    81     public function renderJs($inputName)
     81    public function renderJs($inputName, $inputValue, Request $request)
    8282    {
    8383        // static $alreadyShown = false;
     
    8787        // $alreadyShown = true;
    8888
    89         $dictMonth = $this->t->getFormatMonths();
    90         $dictMonthFull = $this->t->getFormatMonthsFull();
    91         $dictWkd = $this->t->getFormatWeekdays();
     89        $dictMonth = $this->dtf->getMonthNames();
     90        $dictMonthFull = $this->dtf->getMonthFullNames();
     91        $dictWkd = $this->dtf->getDayOfWeekNames();
    9292
    9393        ob_start();
     
    9595<script>
    9696( function(){
    97 const dateFormat = "<?php echo $this->t->getDateFormat(); ?>";
     97const dateFormat = "<?php echo $this->dtf->getDateFormat(); ?>";
    9898const monthLabel = ["<?php echo join('","', $dictMonth); ?>"];
    9999const monthLabelFull = ["<?php echo join('","', $dictMonthFull); ?>"];
     
    221221        $btn->withAttr('data-pw-input-date', '{data}');
    222222        ?>
    223     const btnTemplate = '<?php echo $this->ui->render($btn); ?>';
     223    const btnTemplate = '<?php echo $this->ui->render($btn, $request); ?>';
    224224    ret += parseTemplate(btnTemplate, {data: 'calendar:' + val, label: formatDate(val)});
    225225
     
    254254        $btn->setPrimary(false);
    255255        ?>
    256     const btnTemplate = '<?php echo $this->ui->render($btn); ?>';
     256    const btnTemplate = '<?php echo $this->ui->render($btn, $request); ?>';
    257257    ret += parseTemplate(btnTemplate, {
    258258        data: 'calendar:' + formatDateDb(prevY, prevM, 1),
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/DatePeriodInputRenderer.php

    r3372822 r3394866  
    55use Plainware\Ui\Component\Form\DatePeriodInput;
    66use Plainware\Ui\Component\InlineList;
    7 use Plainware\Time\Time;
    87
    98class DatePeriodInputRenderer
    109{
    11     public Time $t;
    12 
    1310    public function __invoke(DatePeriodInput $el)
    1411    {
    1512        $name = $el->getName();
    16         $period = $el->getValue() ?? $this->t->makeDatePeriod(1, 'w');
    1713
    18         $v = $period->getQty();
    19         $el->getInputQty()
    20             ->setName($name . '_qty')
    21             ->setValue($v)
    22             ;
    23 
    24         if ($period->isMonth()) {
    25             $v = 'm';
    26         } elseif ($period->isDay()) {
    27             $v = 'd';
    28         } elseif ($period->isWeek()) {
    29             $v = 'w';
    30         }
    31 
    32         $options = $el->getInputUnit()->getOptions();
    33         if (!isset($options[$v])) {
    34             $v = current(array_keys($options));
    35         }
    36         $el->getInputUnit()
    37             ->setName($name . '_unit')
    38             ->setValue($v)
    39             ;
     14        $el->getInputQty()->setName($name . '_qty');
     15        $el->getInputUnit()->setName($name . '_unit');
    4016
    4117        $ret = new InlineList();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/HiddenInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\HiddenInput;
    67use Plainware\Ui\HtmlHelper;
     
    910class HiddenInputRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(HiddenInput $el): string
     14    public function __invoke(HiddenInput $el, Request $request): string
    1415    {
    1516        $ret = [];
     
    1920        $attr['type'] = 'hidden';
    2021
    21         $name = $this->ui->getRequest()->getParamName($el->getName());
     22        $name = $request->getParamName($el->getName());
    2223        $attr['name'] = $name;
    2324
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/NumberInputRenderer.php

    r3332867 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\NumberInput;
    67use Plainware\Ui\HtmlHelper;
     
    910class NumberInputRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(NumberInput $el): string
     14    public function __invoke(NumberInput $el, Request $request): string
    1415    {
    1516        $ret = [];
     
    1920        $attr['type'] = 'number';
    2021
    21         $name = $this->ui->getRequest()->getParamName($el->getName());
     22        $name = $request->getParamName($el->getName());
    2223        $attr['name'] = $name;
    2324
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/PasswordInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\HtmlElement;
    67use Plainware\Ui\Component\Form\PasswordInput;
    7 use Plainware\Ui\Ui;
    88
    99class PasswordInputRenderer
    1010{
    11     public Ui $ui;
    12 
    13     public function __invoke(PasswordInput $el)
     11    public function __invoke(PasswordInput $el, Request $request)
    1412    {
    1513        $value = (string) $el->getValue();
    16         $name = $this->ui->getRequest()->getParamName($el->getName());
     14        $name = $request->getParamName($el->getName());
    1715        $attr = $el->getAttr();
    1816
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/RadioInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
    5 use Plainware\Ui\Ui;
     5use Plainware\Http\Request;
    66use Plainware\Ui\Component\HtmlElement;
    77use Plainware\Ui\Component\Form\RadioInput;
     
    99class RadioInputRenderer
    1010{
    11     public Ui $ui;
    12 
    13     public function __invoke(RadioInput $el)
     11    public function __invoke(RadioInput $el, Request $request)
    1412    {
    1513        // $name = $el->getName();
    16         $name = $this->ui->getRequest()->getParamName($el->getName());
     14        $name = $request->getParamName($el->getName());
    1715
    1816        $value = (string) $el->getValue();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/SelectInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\SelectInput;
    67use Plainware\Ui\Component\HtmlElement;
    7 use Plainware\Ui\Ui;
    88
    99class SelectInputRenderer
    1010{
    11     public Ui $ui;
    12 
    13     public function __invoke(SelectInput $el)
     11    public function __invoke(SelectInput $el, Request $request)
    1412    {
    15         $name = $this->ui->getRequest()->getParamName($el->getName());
     13        $name = $request->getParamName($el->getName());
    1614
    1715        $value = (string) $el->getValue();
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/TextInputRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\HtmlElement;
    67use Plainware\Ui\Component\Form\TextInput;
     
    910class TextInputRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(TextInput $el)
     14    public function __invoke(TextInput $el, Request $request)
    1415    {
    1516        $value = (string) $el->getValue();
    16         $name = $this->ui->getRequest()->getParamName($el->getName());
     17        $name = $request->getParamName($el->getName());
    1718        $attr = $el->getAttr();
    1819
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/TextareaInputRenderer.php

    r3332867 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\TextareaInput;
    67use Plainware\Ui\HtmlHelper;
     
    910class TextareaInputRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(TextareaInput $el): string
     14    public function __invoke(TextareaInput $el, Request $request): string
    1415    {
    1516        $ret = [];
     
    1718        $value = (string) $el->getValue();
    1819
    19         $name = $this->ui->getRequest()->getParamName($el->getName());
     20        $name = $request->getParamName($el->getName());
    2021        $attr['name'] = $name;
    2122
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/TimeInputRenderer.php

    r3332867 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\TimeInput;
    67use Plainware\Ui\Component\Form\SelectInput;
     
    1112class TimeInputRenderer
    1213{
    13     public Ui $ui;
     14    public $ui = Ui::class;
    1415    public Time $t;
    1516
    16     public function __invoke(TimeInput $el): string
     17    public function __invoke(TimeInput $el, Request $request): string
    1718    {
    1819        $ret = [];
     
    4243
    4344        $ret[] = '<li>';
    44         $ret[] = $this->ui->render($inputHour);
     45        $ret[] = $this->ui->render($inputHour, $request);
    4546        $ret[] = '</li>';
    4647
     
    5960
    6061        $ret[] = '<li>';
    61         $ret[] = $this->ui->render($inputMinute);
     62        $ret[] = $this->ui->render($inputMinute, $request);
    6263        $ret[] = '</li>';
    6364
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/Form/TimeRangeInputRenderer.php

    r3332867 r3394866  
    33namespace Plainware\Ui\Renderer\Form;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form\TimeRangeInput;
    67use Plainware\Ui\Component\Form\SelectInput;
     
    1112class TimeRangeInputRenderer
    1213{
    13     public Ui $ui;
     14    public $ui = Ui::class;
    1415    public Time $t;
    1516
    16     public function __invoke(TimeRangeInput $el): string
     17    public function __invoke(TimeRangeInput $el, Request $request): string
    1718    {
    1819        $ret = [];
     
    2425
    2526        $ret[] = '<li>';
    26         $ret[] = $this->ui->render($input1);
     27        $ret[] = $this->ui->render($input1, $request);
    2728        $ret[] = '</li>';
    2829
     
    3031
    3132        $ret[] = '<li>';
    32         $ret[] = $this->ui->render($input2);
     33        $ret[] = $this->ui->render($input2, $request);
    3334        $ret[] = '</li>';
    3435
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/FormRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Form;
    67use Plainware\Ui\Component\Menu;
     
    1516final class FormRenderer
    1617{
    17     public Ui $ui;
    18 
    19     private function renderOneliner(Form $form): string
     18    public $ui = Ui::class;
     19
     20    private function renderOneliner(Form $form, Request $request): string
    2021    {
    2122        $ret = [];
     
    3031        foreach ($inputs as $inputName => $input) {
    3132            $ret[] = '<li>';
    32             $ret[] = $this->ui->render($input);
     33            $ret[] = $this->ui->render($input, $request);
    3334            $ret[] = '</li>';
    3435        }
     
    3637        foreach ($buttons as $button) {
    3738            $ret[] = '<li>';
    38             $ret[] = $this->ui->render($button);
     39            $ret[] = $this->ui->render($button, $request);
    3940            $ret[] = '</li>';
    4041        }
     
    4445        $hiddenInputs = $form->getHiddenInputs();
    4546        foreach ($hiddenInputs as $hiddenInput) {
    46             $ret[] = $this->ui->render($hiddenInput);
     47            $ret[] = $this->ui->render($hiddenInput, $request);
    4748        }
    4849
     
    5455    }
    5556
    56     private function renderInput($input)
     57    private function renderInput($input, Request $request)
    5758    {
    5859        $ret = [];
     
    6970
    7071        if ($isContent) {
    71             $labelView = $this->ui->render($input->getLabel());
     72            $labelView = $this->ui->render($input->getLabel(), $request);
    7273            if (strlen($labelView)) {
    7374                $ret[] = '<fieldset>';
     
    8990            $ret[] = '<label>';
    9091            $ret[] = '<span>';
    91             $ret[] = $this->ui->render($input->getLabel());
     92            $ret[] = $this->ui->render($input->getLabel(), $request);
    9293            $ret[] = '</span>';
    9394            $closingTag = '</label>';
     
    9697            $ret[] = '<legend>';
    9798            $ret[] = '<span>';
    98             $ret[] = $this->ui->render($input->getLabel());
     99            $ret[] = $this->ui->render($input->getLabel(), $request);
    99100            $ret[] = '</span>';
    100101            $ret[] = '</legend>';
     
    108109        }
    109110
    110         $ret[] = $this->ui->render($input);
     111        $ret[] = $this->ui->render($input, $request);
    111112
    112113        foreach ($input->getErrors() as $error) {
    113             $ret[] = '<strong style="display: block;">' . $this->ui->render($error) . '</strong>';
     114            $ret[] = '<strong style="display: block;">' . $this->ui->render($error, $request) . '</strong>';
    114115        }
    115116
    116117        $help = $input->getHelp();
    117118        if ($help) {
    118             $ret[] = '<small style="display: block;">' . $this->ui->render($help) . '</small>';
     119            $ret[] = '<small style="display: block;">' . $this->ui->render($help, $request) . '</small>';
    119120        }
    120121        $ret[] = '</span>';
     
    129130    }
    130131
    131     public function __invoke(Form $form): string
     132    public function __invoke(Form $form, Request $request): string
    132133    {
    133134        static $formId = 0;
     
    136137        $isOneliner = $form->isOneliner();
    137138        if ($isOneliner) {
    138             return $this->renderOneliner($form);
     139            return $this->renderOneliner($form, $request);
    139140        }
    140141
     
    157158    // ajust input names if prefix is used
    158159        if ($toggles) {
    159             $request = $this->ui->getRequest();
    160             if ($request) {
    161                 foreach (array_keys($toggles) as $i) {
    162                     $toggles[$i][0]['name'] = $request->getParamName($toggles[$i][0]['name']);
    163                 }
     160            foreach (array_keys($toggles) as $i) {
     161                $toggles[$i][0]['name'] = $request->getParamName($toggles[$i][0]['name']);
    164162            }
    165163            $attr['onchange'] = 'pwFormToggler' . $formId . '(this)';
     
    180178                $ret_[] = '<section ' . HtmlHelper::attr($attr) . '>';
    181179
    182                 $header = $this->ui->render($section->getHeader());
     180                $header = $this->ui->render($section->getHeader(), $request);
    183181                if (strlen($header)) {
    184182                    $ret_[] = '<header>';
     
    195193                    $ret_[] = '<section ' . HtmlHelper::attr($attr) . '>';
    196194
    197                     $ret_[] = $this->renderInput($input);
     195                    $ret_[] = $this->renderInput($input, $request);
    198196                    $ret_[] = '</section>';
    199197                }
     
    208206                $ret[] = '<section ' . HtmlHelper::attr($attr) . '>';
    209207
    210                 $ret[] = $this->renderInput($input);
     208                $ret[] = $this->renderInput($input, $request);
    211209                $ret[] = '</section>';
    212210            }
     
    223221                $menu->add($i_++, $button);
    224222            }
    225             $ret[] = $this->ui->render($menu);
    226 
    227             // if (count($buttons) > 1) {
    228                 // $menu = new Menu();
    229                 // $ii = 1;
    230                 // foreach ($buttons as $button) {
    231                     // $menu->add($ii++, $button);
    232                 // }
    233                 // $ret[] = $this->ui->render($menu);
    234             // } else {
    235                 // $ret[] = $this->ui->render(current($buttons));
    236             // }
     223            $ret[] = $this->ui->render($menu, $request);
    237224
    238225            if ($displayOrder) {
     
    243230        $hiddenInputs = $form->getHiddenInputs();
    244231        foreach ($hiddenInputs as $hiddenInput) {
    245             $ret[] = $this->ui->render($hiddenInput);
     232            $ret[] = $this->ui->render($hiddenInput, $request);
    246233        }
    247234
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/HtmlElementRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\AbstractTag;
    67use Plainware\Ui\Ui;
     
    910final class HtmlElementRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213    private static $noEndTag = ['input'];
    1314
    14     public function __invoke(AbstractTag $el): string
     15    public function __invoke(AbstractTag $el, Request $request): string
    1516    {
    1617        $elements = [];
     
    3132        foreach ($iis as $ii) {
    3233            if (is_object($attr[$ii])) {
    33                 $attr[$ii] = $this->ui->render($attr[$ii]);
     34                $attr[$ii] = $this->ui->render($attr[$ii], $request);
    3435            }
    3536        }
     
    5253
    5354        foreach ($elements as $child) {
    54             $ret .= $this->ui->render($child);
     55            $ret .= $this->ui->render($child, $request);
    5556        }
    5657
    5758        if ($isDeleted) {
    58             $ret .= '<del>';
     59            $ret .= '</del>';
    5960        }
    6061
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/LinkRenderer.php

    r3372822 r3394866  
    44
    55use Plainware\Ui\Component\Link;
     6use Plainware\Core\App;
    67use Plainware\Http\Uri;
     8use Plainware\Http\Request;
     9use Plainware\Http\Router;
    710use Plainware\Ui\Ui;
    811use Plainware\Ui\HtmlHelper;
     
    1013final class LinkRenderer
    1114{
    12     public Ui $ui;
    13     public Uri $uri;
     15    public $app = App::class;
     16    public $ui = Ui::class;
     17    public $uri = Uri::class;
     18    public $router = Router::class;
    1419
    15     public function __invoke(Link $el): string
     20    public function __invoke(Link $el, Request $request): string
    1621    {
    1722        $isHidden = $this->ui->isPrintView();
     
    3035
    3136        $href = null;
     37        $myRequest = null;
    3238
    3339        if ($isPrintView) {
     
    3844                $href = $fullUri;
    3945            } else {
    40                 $slug = $el->getSlug();
    41                 if ($slug) {
     46                $route = $el->getSlug();
     47                if (null !== $route) {
    4248                    $params = $el->getParams();
    4349
    44                     $request = $this->ui->getRequest();
    4550                    $passParams = [];
    4651                    if ($request) {
    47                         $request_ = $request->makeTo($slug, $params);
    48                         $slug = $request_->getSlug();
    49                         $params = $request_->getQueryParams();
     52                        $myRequest = $request->makeTo($route, $params);
     53                        $route = $myRequest->getRoute();
     54                        $params = $myRequest->getQueryParams();
     55                        list($parsedRoute_, $routeParams_) = $this->router->parseRoute($route);
     56                        foreach ($routeParams_ as $k => $v) {
     57                            $myRequest = $myRequest->withRouteParam($k, $v);
     58                        }
    5059                    }
    5160
    52                     $href = $this->uri->to($slug, $params);
     61                    $href = $this->uri->to($route, $params);
    5362                }
    5463            }
     64        }
     65
     66        $label = $el->getLabel();
     67        if ((is_callable($label) or is_array($label)) && $myRequest) {
     68            $label = $this->app->makeFunc($label);
     69            $label = call_user_func($label, $myRequest);
     70        }
     71        $label = $this->ui->render($label, $request);
     72
     73        if (null === $label) {
     74            return '';
    5575        }
    5676
     
    6282        foreach (array_keys($attr) as $k_) {
    6383            while (is_object($attr[$k_])) {
    64                 $attr[$k_] = $this->ui->render($attr[$k_]);
     84                $attr[$k_] = $this->ui->render($attr[$k_], $request);
    6585            }
    6686        }
     
    80100            $ret[] = '<strong>';
    81101        }
     102
     103        $iconBefore = $el->getIconBefore();
     104        $iconAfter = $el->getIconAfter();
     105
    82106        $ret[] = '<a';
    83107        $ret[] = ' ' . HtmlHelper::attr($attr);
     
    89113        }
    90114
    91         $label = $el->getLabel();
    92         if ($label instanceof $el) {
    93             $label = $label->getLabel();
    94         } else {
    95             $label = $this->ui->render($label);
    96         }
    97 
    98         $iconBefore = $el->getIconBefore();
    99         $iconAfter = $el->getIconAfter();
    100 
    101115        foreach ($iconBefore as $icon_) {
    102             $ret[] = '<i>' . $this->ui->render($icon_) . '</i>';
     116            $ret[] = '<i>' . $this->ui->render($icon_, $request) . '</i>';
    103117        }
    104118
     
    112126
    113127        foreach ($iconAfter as $icon_) {
    114             $ret[] = '<i>' . $this->ui->render($icon_) . '</i>';
     128            $ret[] = '<i>' . $this->ui->render($icon_, $request) . '</i>';
    115129        }
    116130
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/MainMenuRenderer.php

    r3372822 r3394866  
    88use Plainware\Ui\Component\MainMenu;
    99use Plainware\Ui\Component\Link;
    10 use Plainware\Ui\Renderer\ContainerRenderer;
    1110
    1211class MainMenuRenderer
    1312{
    14     public Ui $ui;
    15     public ContainerRenderer $containerRenderer;
     13    public $ui = Ui::class;
    1614
    17     public function __invoke(MainMenu $el)
     15    public function __invoke(MainMenu $el, Request $request)
    1816    {
    1917        $ret = '';
     
    2927        }
    3028
    31         $currentSlug = $el->getCurrentSlug() ?? [];
     29        $currentSlug = $el->getCurrentSlug() ?? '';
     30        $currentSlugArray = strlen($currentSlug) ? explode('/', $currentSlug) : [];
    3231
    3332        $ret = new HtmlElement('ul');
     
    4039                $item->setMenu(true);
    4140
    42                 $thisSlug = $item->getSlug();
    43                 $len = min(count($thisSlug), count($currentSlug));
     41                $request_ = $request->makeTo($item->getSlug(), $item->getParams());
     42                $thisSlug = $request_->getSlug();
     43                $thisSlugArray = strlen($thisSlug) ? explode('/', $thisSlug) : [];
     44
     45                $len = min(count($thisSlugArray), count($currentSlugArray));
    4446                $isOn = true;
    4547                for ($i_ = 0; $i_ < $len; $i_++) {
    46                     if ($thisSlug[$i_] !== $currentSlug[$i_]) {
     48                    if ($thisSlugArray[$i_] !== $currentSlugArray[$i_]) {
    4749                        $isOn = false;
    4850                        break;
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/MainRenderer.php

    r3372822 r3394866  
    44
    55use Plainware\Core\Translate;
     6use Plainware\Http\Request;
    67use Plainware\Ui\Component\Main;
    78use Plainware\Ui\Component\Link;
     
    1718final class MainRenderer
    1819{
    19     public Translate $translate;
    20     public Ui $ui;
    21     public ContainerRenderer $containerRenderer;
     20    public $translate = Translate::class;
     21    public $ui = Ui::class;
     22    public $containerRenderer = ContainerRenderer::class;
    2223
    23     public function __invoke(Main $el)
     24    public function __invoke(Main $el, Request $request)
    2425    {
    2526        $wrap = (new HtmlElement('div'))
     
    7778    // pass to container rendering
    7879        $ret = ($this->containerRenderer)($el);
    79         $ret = $this->ui->render($ret);
     80        $ret = $this->ui->render($ret, $request);
    8081
    8182    // translate
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/MenuRenderer.php

    r3372822 r3394866  
    1010class MenuRenderer
    1111{
    12     public Ui $ui;
     12    public $ui = Ui::class;
    1313
    1414    public function __invoke(Menu $el)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/NavRenderer.php

    r3372822 r3394866  
    99final class NavRenderer
    1010{
    11     public Ui $ui;
     11    public $ui = Ui::class;
    1212
    1313    public function __invoke(Nav $el)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/PagerRenderer.php

    r3372822 r3394866  
    1111class PagerRenderer
    1212{
    13     public Ui $ui;
     13    public $ui = Ui::class;
    1414
    1515    public function __invoke(Pager $el)
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/PrintViewMainRendererDecorator.php

    r3372822 r3394866  
    44
    55use Plainware\Core\Translate;
     6use Plainware\Http\Request;
    67use Plainware\Http\Uri;
    78use Plainware\Ui\Ui;
     
    1011final class PrintViewMainRendererDecorator
    1112{
    12     public Translate $translate;
    13     public Ui $ui;
    14     public Uri $uri;
     13    public $translate = Translate::class;
     14    public $ui = Ui::class;
     15    public $uri = Uri::class;
    1516
    16     public function __invoke(Main $el, callable $next)
     17    public function __invoke(Main $el, Request $request, callable $next)
    1718    {
    18         $nextRet = ($next)($el);
     19        $nextRet = ($next)($el, $request);
    1920
    2021        $layoutId = $el->getLayoutId();
     
    3334        $ret[] = '<title>';
    3435
    35         $title = $this->ui->render($el->getTitle());
     36        $title = $this->ui->render($el->getTitle(), $request);
    3637        $title = $this->translate->translate($title);
    3738        $title = strip_tags($title);
     
    5758
    5859        $ret[] = '<body>';
    59         $ret[] = $this->ui->render($nextRet);
     60        $ret[] = $this->ui->render($nextRet, $request);
    6061        $ret[] = '</body>';
    6162
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/SectionRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Section;
    67use Plainware\Ui\Ui;
     
    910final class SectionRenderer
    1011{
    11     public Ui $ui;
     12    public $ui = Ui::class;
    1213
    13     public function __invoke(Section $el): string
     14    public function __invoke(Section $el, Request $request): string
    1415    {
    15         $headerView = $this->ui->render($el->getHeader());
    16         $navView = $this->ui->render($el->getNav());
    17         $contentView = $this->ui->render($el->getContent());
    18         $footerView = $this->ui->render($el->getFooter());
    19         $menuView = $this->ui->render($el->getMenu());
     16        $headerView = $this->ui->render($el->getHeader(), $request);
     17        $navView = $this->ui->render($el->getNav(), $request);
     18        $contentView = $this->ui->render($el->getContent(), $request);
     19        $footerView = $this->ui->render($el->getFooter(), $request);
     20        $menuView = $this->ui->render($el->getMenu(), $request);
    2021
    2122        // if (!($headerView or $navView or $contentView or $footerView or $menuView)) {
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/TabMenuRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Ui;
    67use Plainware\Ui\HtmlHelper;
     
    1011class TabMenuRenderer
    1112{
    12     public Ui $ui;
     13    public $ui = Ui::class;
    1314
    14     public function __invoke(TabMenu $el): string
     15    public function __invoke(TabMenu $el, Request $request): string
    1516    {
    1617        $items = $el->getItems();
     
    2122
    2223        $ret = [];
     24        $ret[] = '<div class="pw-header-tabmenu">';
    2325        $ret[] = '<ul class="pw-nav-tab">';
    2426
     
    2628
    2729        foreach ($items as $itemId => $item) {
    28             $v = $this->ui->render($item);
     30            $v = $this->ui->render($item, $request);
    2931            if (!strlen($v)) {
    3032                continue;
     
    5456        }
    5557        $ret[] = '</ul>';
     58        $ret[] = '</div>';
    5659
    5760        $ret = join('', $ret);
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Renderer/TableRenderer.php

    r3372822 r3394866  
    33namespace Plainware\Ui\Renderer;
    44
     5use Plainware\Http\Request;
    56use Plainware\Ui\Component\Table;
    67use Plainware\Ui\Ui;
     
    910final class TableRenderer
    1011{
    11     public Ui $ui;
    12 
    13     public function __invoke(Table $el): string
     12    public $ui = Ui::class;
     13
     14    public function __invoke(Table $el, Request $request): string
    1415    {
    1516        $headRows = $el->getHeadRows();
     
    4445
    4546        $caption = $el->getCaption();
    46         $caption = $this->ui->render($caption);
    47         if (strlen($caption)) {
     47        $caption = $this->ui->render($caption, $request);
     48        if ($caption) {
    4849            $ret[] = '<caption>';
    4950            $ret[] = $caption;
     
    144145                    }
    145146
    146                     $ret[] = $this->ui->render($cell);
     147                    $ret[] = $this->ui->render($cell, $request);
    147148                }
    148149                $ret[] = '</tr>';
     
    234235// $content = $rowId . '-' . $colId;
    235236// $cell->setContent($content);
    236                         $ret[] = $this->ui->render($cell);
     237                        $ret[] = $this->ui->render($cell, $request);
    237238                    } else {
    238239                        // $ret[] = '<td>x</td>';
     
    325326                    }
    326327
    327                     $ret[] = $this->ui->render($cell);
     328                    $ret[] = $this->ui->render($cell, $request);
    328329                }
    329330                $ret[] = '</tr>';
  • plain-event-calendar/trunk/vendor/plainware/ui/src/Ui.php

    r3372822 r3394866  
    88class Ui
    99{
    10     public App $app;
     10    public $app = App::class;
    1111    private $renderers = [];
    12     private ?Request $request = null;
    1312    private bool $isPrintView = false;
    1413
     
    1615    {
    1716        return $this->isPrintView;
    18 
    19         // $ret = false;
    20 
    21         // $request = $this->getRequest();
    22         // if (!$request) {
    23             // return $ret;
    24         // }
    2517    }
    2618
     
    3224    }
    3325
    34     public function withRequest(Request $request): self
    35     {
    36         $this->request = $request;
    37 
    38         return $this;
    39     }
    40 
    41     public function getRequest(): ?Request
    42     {
    43         return $this->request;
    44     }
    45 
    4626    private function findRenderers(string $className): array
    4727    {
     
    4929    }
    5030
    51     public function render($el)
     31    public function render($el, Request $request)
    5232    {
     33        if (is_callable($el) or is_array($el)) {
     34            $ret = $this->app->makeFunc($el);
     35            $ret = call_user_func($ret, $request);
     36
     37            return $this->render($ret, $request);
     38        }
     39
    5340        if (!is_object($el)) {
    5441            return $el;
     
    8370        $func = $this->app->makePipeline($funcs);
    8471
    85         $ret = call_user_func($func, $el);
     72        $ret = call_user_func($func, $el, $request);
    8673        if (is_object($ret)) {
    87             return $this->render($ret);
     74            return $this->render($ret, $request);
    8875        }
    8976
Note: See TracChangeset for help on using the changeset viewer.