LocherLocher MemberComments: 2 Received thanks: 0 Member since: November 2019 edited November 2019

Hallo liebe Shopware-User!

Ich schreibe gerade ein Shopware Plugin, welches eine Kontroller-Methode ersetzen soll.

Die zu ersetzende Methode hat auch Parameter, aber das konnte ich bereits lösen.

Das erfolgsbremsende Problem ist, dass die Original-Methode auch Methoden innerhalb dessen Klasse aufruft, für welches mein Plugin keinen Kontext besitzt und es kommt zum Fehler.

Ich habe von der hilfreichen executeParent() Methode gehört, welches simulierend die Elternmethode aufruft. Aber ich habe Probleme dies zu implementieren.

Hier mein Codeschnipsel.

    public static function getSubscribedEvents()
    {
        return [
            'Enlight_Controller_Action_PostDispatchSecure_Backend' => 'onOrderPostDispatch',
            'Shopware_Controllers_Backend_Order::getList::replace' => 'getListReplace'
        ];
    }

    public function getListReplace(\Enlight_Hook_HookArgs $args)
    {
        $request = $args->getSubject()->Request();
        $filter = $request->getParam('filter');
        $sort = $request->getParam('sort');
        $offset = $request->getParam('offset');
        $limit = $request->getParam('limit');


        // Original-Methodenaufruf: $sort = $this->resolveSortParameter($sort);
        // $sort = $args->getSubject()->executeParent(Shopware_Controllers_Backend_Order::resolveSortParameter, $args = [$sort]);
        // $sort = $this->executeParent('resolveSortParameter', $args = [$sort]);
        // $sort = $args->setReturn($args->getSubject()->executeParent('resolveSortParameter', $args->getArgs()));
        $sort = $args->getSubject()->executeParent('resolveSortParameter', $args = [$sort]);

...

getList() ist die Methode, die ich ersetzen möchte. Der Hook funktioniert. Aber ich schaffe es nicht, dem executeParent() den fehlenden Kontext zu geben.

ich will auch nicht alle aufgerufende Methoden, die man in der Order.php findet, ins Plugin hineinkopieren.

 

Bitte um Verzeihung falls die Frage komisch wirkt oder gänzlich als Anfängerfehler eingestuft wird,

ich versuche das Shopware Plugin noch zu schreiben ehe die 1Monat ShopwareDemo abgelaufen ist.

Answers

  • LocherLocher MemberComments: 2 Received thanks: 0 edited November 2019 Member since: November 2019

    Hallo liebe Shopware-User!

    Ich komme nur kurz zurück um zu sagen, dass ich mein Problem hiermit zurücknehme.

    Mein Plugin ist nun zuende geschrieben und ich habe alles erreicht, was ich erreichen wollte. Alles OHNE die Nutzung von der Methode executeParent().

    Für zukünftige Besucher dieses Forums hinterlasse ich noch die Hintergründe meines Problems und was mein Plugin eigentlich erreichen sollte:

     

    Hintergrund:

    Es gibt da einen PC-Shop, welches im Backend für die Bestellliste einen weiteren Filter braucht. Ich kenn mich zwar nicht mit Shopware aus aber das Shopware-Plugin für PHPStorm hat eine Probezeit von einem Monat, also genügend Zeit ein kleines Plugin zu schreiben, der das erledigt.

    Nachdem ich die selbstgeschriebene Filteroption über 'Shopware.apps.Order.view.list.Filter' dargestellt hatte und Shopware diesen Filter mitsamt seinem Wert akzeptiert hatte, musste ich im Backend-Controller natürlich diesen Filter aus dem Filter-Array herauspicken und entfernen bevor dieser Filter-Array zum Doctrine kommt und Fehler spuckt.

    Daher meine Idee die Methode getList() zu überschreiben, denn hier wird auch aktiv gefiltert. Ich muss nur am Anfang der Methode meinen speziellen Filter herausnehmen und kurz am Ende der Methode (vor dem Return des Objektes) meine eigene Filterung hineinprogrammieren.

    Das war ein großes Wunschdenken: So gut wie alle Methoden innerhalb der Order.php sind entweder auf private oder protected gesetzt: Keine Chance für executeParent().

    Danke hierbei an folgendem Beitrag :

     

    Nun kommt hier mein Kniff: ich nutze sowohl ein ::before und ::after Hook für die getListAction().

    Ich kann getListAction() nicht mit ::replace überschreiben, denn die darin aufgerufende getList() ist eine protected Methode.

    Naja egal.

    Darunter seht ihr die Reihenfolge von ::before, eigentliche Methode, ::after

     

    before_getListAction() prüft nur, ob ein CustomFilter vorliegt. Falls ja, dann soll er es vermerken und den Filter aus dem FilterArray entfernen.
    Da die Hauptmethode sich den Filter-Array holen wird, muss der angepasste Filter über setParam() auch wieder gesetzt werden.

        public function before_getListAction(\Enlight_Hook_HookArgs $args) {
            $request = $args->getSubject()->Request();
            $filter = $request->getParam('filter');
    
            //$customFilter ist nun die letzte Stelle des Filter-Arrays
            $GLOBALS["customFilter"] = array_values(array_slice($filter, -1))[0];
            if ($GLOBALS["customFilter"]['property'] == 'customFilter') {
                $GLOBALS["customFilter"] = $GLOBALS["customFilter"]['value'];
                array_pop($filter); // Lösche den speziellen Filter ehe Doctrine sich beschwert
            } else {
                $GLOBALS["customFilter"] = null;
            }
            $request->setParam('filter', $filter); // Der Filter ist nun überschrieben!
        }

     

        public function getListAction()
        {
            // Read store parameter to filter and paginate the data.
            $limit = (int) $this->Request()->getParam('limit', 20);
            $offset = (int) $this->Request()->getParam('start', 0);
            $sort = $this->Request()->getParam('sort', []);
            $filter = $this->Request()->getParam('filter', []);
            $orderId = $this->Request()->getParam('orderID');
    
            if ($orderId !== null) {
                $orderIdFilter = ['property' => 'orders.id', 'value' => $orderId];
                if (!is_array($filter)) {
                    $filter = [];
                }
                $filter[] = $orderIdFilter;
            }
    
            $list = $this->getList($filter, $sort, $offset, $limit);
    
            $this->View()->assign($list);
        }

    after_getListAction() verfügt über die fertig gefilterten Datensätze. Er muss nur schauen ob der spezielle Filter angewendet wurde.

    Falls ja, dann holt er sich den Datensatz via getAssign() und macht damit seine speziellen Filteroperationen.

    Am Ende wird die weiter-gefilterten Datensätze via assign() festgeschrieben. Das alte Objekt wird dadurch mit unserem überschrieben.

        public function after_getListAction(\Enlight_Hook_HookArgs $args) {
            // Überschreibe die Bestellsätze nur, falls ein spezieller Filter angewendet wurde
            if ($GLOBALS["customFilter"] != null) {
                $list = $args->getSubject()->View()->getAssign();
                $list = $this->applyCustomFilter($list);
                $args->getSubject()->View()->assign($list);
            }
        }

    Hiermit endet mein zwei-wöchiger Shopware Ausflug. Vielen Dank!

    Demonstration

Sign In or Register to comment.