Iterování všech Presenterů

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Hlava
Člen | 19
+
0
-

zdravím, předem se omlouvám, co se týče cesty poznání Nette, sotva jsem obul boty, nicméně, teď jsem se zaseknul na jedné věci a chci to udělat „správně“ a nikde jsem nenašel podobné téma.

Předělávám jednu pravěkou aplikaci a rozhodl jsem se právě pro Nette.

V principu aplikace obsahuje několik modulů, které můžou její uživatele používat. Všechny Moduly jsou pro mě v aplikaci Presentery, resp. děcka Nette\Application\UI\Presenter.

Vím, že se používá jen to, co je potřeba, ale chtěl bych udělat dynamické generování stromu (kvůli menu), a to tak, že projedu naprosto všechny Presentery, co jsou v aplikaci a zeptám se je, zda s nima může přihlášený uživatel pracovat. Plán je udělat to jen jednou při prvním „login“ uživateli a pak jen expirovat cache v různých případech.

Můj dotaz je – není nějaký lepší způsob než projet všechny Presentery? Nejspíš ne, s tím je spojený další dotaz – jak vlastně mám projet všechny presentery? Co jsem tak pochopil, tak se instance ani nevytváří, pokud nejsou potřeba (což je super, ale…).

Předem díky za odpověď a naťuknutí :)

PS: Zatím všechno co jsem o Nette zjistil, tak se mi docela líbí a jelikož jsem úplný ňouma co se Nette týče a opravdu na úplném začátku, tak dokumentace není zase tak špatné, jak se všude dokola píše :)

David Matějka
Moderator | 6445
+
+1
-

Nejpr odpovim na otazku: asi by to mohlo jit metodou findByType na Containeru (ten si injectnes jako zavislost), nette totiz hleda presentery a registruje je jako sluzby. Hledal bys dle typu Nette\Application\UI\Presenter a melo by to vratit nazvy sluzeb presenteru. Problem je, ze bys asi musel vytvorit instance te sluzby, abys vubec zjistil, o jaky presenter se jedna.

Ale nedoporucuju ti to, krom toho, ze to nebude uplne spolehlive, tak te to muze pozdeji limitovat. A jeste par poznamek:

Všechny Moduly jsou pro mě v aplikaci Presentery

tohle nedoporucuju, predpokladam, ze ty moduly mohou byt celkem rozsahle? Radeji si pro to vytvor moduly :). To je v nette logicke rozcleneni presenteru do nejakych celku, pouziti najdes v examplech: https://github.com/…odules-Usage … v tech modulech pak budes mit presentery pro jednotlive casti tech modulu, osobne doporucuji mit v presenterech pouze jednu akci.

Pro kazdy modul budes pak mit tridu registrovanou jako sluzbu, ktera by popisovala vlastnosti toho modulu a mohla by se treba vyuzit prave pro to menu nebo zjistovani pristupu. coz tedy vyresi i puvodni otazku

Hlava
Člen | 19
+
0
-

Velmi děkuji za odpověď.

Asi je to i trochu způsobené mou „negramotností“ co se komunikace na fóru týče :)

Naprosto rozumím tomu, co mi doporučuješ a samozřejmě souhlasím. A asi to mám i tak nějak základně navržené. Jde mi ale o to, že i ta aplikace má stejný problém jako já. Ve skutečnosti se moc neliším od onoho rozčlenění, jen mám malinko jinak řešen BasePresenter.

Modules/Admin/DefaultPresenter.php
Modules/Front/DefaultPresenter.php
Modules/Front/CatalogListPresenter.php
Modules/Front.export/DefaultPresenter.php

přihlášený uživatel bude mít práva jen na některé presentery. A jen ty mu chci nabídnout v MENU. Jde mi o to, že ta iterace asi fakt bude vyžadovat vytvoření všech instancí (ale to mi tak nevadí, pomalost vyřeší cache), jak to ale udělat správně? Hrozně rád bych se vyhl „prasárně“ typu vytvoření vlastního kontejneru, který by mi evidoval všechny Presentery (instancované i ve stínu) a jejich atributy, fakt nic takového není v Nette? Těžko se mi tomu věří.

Editoval Hlava (16. 12. 2015 12:01)

Pavel Kravčík
Člen | 1183
+
0
-

Řešil jsem něco podobného následovně. Každý modul má vlastní config → v boostrap se pak skládají. Pokud je zadaný parametr menu → generuje se z něj menu a kontrolují se práva. Je to pár podmínek. Výsledek se uloží někam do cache.

Modul může mít více presenterů. Zbytek se pak generuje automaticky – má uživatel práva – zobrazí se to v menu. Pokud nemá – nezobrazí se to apod. Ty pravidla si pak můžeš nastavit sám. To projíždění presenterů jsem zkoušel, jde to snadno, ale nebylo to výhodné, pokud si je chtěl nějak spojovat do bloků, nastavovat jim ikonky, barvy a třeba pravidla pro zobrazí v seznamu aplikací či různých blocích.

parameters:
    menu:
        psa:
            title: Smlouvy
            titleLong: PSA - Smlouvy
            presenter: Psa
            alias:
                - PsaContract
                - PsaNeco
            icon:
                name: file-text-o
                color: pink
            submenu:
                contract:
                    title: Seznam
                    presenter: Psa
                    action: default
                    icon:
                        name: list
                list:
                    title: Ostatní
                    presenter: PsaNeco
                    icon:
                        name: plane
                    dropbox:
                        prolong:
                            title: Prolongace smluv
                            presenter: PsaNeco
                            action: default
                            icon:
                                name: plane
                        #...
CZechBoY
Člen | 3608
+
0
-

Tak můžeš si vyžádat tu službu z kontejneru, z kontejneru už ti přijde instance.

Do toho menu stejně budeš potom přidávat různý další akce (třeba jako submenu). Hodně blbě se ti to bude spravovat (pořadí, submenu, ikonky, atd.). Určitě to menu negeneruj nijak automaticky podle všech presenterů.

Hlava
Člen | 19
+
0
-

Asi jsem trochu náročnej, ale tohle řešení by mi nevyhovovalo.

Vytvoření nového modulu a jeho „zapojení“ do aplikace by vyžadovalo myslet na úpravu i tohoto configu. A nejedná se mi pouze o samotné menu.

Dejme tomu třeba vytvoření nějakého CRONu. Ano – můžu mít několik akcí v samotném spouštění a podle url spouštět jednotlivé akce v presenteru. Ale co když chci jenom spustit v cronu ⇒ aplikace/uklidPoSobe a všechny presentery budou mít spustět svoje volání? Nechci to dělat přes aplikace/Front/uklidPoSobe, aplikace/Admin/uklidPoSobe …

A v praxi člověk přijde na mnoho dalších věcí. Prostě asi je to síla zvyku, ale všechny akce, co by měl daný modul dělat by se mi moc líbilo definovat v DefaultPresenteru onoho modulu. Ať už to je definice Menu (Tvé řešení neřeší např. jazykové mutace, v cz je v sk není, ano šlo by to rozšířit, ale… to by bylo možné pak rozšířovat do nekonečna).

V principu to všechno vyřeší jedna jediná věc – mít možnost vytvoření instancí všech Presenterů a úplně dokonale pouze těch, co budou mít nějakou statickou proměnou nějak nastavenou. Takové řešení není, že?

A pokud ne, otázka, má smysl to řešit nějak globálně? Jsem opravdová „lama“, co se nette týče a na nějaký pull requesty se asi moc ještě necítím, ale kdo nic nezkusí, nic nezíská :)

Hlava
Člen | 19
+
0
-

CZechBoY napsal(a):

Do toho menu stejně budeš potom přidávat různý další akce (třeba jako submenu). Hodně blbě se ti to bude spravovat (pořadí, submenu, ikonky, atd.). Určitě to menu negeneruj nijak automaticky podle všech presenterů.

Děkuji za odpověď. Dovolím si ale nesouhlasit.

Samotné menu je řešeno tak, že se Kouknu do Modulu → DefaultPresenteru, zjistím, zda existuje a mám povolené menu a přidám do objektu menu. Poté projedu všechny další Presentery modulu, které jsou k dispozici a přidám submenu. Sice to je pouze dvouúrovňové, ale v této logice mi to nevadí. A řazení se dá udělat jednou hodnotou v definici.

Ale jak říkám – nejedná se pouze o menu.

Tak můžeš si vyžádat tu službu z kontejneru, z kontejneru už ti přijde instance.

To ano, ale jak zjistím, jaké služby mám chtít?

Editoval Hlava (16. 12. 2015 12:24)

Pavel Kravčík
Člen | 1183
+
0
-

To není řešení, ale nástřel toho, jak by to řešené být mohlo. :) Jazykové mutace to neřeší, protože ten projekt jazykové mutace nikdy mít nebude. :)

To už záleží na Tobě, jak si to nastavíš. Config bude vždy přehlednější, než několik proměnných v presenteru → protože config se dá hezky zanořovat.

A každý modul má vlastní config, takže nic nikde nerozbiješ a nastavuješ jen, když ho programuješ. Takhle vypadá třeba nějaký reálný pro malý modul:

parameters:
    acl:
        Dev:
            - exec

    menu:
        dev:
            presenter: Dev
            title: Dev
            hiddenApp: TRUE
            icon:
                name: linux
                color: orange

services:
    DevPresenter:
        class: \App\DevPresenter
        setup:
            - injectParameters(%tempDir%)

A výsledek pak vidíš v menu nějak takhle http://imgur.com/tK2j9ae.

Hlava napsal(a):

Ale jak říkám – nejedná se pouze o menu.

Však si tam můžeš dát i acl třeba a tam si dopsat akce, které se mají hlídat. V tomhle projektu nechci hlídat všechy, ale jen definované. Ty si pak automaticky generuji do pole checkboxů a ve správě uživatelů si můžeš zaškrtnout, kdo kam může a to ovlivní zobrazení menu. To by pro Tebe mohla být nejlepší cesta.

Editoval Pavel Kravčík (16. 12. 2015 12:32)

iguana007
Člen | 970
+
0
-

Asi mi uniká podstata toho, proč to řešit přes configy, generátory apod.? Jak by se řesily výjimky, či speciální pravidla pro generování menu atd.? Změnou zdrojových souborů?

Já když řešil téměř stejnou věc, tak jsem do aplikace implmentoval obdobu tohoto: https://forum.nette.org/…control-list

Všechno je v databázi, je možné práva editovat přímo v administraci a nemusím tak kvůli kdejaké změně v právech/přístupech/menu dělat commit a úpravy ve zdrojových souborech.

Menu pak generuji z traverzovaných dat v databázi, nad kterými se dělá i validace ACL, takže každému se vykresluje menu s těmi položkami, které má vidět + se samozřeujmě autorizuje i přstup na stránku skrz přímou URL.

Hlava
Člen | 19
+
0
-

Pavel Kravčík napsal(a):

Takhle to určitě asi fungovat může, jen mi to přijde jako řešení už trochu „vedle“ samotného Nette. Potřeba dopsat spoustu věcí, co mi to budou obhospodářovávat. Ale z reakcí cítím, že mi asi nic jiného nezbyde, že přímo v Nette nic není.

Jen dotaz. To píšeš všechno do hlavního configu? nebo máš neon v každém modulu zvlášť? Automaticky se to při spuštění nahraje nebo musím „ručně“?

Tohle jsou už ale otázky zbytečné a obtěžující, je mi jasné, že to už někde jinde dohledám. Každopádně za ušetření času děkuji.

Hlava
Člen | 19
+
0
-

iguana007 napsal(a):

Asi mi uniká podstata toho, proč to řešit přes configy, generátory apod.? Jak by se řesily výjimky, či speciální pravidla pro generování menu atd.? Změnou zdrojových souborů?

Já když řešil téměř stejnou věc, tak jsem do aplikace implmentoval obdobu tohoto: https://forum.nette.org/…control-list

Všechno je v databázi, je možné práva editovat přímo v administraci a nemusím tak kvůli kdejaké změně v právech/přístupech/menu dělat commit a úpravy ve zdrojových souborech.

Menu pak generuji z traverzovaných dat v databázi, nad kterými se dělá i validace ACL, takže každému se vykresluje menu s těmi položkami, které má vidět + se samozřeujmě autorizuje i přstup na stránku skrz přímou URL.

Taky řešení. Každé má své pro i proti, ale v podstaty věci samotné je to pro mě stále jen, „tak dobře no, tak to půjde“, místo „super pecka“. :)

Výsledek je ten – iterovat všechny instancované i neinstancované Presentery NELZE! Správně? Nehleďme na důvody, protože správné řešení asi každý z nás vidíme jinak a vždy každý má správné argumenty!

Pavel Kravčík
Člen | 1183
+
0
-

@iguana007: Jasně, tak nastavování uživatelům už probíhá přes DB. To by bylo hloupé kvůli úpravě práv uživatele šahat do kódu.

@Hlava: Každý modul má vlastní config.neon. To jsem dělal kvůli službám, těch je asi 100 a mít je v jednom configu mi přišlo zrůdné. Já ty práva vytvářím společně s containerem automaticky.

Pavel Kravčík
Člen | 1183
+
0
-

Hlava napsal(a):

Výsledek je ten – iterovat všechny instancované i neinstancované Presentery NELZE! Správně? Nehleďme na důvody, protože správné řešení asi každý z nás vidíme jinak a vždy každý má správné argumenty!

A tohle by Ti nestačilo?

$finder = Finder::findFiles('*Presenter.php')
                ->exclude('*BasePresenter*')
                ->in('../app')
                ->limitDepth(3);
Hlava
Člen | 19
+
0
-

Jo, to by určitě mohlo fungovat, ale taky je to postavené „mimo“ Nette, každopádně děkuji za návrh, tušil jsem, že jinak než procházet soubory to nepůjde.

Díky :)