Bei plugin-Installation feststellen, welches theme beim User aktiv ist

Hallo zusammen,

ich habe folgendes Anliegen: Bei dem plugin das ich gerade entwickle ist es wichtig, dass ich, wenn der User bei sich das plugin installiert, währenddessen im Hintergrund feststellen kann, welches theme beim User gerade aktiv ist. Ich wollte das jetzt erstmal über die Datenbank probieren, aber dort habe ich bisher keinen Wert gefunden, der dabei hilfreich sein könnte.
Gibt es einen Wert, auf den ich im Backend auch zugreifen kann, der mir sagen kann, welches theme gerade aktiv ist?

Beste Grüße
Olli

1 „Gefällt mir“

Hi, also in s_core_shops hast du die template_id und dazu wiederrum findest du infos in  s_core_templates

1 „Gefällt mir“

Hi brettvormkopp,

klasse, genau das habe ich gebraucht. Vielen Dank für die Antwort. Jetzt möchte ich gerne diesen Wert während der Installation meines plugins ermitteln, aber ich befinde mich ja im Backend. Ist das denn dort dann auch so möglich:

 

$connection = $this->container->get('dbal_connection');
$db_theme_used_id = Shopware()->Db()->select('template_id')->from('s_core_shops');
$db_theme_used_name = Shopware()->Db()->select('template')->from('s_core_template')->where('id = ?', $db_theme_used_id);

Oder muss ich mich dafür nun in die zehnte Programmiersprache einarbeiten? :wink:

Beste Grüße
Olli

Hilft Dir jetzt nicht weiter, aber was machst Du, wenn der Shop noch Subshops hat? Dann hat Dein Shop mehrere “aktive” Themes.

1 „Gefällt mir“

@sonic schrieb:

Hilft Dir jetzt nicht weiter, aber was machst Du, wenn der Shop noch Subshops hat? Dann hat Dein Shop mehrere „aktive“ Themes.

Das ist eine sehr gute Frage. Es geht darum, dass ich an zwei oder drei template-Dateien des Shops, der sich das plugin installiert, Änderungen vornehmen muss. Das sind checkout/items/product.tpl, detail/index.tpl und home/index.tpl. Hier müssen Blöcke unter bestimmten Bedingungen komplett rausgenommen werden oder Blöcke ergänzt werden.

Okay, habe es nun mal getestet mit folgendem php-Code:

 

public function install(InstallContext $context) 
	{
		// NAMEN DES AKTIVEN THEMES ERMITTELN
		$connection = $this->container->get('dbal_connection');
		$theme_used_id = Shopware()->Db()->select('template_id')->from('s_core_shops');
		$theme_used_name = Shopware()->Db()->select('template')->from('s_core_template')->where('id = ?', $theme_used_id);
		
		$file = 'custom/plugins/xxx/Resources/checkout/items/product.tpl';
		$newfile = 'themes/Frontend/'.$theme_used_name.'/frontend/checkout/items/product.tpl';
		if (!copy($file, $newfile)) {
			echo "copy $file schlug leider fehl. Bitte wenden Sie sich an Ihren Administrator!\n";
			}
			
		$file = 'custom/plugins/xxx/Resources/detail/index.tpl';
		$newfile = 'themes/Frontend/'.$theme_used_name.'/frontend/detail/index.tpl';
		if (!copy($file, $newfile)) {
			echo "copy $file schlug leider fehl. Bitte wenden Sie sich an Ihren Administrator!\n";
			}
			
		$file = 'custom/plugins/xxx/Resources/home/index.tpl';
		$newfile = 'themes/Frontend/'.$theme_used_name.'/frontend/home/index.tpl';
		if (!copy($file, $newfile)) {
			echo "copy $file schlug leider fehl. Bitte wenden Sie sich an Ihren Administrator!\n";
			}
		$dstfile = "media/image/.00customized_pics";
		mkdir(dirname($dstfile), 0777, true);
			
		return true;
	}

Ergebnis: Das plugin lädt sich beim Installieren tod, Tab geschlossen, Backend neu geöffnet, plugin ist zwar installiert, aber hat die oben enthaltenen Operationen nicht durchgeführt. :frowning: Error-Log sowohl auf dem Server als auch bei SW zeigt allerdings keine Fehler an.
Wie ist der richtige Weg?

Ich verstehe nicht, was Du vor hast Wink
Du willst wärend der Instalation Dateien vom Theme austauschen? Was machst Du, wenn der User das Theme mal ändert? Shopware am Basistheme (Bare) etwas umbaut?
Eigentlich wäre der richtige Weg, sich an ein Event zu hängen, und beim Aufruf der zugehörigen Seite im Theme-Zweig vom Plugin die Blöcke zu überschreiben oder ändern.  Undecided

Mhm, ich habe das bisher so verstanden, dass wenn ich ein template ändern will ich IMMER auch im entsprechenden Ordner meines child-themes dieses template ablegen muss, das dann z.b. so aussehen kann, in dem Fall ein Einbinden einer css-Datei im header:

 

{* externes Stylesheet *}
{extends file='parent:frontend/index/header.tpl'}

{block name="frontend_index_header_css_screen" append}



{/block}

Also dachte ich muss ich doch in jedem Fall auf die Ordner zugreifen und dort eine template-Datei ablegen oder?

Nö.
Wie ein eigenes von Bare / Respo9nsive abgeleitetes Theme einzelne Blöcke in Datein ändern und überschreiben kann, kann das auch ein Plugin. Steht aber so in den Dokus oben unter “Developers”
Du Registriest zur Laufzeit auf ein Event den Pfad zu Deinem Plugin/Theme-Pfad und hast dort wieder die gleiche Struktur, wie im Theme und überschreibst dort wahlweise Dateien/Blöcke

Lese Dich mal durch die Doku - oder kauf Daniels Buch :slight_smile:

@sonic schrieb:

Du Registriest zur Laufzeit auf ein Event den Pfad zu Deinem Plugin/Theme-Pfad und hast dort wieder die gleiche Struktur, wie im Theme und überschreibst dort wahlweise Dateien/Blöcke

Lese Dich mal durch die Doku - oder kauf Daniels Buch :)

Danke für den Tipp, immerhin wird das plugin jetzt hochgeladen und installiert, allerdings funktioniert ansonsten auch nichts. 
Das Buch habe ich ja schon länger hier, aber auch an dieser Stelle finde ich die Beschreibungen der Vorgehensweise wieder sehr lückenhaft. Für mich ist auf den entsprechenden Seiten 139 bis 145 absolut unklar wie der Zusammenhang ist zwischen dem ersten plugin und dem zweiten, wie welche Ordner und Dateien wo angelegt werden müssen.
Habe versucht, alles so gut wie möglich einzuhalten, aber irgendwo muss ich noch was falsch machen…

Ich habe also nun das theme-Verzeichnis, das ich im Einsatz habe (wie soll das denn eigentlich später gehen wenn das plugin bei anderen installiert wird (?), nochmal in mein plugin kopiert in den Ordner Resources/Themes/Frontend/meintheme/
Dann habe ich in meinem plugin meine public static function getSubscribedEvents()…
erweitert um:

'Enlight_Controller_Front_StartDispatch' => 'onGetControllerPath',

Meine onGetControllerPath sieht dann so aus:
 

public function onGetControllerPath (\Enlight_Controller_EventArgs $args)
	{
		$this->container->get('Template')->addTemplateDir (
			$this->getPath() . '/Resources/Views/'
		);
		
		return $this->getPath() . '/Controllers/Frontend/meinplugin.php';
	}

So, dann wird es im Buch total verwirrend.
Was ist mit dem Verzeichnis „Resources/Views/“ - muss ich das auch noch in meinem plugin anlegen? Und da muss da dann diese index.tpl rein?
 

{extends file='parent:frontend/index/index.tpl'}

{block name="frontend_index_content"}

{/block}

Was ist mit dem Verzeichnis „/Controllers/Frontend/“ - muss ich das auch noch in meinem plugin anlegen und meine plugin-php-Datei dort auch nochmal ablegen?

Dann war ja immer noch die Frage nach der Installations-Funktion:

 

public function install(InstallContext $context) 
	{
		// NAMEN DES AKTIVEN THEMES ERMITTELN
		$connection = $this->container->get('dbal_connection');		
		
		$theme_used_id_prep = "SELECT template_id FROM s_core_shops";
		$theme_used_id = $connection->query($theme_used_id_prep);
		
		$theme_used_name_prep = "SELECT template FROM s_core_templates WHERE id = '$theme_used_id'";
		$theme_used_name = $connection->query($theme_used_name_prep);
		
		$dstfile = "media/image/.00customized_pics";
		mkdir(dirname($dstfile), 0777, true);

        return true;
	}

Okay, die Ermittlung des aktiven themes brauche ich ja nun gar nicht mehr, aber ist es möglich dieses Verzeichnis, das ich zwingend brauche, in dieser Form anzulegen? Eine Fehlermeldung gibt es diesbezüglich nicht, aber angelegt wird halt auch nichts. Zugriffsrechte sind vorhanden.

Im Prinzip machst du folgendes, du registrierst dich zunächst auf ein Event (bspw. den Blog-Controller):

    public static function getSubscribedEvents()
    {
        return [
            'Enlight_Controller_Action_PostDispatchSecure_Frontend_Blog' => 'onFrontendPostDispatchBlog'
        ];
    }

Danach registrierst du das Theme-Verzeichnis deines Plugins:

    public function onFrontendPostDispatchBlog(\Enlight_Controller_ActionEventArgs $args)
    {
        /** @var \Enlight_Controller_Action $controller */
        $controller = $args->get('subject');
        $view = $controller->View();
        $this->container->get('Template')->addTemplateDir(
        $this->getPath() . '/Resources/views/'
        );
    }

Und danach legst du deine Datei im Verzeichnis ~Pluginverzeichnis/Resources/views/frontend/blog/detail.tpl ab. Die könnte so aussheen:

{extends file="parent:frontend/blog/detail.tpl"}

{block name='frontend_index_content'}
	{$smarty.block.parent}
        {include file='plugins/Testplugin/DoSomethingInBlog.tpl'}
{/block}

Deine eigentliche Logik legst du dann in ~Pluginverzeichnis/Resources/views/plugins/Testplugin/ ab. Das funktioniert einwandfrei.

Für Less müsstest du dich noch zusätzlich registrieren. die Beispiele sind für das neue Plugin-System. Less kannst du bspw. per Subscriber machen.

    public static function getSubscribedEvents()
    {
        return [
            'Theme_Compiler_Collect_Plugin_Less' => 'addLessFiles'
        ];
    }
    /**
     * Provides the less files for compression
     *
     * @return ArrayCollection
     */
    public function addLessFiles()
    {
        $less = new LessDefinition(
            [], // configuration
            [__DIR__. '/../Resources/views/frontend/_public/src/less/all.less'], // less files to compile
            __DIR__ // import directory
        );
        return new ArrayCollection([$less]);
    }
}

Steht aber auch alles in der Doku:

https://developers.shopware.com/developers-guide/plugin-system/#search-results

 

1 „Gefällt mir“

@Moritz Naczenski schrieb:

Im Prinzip machst du folgendes, du registrierst dich zunächst auf ein Event (bspw. den Blog-Controller):

public static function getSubscribedEvents()
{
return [
‚Enlight_Controller_Action_PostDispatchSecure_Frontend_Blog‘ => ‚onFrontendPostDispatchBlog‘
];
}

Danach registrierst du das Theme-Verzeichnis deines Plugins:

public function onFrontendPostDispatchBlog(\Enlight_Controller_ActionEventArgs $args)
{
/** @var \Enlight_Controller_Action $controller */
$controller = $args->get(‚subject‘);
$view = $controller->View();
$this->container->get(‚Template‘)->addTemplateDir(
$this->getPath() . ‚/Resources/views/‘
);
}

Und danach legst du deine Datei im Verzeichnis ~Pluginverzeichnis/Resources/views/frontend/blog/detail.tpl ab. Die könnte so aussheen:

{extends file=„parent:frontend/blog/detail.tpl“}

{block name=‚frontend_index_content‘}
{$smarty.block.parent}
{include file=‚plugins/Testplugin/DoSomethingInBlog.tpl‘}
{/block}

Deine eigentliche Logik legst du dann in ~Pluginverzeichnis/Resources/views/plugins/Testplugin/ ab. Das funktioniert einwandfrei.

Für Less müsstest du dich noch zusätzlich registrieren. die Beispiele sind für das neue Plugin-System. Less kannst du bspw. per Subscriber machen.

public static function getSubscribedEvents()
{
return [
‚Theme_Compiler_Collect_Plugin_Less‘ => ‚addLessFiles‘
];
}
/**

  • Provides the less files for compression
  • @return ArrayCollection
    */
    public function addLessFiles()
    {
    $less = new LessDefinition(
    , // configuration
    [DIR. ‚/…/Resources/views/frontend/_public/src/less/all.less‘], // less files to compile
    DIR // import directory
    );
    return new ArrayCollection([$less]);
    }
    }

Steht aber auch alles in der Doku:

https://developers.shopware.com/developers-guide/plugin-system/#search-results

 

Vielen Dank erstmal für die Hilfestellung.
Ich habe das alles exakt so umgesetzt, aber es funktioniert nach wie vor nicht. :frowning:
Ich habe mein theme nun unter custom/plugins/meinPlugin/Resources/views/plugins/meinPlugin/ abgelegt und unter custom/plugins/meinPlugin/Resources/views/frontend/detail/ die modifizierte index.tpl abgelegt bzw. die index.tpl abgelegt, die wie von Dir beschrieben, auf die index.tpl im Ordner custom/plugins/meinPlugin/Resources/views/frontend/detail/ verweist. Da tut sich leider aber gar nichts im Frontend. :frowning:
Ich muss dazu sagen, dass die Änderungen und die Logik des plugins einwandfrei funktionieren solange ich die modifizierten template-Dateien normal in meinem child-theme liegen habe. Nur jetzt bei der Installation bekomme ich das einfach nicht abgebildet. Habe es ja erst so probiert wie im Buch von Daniel beschrieben, aber das funktionierte genauso wenig. Wobei er das ja wieder ganz anders beschreibt wie Du? In der Doku finde ich weiterhin nichts, was mir dabei wirklich weiterhelfen könnte und das was ich finde funktioniert in der Regel auch nicht. Na ja, ich probiere weiter…

Frustrierte Grüße
Olli

Hast du das Plugin jedes Mal neu installiert? 

Generell kannst du ja erstmal testen ob er überhaupt in die Funktion reingeht, in der du dein Template registrierst, indem du da ein die(); setzt.

Ich hab mein Beispiel aus einem Plugin, was ich selbst gebastelt habe. Das funktioniert.

Ja, ich installiere jedes Mal alles neu.
Ich registriere mich ja auf zwei Events. Einmal ‚Enlight_Controller_Action_Frontend_Checkout_Cart‘ und ‚Shopware_Modules_Order_SendMail_Send‘. Die Funktion zum zweiten Event macht am Schluß - nach Abschluss der Bestellung - eine Probevariablenausgabe und die funktioniert auch, d.h. die Funktion wird durchlaufen. Das Einzige was nicht funktioniert sind die (kleinen aber elementaren) Änderungen an 3 templates, die ich vornehmen muss.

Okay, mittlerweile habe ich dann festgestellt, dass ich mich natürlich auf noch ein Event registrieren muss, da in der Detailansicht in unserem Shop bei vielen Artikeln der „In den Warenkorb“ Button rausgenommen wird, Also habe ich mich noch auf das Event ‚Enlight_Controller_Action_PreDispatch_Frontend_Detail‘ registriert und rufe dort diese Funktion auf:
 

public function onGetControllerPath (\Enlight_Controller_EventArgs $args)
	{
		/** @var \Enlight_Controller_Action $controller */
        $controller = $args->get('subject');
        $view = $controller->View();
        $this->container->get('Template')->addTemplateDir(
        $this->getPath() . '/Resources/views/plugins/meinPlugin/'
        );
	}

Ergebnis: Keines. Eine Probeausgabe führte zu der Erkenntnis, dass diese Funktion nicht mal aufgerufen wird. Ich verstehe das nicht. Seit 1,5 Tagen versuche ich nun irgendwie die geänderten template-Dateien einzubauen… :frowning:

Und danach legst du deine Datei im Verzeichnis ~Pluginverzeichnis/Resources/views/frontend/blog/detail.tpl ab. Die könnte so aussehen:

{extends file=„parent:frontend/blog/detail.tpl“}

{block name=‚frontend_index_content‘}
{$smarty.block.parent}
{include file=‚plugins/Testplugin/DoSomethingInBlog.tpl‘}
{/block}

Ich glaube, dass hier der Fehler bei mir liegt. 
Ich muss u.a. die Datei detail/index.tpl komplett überschreiben und mache das glaube ich falsch:

Ich sage im Ordner MeinPlugin/Resources/views/frontend/detail/index.tpl nur

{extends file=„parent:plugins/MeinPlugin/detail/index.tpl“}
{$smarty.block.parent}

Im entsprechenden plugin-Ordner liegt dann die komplette detail/index.tpl - ist das richtig so? Oder muss ich expilizit einzelne Blöcke appenden oder prependen?
 

Schöner sind natürlich einzelne Blöcke. Wenn du direkt etwas in der Detail.tpl in deinem pluginverzeichnis änderst, dann brauchst du auch das include nicht. Aber ich verstehen immer noch nicht, Wasa genau du machst, schick mir mal dein Plugin an forum@shopware.de - ich bin morgen wieder im Büro und schaue dann mal rein.

1 „Gefällt mir“

@Moritz Naczenski schrieb:

Schöner sind natürlich einzelne Blöcke. Wenn du direkt etwas in der Detail.tpl in deinem pluginverzeichnis änderst, dann brauchst du auch das include nicht. Aber ich verstehen immer noch nicht, Wasa genau du machst, schick mir mal dein Plugin an forum@shopware.de - ich bin morgen wieder im Büro und schaue dann mal rein.

Vielen Dank für das Angebot. Ja, exakt das ist das Thema mit dem „… ich verstehe immer noch nicht…“ - genau deshalb schreibe ich das plugin. :wink: Das verstehen nämlich viele nicht, deshalb könnte das plugin auch für viele interessant sein, wenn ich es denn mal zum Laufen bekomme. :wink: Als erstes Projekt mit SW, das ich bis vor ein paar Wochen nur vom Hören/Sagen kannte, ist das echt ein Klopper.

Hallo,

ich hab gerade im Zug dein Plugin mal überflogen. So richtig hast du das mit der Theme-Vererbung noch nicht verstanden. Generell ist die Reihenfolge in Shopware wie folgt:

Bare -> Responsive > Plugins > KundenTheme

Du erweiterst also mit deinem Plugin das Bare-Theme. Ich habe dir mal ein einfaches Beispiel angehängt. Das Beispielplugin gibt das Attribut3 unter den anderen Attributfeldern auf der Detailseite aus. Dafür erweitere ich einen Block und füge dort ein eigenes Template mit ein. Das {$smarty.block.parent} ist dabei gleichzusetzen mit append/prepend - wenn es vor deiner Anpassung steht ist es ein prepend, wenn davor ein append. Wenn du beides weglässt, dann überschreibst du den Block komplett. 

Hier das Beispiel-Plugin: http://5.189.189.70/Beispielplugin/ChangeDetailPage.zip

Dein Plugin lies sich bei mir schon garnicht installieren, da du die falschen Parameter für deine onGetControllerPath-Funktion übergibst. Auch ist dein /views/-Verzeichnis nicht korrekt aufgebaut. 

1 „Gefällt mir“

@Moritz Naczenski schrieb:

Hallo,

ich hab gerade im Zug dein Plugin mal überflogen. So richtig hast du das mit der Theme-Vererbung noch nicht verstanden. Generell ist die Reihenfolge in Shopware wie folgt:

Bare -> Responsive > Plugins > KundenTheme

Du erweiterst also mit deinem Plugin das Bare-Theme. Ich habe dir mal ein einfaches Beispiel angehängt. Das Beispielplugin gibt das Attribut3 unter den anderen Attributfeldern auf der Detailseite aus. Dafür erweitere ich einen Block und füge dort ein eigenes Template mit ein. Das {$smarty.block.parent} ist dabei gleichzusetzen mit append/prepend - wenn es vor deiner Anpassung steht ist es ein prepend, wenn davor ein append. Wenn du beides weglässt, dann überschreibst du den Block komplett. 

Hier das Beispiel-Plugin: http://5.189.189.70/Beispielplugin/ChangeDetailPage.zip

Dein Plugin lies sich bei mir schon garnicht installieren, da du die falschen Parameter für deine onGetControllerPath-Funktion übergibst. Auch ist dein /views/-Verzeichnis nicht korrekt aufgebaut. 

Erstmal vielen Dank für die Hilfe an Dich!
Du hast Recht, ich hatte es bisher nur so gesehen: Bare -> Responsive > KundenTheme - Das plugin-theme hatte ich mir bisher gar nicht richtig reingedacht, weil ich ja das erste Mal überhaupt entwickelt habe in SW und die zu ändernden tpl-Dateien einfach in meinem von Responsive abgeleiteten theme abgelegt habe. Wenn ich es aber jetzt dynamisch als plugin umsetzen will  muss ich das natürlich nun zwingend mitbeachten und blicke nicht mehr ganz durch. :-o
Das mit dem plugin ist merkwürdig - ich wünschte ich hätte es bei mir auch nicht installieren können und es wäre eine Fehlermeldung erschienen, dann wäre ich nicht nun mittlerweile den dritten Arbeitstag am rumrätseln was hier nicht funktioniert.
Mit dem views-Verzeichnis ist mir nicht ganz klar - es sieht doch so aus wie in Deinem Beispiel, nur dass ich in dem Ordner ChangeDetailPage/Resources/views/plugins/MeinPlugin/ dann das komplette theme nochmal abbilde. Ist das falsch?
Mit den Parametern habe ich überhaupt nicht drauf geachtet bisher. :-o Das muss ich nochmal checken…

Deine Template Dateien liegen im falschen Verzeichnis. Du müsstest die unter …/views/frontend/detail bspw. packen. Und auch entsprechend das Verzeichnis korrekt registrieren. Aktuell würde es auch nur auf der Detail Page hinzugefügt. Wenn du mehrere Seiten anpasst kannst du besser _detail bei dem Event weglassen und dich auf das komplette Frontend registrieren.

1 „Gefällt mir“