Filtern von Zahlungsarten

Hi

Ich bin neu hier und habe einige Dinge noch nicht ganz verstanden.
Zur Zeit erstelle ich kleinere Module für einige Tests des OXID eshop Systems.

Nun, für einer der Tests möchte ich im checkout, vor der Auswahl der Zahlungsarten, die Liste der Zahlungsarten filtern.

Dafür habe ich eine schon beinahe perfekt vorbereitete Methode Gefunden:
Datei: /vendor/oxid-esales/oxideshop-ce/source/Application/Model/PaymentList.php
Klasse: PaymentList
Methode: getPaymentList

Frage #1: Ist meine einzige möglichkeit die zahlungsarten zu filtern, das Überschreiben der gesammten Klasse? Ich finde dies ist ein overkill.

So, für meinen Test habe ich direkt mal versucht die Klasse zu überschreiben.
Meta:
/**
* Metadata version
*/
$sMetadataVersion = ‘1.0’;

/**
 * Module information
 */
$aModule = array(
'id'           => 'chriso',
'title'        => 'Chriso',
'description'  => array(
    'de' => 'Mehr balabala mit chriso.',
    'en' => 'Mehr balabala mit chriso.',
),
'version'      => '0.1.1',
'author'       => 'Chriso',
'url'          => 'https://www.chriso.nenenenne.com',
'email'        => '[email protected]',
'extend'       => array(
    \OxidEsales\Eshop\Application\Model\PaymentList::class     => \CHRISO\testmodule\Model\PaymentList::class,
    //\OxidEsales\Eshop\Application\Controller\PaymentController::class     => \OxidEsales\PayPalModule\Controller\PaymentController::class,
)
);

und die Klasse (logisch unverändert):
namespace CHRISO\testmodule\Model;

class PaymentList extends \OxidEsales\EshopCommunity\Application\Model\PaymentList
{
/**
 * Loads and returns list of user payments.
 *
 * @param string                                   $sShipSetId user chosen delivery set
 * @param double                                   $dPrice     basket product price excl. discount
 * @param \OxidEsales\Eshop\Application\Model\User $oUser      session user object
 *
 * @return array
 */
public function getPaymentList($sShipSetId, $dPrice, $oUser = null)
{
    $this->selectString($this->_getFilterSelect($sShipSetId, $dPrice, $oUser));

    return $this->_aArray;
    // return parent::getPaymentList .... 
}
}

Problem #1:
Im Backend bekomme ich die Fehlermeldung:
Es wurden ungültige Module erkannt.

  • OxidEsales\Eshop\Application\Model\PaymentList => CHRISO\testmodule\Model\PaymentList
    Die Klasse wird nicht überschrieben. (Die standard Klasse wird verwendet).

Problem #2:
In diesem Fall bringt es wohl nichts, die parent klasse mit der methode getPaymentList aufzurufen.
So wie die Klasse aufgebaut ist, scheint Sie mir nicht “overridable”.

Kann mir jemand sagen wie der “best Practice”-Ansatz für das filtern von Zahlungsarten ungefähr aussehen würde?

Grüsse

Man überschreibt einzelne Methoden. Bei extends verwendet man “klassenname_parent”, OXID macht daraus eine Vererbungskette, deshalb sollte man wenn möglich die parent-Methode innerhalb der eigenen Methode aufrufen. Also z.B.

$paymentlist = parent::getPaymentList();
//... irgendwelche Filter
return $paymentlist;

Details z.B. hier: Steps for creating a basic module — OXID eShop developer documentation 6.1.0 documentation

Man muss den Namespace in composer registrieren, bevor man das Modul verwenden kann: https://docs.oxid-esales.com/developer/en/6.1/modules/good_practices/module_setup.html

Weder noch, siehe oben.

Man muss den Namespace in composer registrieren, bevor man das Modul verwenden kann

Ist gemacht:

"autoload": {
 "psr-4": {
   "CHRISO\\testmodule\\": "../../../source/modules/CHRISO/testmodule"
  }
}

Weder noch, siehe oben.

Die zu überschreibende Methode verwendet Parameter des Klassenobjekts,
der Aufruf $paymentlist = parent::getPaymentList(); ist objektlos. Daher können keine Werte im Objekt geändert oder gespeichert werden. Oder verstehe ich dies falsch?

Momentan hänge ich an einem komischen Effekt und kann deshalb nicht weiter daran testen:
Betreffend der Fehlermeldung “Es wurden ungültige Module erkannt” bleibt bei mir, auch wenn ich den extend block im meta file lösche und auch das PHP File (PaymentList) lösche.
Wenn ich die Meldung nicht wegbringe, kann ich auch nicht an ner Lösung tüfteln.
(Habe den Inhalt von /temp gelöscht)

parent:: kann eine nichtstatische Methode aufrufen und hat dann Objektkontext, trotz dem Operator.

Modul Reset probieren: /tmp leeren und folgendes SQL ausführen:

DELETE FROM oxconfig WHERE OXVARNAME LIKE ‘%module%’

Also wenn du die Methode verwenden willst die ich verlinkt habe (Eintrag in der composer.json des Shops und composer dump-autoload, dann sind da ein paar “…/” zu viel.

Danke. Nun ist vieles klarer.
Jedoch kommt die Meldung wieder, mit dem “Es wurden ungültige Module erkannt.”.

composer.json

{
  "name": "chriso/testmodule",
  "description": "This is the PayPal module for the OXID eShop. not",
  "type": "oxideshop-module",
  "keywords": ["oxid", "modules", "eShop"],
  "homepage": "https://www.CHRISO.com",
  "license": [
    "GPL-3.0-only",
    "proprietary"
  ],
  "extra": {
    "oxideshop": {
      "target-directory": "CHRISO/testmodule"
    }
  },
  "require": {
    "php": ">=5.6",
    "lib-curl": "*",
    "lib-openssl": "*",
    "ext-curl": "*",
    "ext-openssl": "*"
  },
  "autoload": {
    "psr-4": {
      "CHRISO\\testmodule\\": "./source/modules/CHRISO/testmodule"
    }
  }
}

metadata.php

<?php

/**
 * Metadata version
 */
$sMetadataVersion = '1.0';

/**
 * Module information
 */
$aModule = array(
    'id'           => 'chriso',
    'title'        => 'Chriso',
    'description'  => array(
        'de' => 'Mehr balabala mit chriso.',
        'en' => 'Mehr balabala mit chriso.',
    ),
    'version'      => '0.1.1',
    'author'       => 'Chriso',
    'url'          => 'https://www.chriso.com',
    'email'        => '[email protected]',
    'extend'       => array(
        \OxidEsales\Eshop\Application\Model\PaymentList::class     => \CHRISO\testmodule\Model\PaymentList::class,
        //\OxidEsales\Eshop\Application\Controller\PaymentController::class     => \OxidEsales\PayPalModule\Controller\PaymentController::class,
    )
);

Model/PaymentList.php

<?php
namespace CHRISO\testmodule\Model;

class PaymentList extends \OxidEsales\EshopCommunity\Application\Model\PaymentList_parent
{
    /**
     * Loads and returns list of user payments.
     *
     * @param string                                   $sShipSetId user chosen delivery set
     * @param double                                   $dPrice     basket product price excl. discount
     * @param \OxidEsales\Eshop\Application\Model\User $oUser      session user object
     *
     * @return array
     */
    public function getPaymentList($sShipSetId, $dPrice, $oUser = null)
    {
        $paymentMethodes = parent::getPaymentList($sShipSetId, $dPrice, $oUser);

        // Da filter

        return $paymentMethodes;
    }
}
?>

Ist es korrekt, dass ich im PaymentList die Klasse PaymentList_parent extende?
Ist es korrekt, dass im composer.json der relative Pfad vom Shop-Root ausgeht?

Ansonsten habe ich keine Idee mehr, wo das Problem liegen könnte.

einfach nur PaymentList_parent, ohne den Namespace. Klick doch mal auf die Links die ich gepostet habe.

In der composer.json des Moduls nicht, da gehört es so wie du es vorher schon hattest. Die composer.json des Moduls wird aber nur verwendet wenn du das Modul aus einem Repository mit “composer require” lädst, machst du das?

Falls nicht, hat composer den Namespace nicht. Du kannst ihn aber manuell in die composer.json des Shops (nicht des Moduls) eintragen, und mit “composer dump-autoload” laden. Da brauchst du dann den relativen Pfad vom Shoproot weil die composer.json des Shops eben da liegt. Steht in dem 2. Link den ich gepostet habe.

Also, da es gerade nicht draufan kommt, habe ich den Namespace eingetragen im shop composer file.
Der Befehl “composer dump-autoload” generiert folgender Fehler:

Parse error: parse error, expecting ';'' or ‘{’’ in /opt/local/www/apache2/html/test.oxid.cwo/my_oxid_eshop_project/vendor/ocramius/package-versions/src/PackageVersions/Installer.php on line 95

Ehrlichgesagt habe ich kein Bock mehr. Denke nicht, dass wir unsere Module auf oxid portieren.
Mal sehen wie wichtig es dem Management ist.

Parse error ist wahrscheinlich falsche PHP-Version der Shell. Oxid benutzt halt composer, wenn man sich damit nicht anfreunden kann dann geht’s nicht.

“autoload”: {
“psr-4”: {
“CHRISO\testmodule\”: “…/…/…/source/modules/CHRISO/testmodule”
}
}
Im composer.json des moduls.

Dann im verzeichnis des moduls:
composer dump-autoload

Generating autoload files

Im Backend nach aktivieren des Moduls:

Es wurden ungültige Module erkannt.

Komme dem Problem nicht auf die Schliche.
Habe nochmals das PayPal Modul kopiert und von vorne angefangen.
Macht zwar nicht wirklich einen Unterschied.

Verzeichnis Struktur
my_oxid_eshop_project
-vendor
-source

public_html (link > my_oxid_ehsop_project/source/)

  • modules
    –CWO
    —protofilter
    ----composer.json
    ----metadata.php
    ----Model
    -----PaymentList.php

metadata.php

<?php

/**
 * Metadata version
 */
$sMetadataVersion = '2.0';

/**
 * Module information
 */
$aModule = array(
    'id'           => 'protofilter',
    'title'        => 'Prototype PaymentMethod Filter',
    'description'  => array(
        'de' => 'Prototype PaymentMethod Filter',
        'en' => 'Prototype PaymentMethod Filter',
    ),
    'version'      => '0.1.1',
    'author'       => 'cwo',
    'url'          => 'https://www.ooooooooo.com',
    'email'        => '[email protected]',
    'extend'       => array(
        \OxidEsales\Eshop\Application\Model\PaymentList::class => \CWO\Protofilter\Model\PaymentList::class
    )
);

Ich muss den Post aufteilen…

composer.json

 {
  "name": "cwo/protofilter",
  "description": "Prototype PaymentMethod Filter",
  "type": "oxideshop-module",
  "keywords": ["oxid", "modules", "eShop"],
  "homepage": "https://www.ooooooooooooo.com",
  "license": [
    "GPL-3.0-only",
    "proprietary"
  ],
  "extra": {
    "oxideshop": {
      "target-directory": "CWO/protofilter"
    }
  },
  "require": {
    "php": ">=5.6",
    "lib-curl": "*",
    "lib-openssl": "*",
    "ext-curl": "*",
    "ext-openssl": "*"
  },
  "autoload": {
    "psr-4": {
      "CWO\\Protofilter\\": "../../../modules/CWO/protofilter"
    }
  }
}

Composer hat dem Namespace richtig erkannt.
protofilter/vendor/composer/autoload_psr4.php

 <?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__)); // CWO/protofilter/vendor/composer/../ => CWO/protofilter/vendor/
$baseDir = dirname($vendorDir); // CWO/protofilter/vendor/.. => CWO/protofilter/

return array(
    'CWO\\Protofilter\\' => array($baseDir . '/'),
);

$baseDir . '/' sollte dabei korrekt auf modules/CWO/protofilter/ verweisen.

Model/PaymentList.php

<?php
namespace CWO\Protofilter\Model;

class PaymentList extends PaymentList_parent
{
    /**
     * PaymentList class wrapper for Protofilter module
     *
     * Loads,returns and filter list of user payments.
     *
     * @param string                                   $sShipSetId user chosen delivery set
     * @param double                                   $dPrice     basket product price excl. discount
     * @param \OxidEsales\Eshop\Application\Model\User $oUser      session user object
     *
     * @return array
     *
     * @mixin \OxidEsales\EshopCommunity\Application\Model\PaymentList
     */
    public function getPaymentList($sShipSetId, $dPrice, $oUser = null)
    {
        $paymentMethods = parent::getPaymentList($sShipSetId, $dPrice, $oUser);

        // Da filter

        return $paymentMethods;
    }
}
?>

Im PayPal Modul ist die psr-4 Angabe etwas anders aufgebaut.

"autoload": {
    "psr-4": {
        "OxidEsales\\PayPalModule\\": "../../../source/modules/oe/oepaypal"
    }
}

Desshalb habe ich auch in meinem Modul verschiedenes Ausprobiert, zB.:

"autoload": {
"psr-4": {
  "CWO\\Protofilter\\": "../../../source/modules/CWO/protofilter"
}

}
Aber auch noch einiges anderes.

Zwischen meinen Test habe ich jeweils:

  • tmp verzeichnis geleert
  • DELETE FROM oxconfig WHERE OXVARNAME LIKE '%module%' ausgeführt
  • und entweder composer update oder composer dump-autoload laufen lassen
    (composer über PHP 7.0 und PHP 5.6, je nachdem auf was Oxid gerade lief)

Wo mach ich etwas falsch?
Was habe ich falsch verstanden?

Wo (in welchem File) entscheidet Oxid, dass das Modul ungültig ist?
Ich würde mich dort gerne einhängen um mehr über das Problem zu erfahren.

Unterstützt Oxid MacOS Sierra?

Ich verwende Oxid ehsop CE 6.0.
PHP7.0 (habe auch Tests mit PHP 5.6 durchgeführt)

Also … des Shops (nicht des Moduls)!