Archive for the ‘Allgemein’ Category

Magento2: Attribute eines Produkts aus einer bestimmten Attributgruppe

15. Dezember 2016

Um im Magento in einer phtml Datei alle Attribute eines Produkts, die zu einer bestimmten Gruppe (namens “customattributes”) gehören, habe ich mir einen Helper geschrieben, der folgendes macht:

  1. class Product extends \Magento\Framework\App\Helper\AbstractHelper
  2. {
  3. const CUSTOMATTRIBUTE_GROUP_NAME = 'customattributes';
  4. public $groupCollectionFactory;
  5. public function __construct(
  6. \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory $groupCollectionFactory
  7. ){
  8. $this->groupCollectionFactory = $groupCollectionFactory;
  9. }
  10. public function getAttributesForProduct($_product){
  11. $groupCollection = $this->groupCollectionFactory->create();
  12. $groupCollection->addFieldToFilter('attribute_group_name',self::CUSTOMATTRIBUTE_GROUP_NAME);
  13. $groupCollection->addFieldToFilter('attribute_set_id', $_product->getAttributeSetId());
  14. $group = $groupCollection->getFirstItem();
  15. $data = array();
  16. $c = 0;
  17. $productAttributes= $_product->getAttributes();
  18. foreach ($productAttributes as $attribute) {
  19. if ($attribute->isInGroup($_product->getAttributeSetId(), $group->getAttributeGroupId())) {
  20. if ($attribute->getFrontend()->getValue($_product)) {
  21. $data[$c]['attribute'] = $attribute->getFrontendLabel();
  22. $data[$c]['value'] = $attribute->getFrontend()->getValue($_product);
  23. $c++;
  24. }
  25. }
  26. }
  27. return $data;
  28. }
  29. }

Das liefert ein schönes Array mit allen Attributen und ihren Werten für das aktuelle Produkt zurück.

SSH: alle Symlinks des aktuellen Ordners mit Pfad anzeigen

27. September 2016

Ganz einfach (wenn mans weiß):

  1. find ./ -type l -ls

Google Maps Api: Karte wird nur grau dargestellt, verzerrte Buttons

11. November 2015

Nach dem einbinden von Google maps mit der API (v3) wurde die Map teilweise nur in grau dargestellt und die Buttons waren merkwürdig verzerrt:
karte
Stellt sich raus, der Übeltäter war Bootstrap. Das setzt img nämlich auf max-width:100% oder sowas. Die Lösung:

  1. #map-canvas img {
  2. max-width: none !important;
  3. }

Und damit gehts dann auf einmal.

Zend Framework 2 – Exception fangen

25. November 2014

Klingt trivial, ist es auch, aber man muss es halt doch mal wissen. Zend Framework baut sich sein ganz eigenes Errorhandling und als ich versuchte, eine Exception mit try und catch(Exception $e) aufzufangen, bewirkte das genau gar nichts. Warum? Man muss catch(\Exception $e) schreiben. Konkret versuchte ich mich an einer IMAP Verbindung zu einem Mailserver:

  1. $mail = new \Zend\Mail\Storage\Imap(array(
  2.     'host'     => 'imap.gmail.com',
  3.     'user'     => 'USERNAME@gmail.com',
  4.     'password' => 'PASSWORD',
  5.     'ssl'      => 'SSL',
  6.     'port'     => 993
  7. ));

Wenn die Logindaten nicht stimmen, dann wirft das einen Fehler. Um diesen zu fangen und im Falle falscher Logindaten zu reagieren, fange ich das ganze so auf:

  1. try{
  2.     $mail = new \Zend\Mail\Storage\Imap(array(
  3.         'host'     => 'imap.gmail.com',
  4.         'user'     => 'USERNAME@gmail.com',
  5.         'password' => 'PASSWORD',
  6.         'ssl'      => 'SSL',
  7.         'port'     => 993
  8.     ));
  9. }catch(\Exception $e){
  10.     die("wrong credentials!");
  11. }

Und mit \Exception klappts dann auch im Zend Framework.

Offtopic: World of Warcraft in Linux Mint spielen

14. September 2014

Ich habe mich 2 Tage lang gequält, um das ganze endlich hinzubekommen. Ich habe nun Wine1.7 installiert, das folgendermaßen konfiguriert ist:
Windows Version: Windows XP
Libraries -> Existing_overrides: dbghelp (disabled)

Meine WTF Datei im WOW Ordner hat die folgenden zusätzlichen Werte:

  1. SET Sound_OutputDriverName "Systemstandard"
  2. SET ffxDeath "0"
  3. SET ffxGlow "0"
  4. SET SoundOutputSystem "1"
  5. SET SoundBufferSize "150"
  6. SET lastCharacterIndex "9"

Ich habe mir auf dem Desktop eine ausführbare wowlaunch.txt gemacht, mit der ich das Spiel starte. Die sieht so aus:

  1. WINEDEBUG=-all wine "/media/USERNAME/Daten/spiele/World of Warcraft/WoW.exe" -opengl

Das half auch ganz gut, allerdings stürzte WoW sofort nach dem einloggen ab, mit dem Error 132, memory could no be “executed”.

Dann habe ich driconf installiert:

  1. sudo apt-get install driconf

Und eeendlich gehts!

1000 Dank an diesen hilfreichen Beitrag

Der Facebook Like Button vs. Designer: Runde 2402

22. Juni 2012

Facebook hat sich ja vor einer ganzen Weile schon entschieden, den Teilen Button nicht weiter zu unterstützen. Tatsächlich haben sie den sehr gut modifizierbaren Share Button durch den starren, sehr eingeschränkten Like/Recommend Button ersetzt. Was heißt das für Designer?

Fakt 1: Den Teilen (Share) Button GIBT es nicht  mehr.

Ich kann das gar nicht oft genug sagen, aber es kommen immer noch Anfragen für Webseiten mit dem Share Button. Weil der so schön modifizierbar war. Da konnte der Designer von Welt sich so richtig austoben. Nachdem  die Nachfrage einfach nicht stoppen will, habe ich mir schließlich einen Weg überlegt, um den Kunden zu geben, was sie wollen: man kann den Share Button simulieren und damit jedes Designerherz höher schlagen lassen. Dann können sie nach Herzenslust einen Button gestalten und man ruft via Javascript halt die FB.ui method:stream.publish. So fordert man den User auf, einen Wallpost zu machen. Dies funktioniert dann in etwa so:

  1.     <a href="#" onclick="shareStuff()">Teilen!</a>
  2.     <script type="text/javascript">    
  3.     function shareStuff(){
  4.             FB.ui({
  5.                         method: 'stream.publish',
  6.                         message: '',
  7.                         attachment : {
  8.                             name: 'Dies ist der Titel des Wallposts',
  9.                             caption: '',
  10.                             description: 'der lange Text des Wallposts blablablablabla',
  11.                             href:'https://www.facebook.com/pages/xxx/app_0000000000',
  12.                             media: [{
  13.                             type: 'image',
  14.                             href: 'https://www.facebook.com/pages/xxx/app_0000000000',
  15.                             src: 'img/logo_share.jpg'
  16.                           }]
  17.                         },
  18.                         action_links: [
  19.                     { text: 'Mitspielen!', href: 'https://www.facebook.com/pages/xxx/app_0000000000' }
  20.                 ]
  21.         });            
  22.     }
  23.     </script>

Statt dem Text kann man nun an der Stelle seinen gestylten Button einbauen und macht so den Designer glücklich. Der weiß natürlich nicht, dass für seinen heißgeliebten Share Button nicht mehr nur ein Snippet kopiert werden musste, und sieht einen dann fragend an, wenn man ihm versucht zu erklären, warum man statt 5 Minuten eine halbe Stunde gebraucht hat für seinen blöden Button.

Fakt 2: Der Like Button sieht nicht so aus, wie Designer das glauben

Wenn man den Gestalter doch soweit hat, mit dem Likebutton zu arbeiten statt sich den Share Button einzubilden, gilt es, ihm klarzumachen, dass seine Vorstellung vom Likebutton FALSCH ist. Sehen wir uns doch mal einen kleinen Vergleich an:

DIES IST KEIN LIKEBUTTON!So sieht er nur aus, wenn noch keine einzige Person “gefällt mir” geklickt hat. Idealerweise werden aber sehr viele Leute klicken, also sollte er diesen Status nicht lange behalten. So könnte ein Likebutton aussehen.Es gibt auch noch 2 andere Varianten, aber es zeigt, dass der Likebutton für gewöhnlich NICHT einfach so alleine steht. er hat mindestens einen Zähler dabei und wenn man klickt, öffnet sich ein Detailfenster zur Texteingabe.

Ich glaube, hier wird schon deutlich, wo das Problem liegt. Der Designer nimmt das, was er für den Likebutton hält, als Vorlage, und quetscht es ins Design. Und wundert sich dann, wenn der Likebutton mit seinem Counter andere Elemente überdeckt. Gestalter scheinen sowieso ein natürliches Gespür für das Unpraktische zu haben, darum kann man eigentlich davon ausgehen, dass der Designer den Button irgendwo ganz nach rechts platziert (und dann total entsetzt ist, wenn er draufklickt, das Textfenster nach rechts aufgeht und eine SCROLLBAR erscheint).

Mein eindringlicher Rat ist es deshalb, dem Gestalter frühzeitig mitzuteilen, dass seine Vorstellung des Likebuttons schlicht und ergreifend nicht den Tatsachen entspricht und dass er idealerweise genügend Platz für den Counter und das Textfenster einkalkuliert. Ein auf diese Weise gebriefter Designer wird sich neue und kreative Wege überlegen, den Likebutton ästhetisch in sein Layout einzubauen.

…und dann wache ich auf weil mein Wecker klingelt. Nein, die Erfahrung zeigt, dass der Designer sich in seinem ästhetischen Empfinden verletzt fühlen wird und darauf bestehen wird, dass man einen Weg findet, den Counter und das Textfeld auszublenden. Soviel zum Thema Flexibilität der Designer. Und ich habe mich dem gefügt und es gibt tatsächlich einen Weg, beides auszublenden. Den Counter blendet man aus, indem man die Größe des iframes definiert. Hier ist allerdings auf eines zu achten: der gute alte Safari (auf MacOSX) braucht natürlich eine Extrawurst, der hat einen breiteren Likebutton. Muss man also eine Browserweiche machen.

  1. <?php
  2. $w = 78;
  3. $agent = $_SERVER["HTTP_USER_AGENT"];
  4. if (strrpos($agent, "Safari") > -1)
  5.     $w = 83;
  6. ?>
  7. <style>
  8.      body{padding:0px;margin:0px;}
  9.      .fb_edge_widget_with_comment span.fb_edge_comment_widget iframe.fb_ltr {display: none !important;}
  10.     .fb-like iframe{width:<?=$w?>px !important;}
  11. </style>
  12. <div data-href="LIKEURL" data-send="false" data-layout="button_count" data-width="78" data-show-faces="true"></div>

Und damit werden die Count Bubble und der Text versteckt. Und der Designer ist dann hoffentlich auch glücklich. Wird sich zeigen, ob Facebook das länger mitmacht.

wordpress: nextgen Problem nach Server Transfer

18. Januar 2012

Nachdem ich ein wordpress Projekt von Server A nach Server B übertragen hatte, waren plötzlich sämtliche nextgen Konfigurationen verschwunden. Sämtliche Galerien auf der Seite funktionierten nicht mehr, stattdessen wurden einfach alle Bilder unformatiert und ohne hübsche Slideshow angezeigt.

Das Problem lässt sich mit Datenbankzugang folgendermaßen beheben: in wp_options den Eintrag finden wo option_name = ngg_options und dann option_value von der alten Datenbank holen und reinkopieren. Die Werte in option_value sind offenbar die config Werte der Galerie und werden aus irgendeinem Grund nicht richtig eingetragen in die Datenbank.

 

Shell….

23. August 2011

Unfassbar. Wirklich, es ist peinlich, dass ich sowas nicht weiß. Ich bin ein Kind des DOS-Modus, meine ersten PC-Spiele habe ich über DOS Befehle gestartet. Aber mit Shell Befehlen hab ich halt nichts am Hut und alles, was ich bisher damit machen musste, war eine Mischung aus verzweifeltem Raten, googeln von Befehlen und beten. Ich bin dankbar, dass ich trotz diversen root Zugängen zu großen Projekten nie irgendwas zerstört habe.

Und da ich aktuell ein php Script über shell-Befehle ausführen muss, habe ich mit Entsetzen festgestellt: ich weiß nicht, wie man ein Script unterbricht. Darum ein Memo an mich:

Laufende Scripte beendet man mit CRTL + C !

Wie peinlich. Danke an diese Seite und den Punkt 5.4.

Typo3: Einen neuen BE Benutzer anlegen

04. April 2011

Inzwischen musste ich schon oft genug einen neuen Backend Benutzer anlegen und hatte dabei eigentlich immer wieder dieselben Schwierigkeiten: der Seitenbaum wurde erstmal nicht angezeigt und wenn der dann endlich da war, war die Dateiliste leer. Daher wiedermal meine schrittweise Anleitung zum Erstellen eines BE Benutzers, ohne Anspruch auf Vollständigkeit und möglicherweise auch mit einigen überflüssigen Schritten.

1. einen neuen Benutzer erstellen
Unter “Benutzer” den neuen Benutzer erstellen. Benutzername und Passwort ausfüllen und ggf. eine Standardsprache auswähklen. Speichern und dann eine neue Gruppe erstellen mit Klick auf das PLUS unter Gruppe.

2. neue Gruppe erstellen
einen aussagekräftigen Gruppennamen vergeben und dann unter “Zugriffsliste” als erstes “Zugriffslisten mit einschließen” auswählen. Anschließend die gewünschten Module, Tabellen, Seitentypen etc. auswählen. Wer sich damit nicht auskennt, kann direkt alles auswählen und später genauer selektieren.
Unter “Freigaben und Arbeitsumgebungen” bei Datenbankfreigaben die root Seite auswählen
Für die Verzeichnisfreigaben zuerst ein neues Objekt erstellen. Am einfachsten ist es, direkt den fileadmin Ordner zuzuweisen, mit mehr Erfahrung sollte man den templates Ordner allerdings vor Userzugriff unbedingt schützen. Man wählt am besten die Option Basis: absolut aus und gibt den Pfad an (am besten herauszufinden wenn man sich $_SERVER[‘DOCUMENT_ROOT’] ausgeben lässt). Speichern, nochmal prüfen ob der Gruppe die Verzeichnisfreigabe zugewiesen ist und dann auch die Gruppe speichern.
Nochmal sichergehen, dass der eben erstellte Benutzer dieser neuen Gruppe auch wirklich zugewiesen ist.

3. Zugriffe
Damit dieser User den Seitenbaum auch wirklich sehen kann, bedarf es eines weiteren Schrittes. Unter Web – Zugriff – Rechte wählt man sich sein root Verzeichnis aus und bearbeitet dies. Im folgenden Formular wählt man sich die eben erstellte Gruppe im “Gruppe” Dropdown aus und wählt einfach ALLE checkboxen unter Rechte an. Das ganze lässt man Rekursiv über 3 Ebenen laufen und speichert. Anschließend sollte die Rechte Übersicht in etwa so aussehen:

Und wenn das alles geklappt hat, sollte der neu erstellte User nun auch nach dem Login den Seitenbaum und die Dateiliste sehen und bearbeiten können. Sollte dem nicht so sein, wäre der erste Schritt, zu prüfen, ob dem User auch wirklich die Gruppe zugewiesen wurde, und ob der Gruppe die entsprechenden Rechte zugewiesen wurden. Es ist NICHT nötig, einem User einzeln Rechte zu verteilen, es reicht durchaus, dass die entsprechende Gruppe die nötigen Rechte hat.

Noch ein Hinweis: diese Anleitung gibt die einzelnen Schritte natürlich nur in ihrer simpelsten Form wieder. das Typo3 Rechtesystem ist relativ umfangreich und man braucht weder direkt den Fileadmin Ordner freizugeben noch die root Seite. Man kann hier sehr gut differenzieren, aber für eine erste Zuweisung, die erstmal nichts weiter können muss als dem eingeloggten Benutzer einen Seitenbaum und eine Dateiliste anzuzeigen, eignet sich diese Anleitung durchaus.

Ein kleiner Abstecher…

01. Februar 2008

…in die wunderliche Welt von Microsoft, genauer gesagt in die Welt von M$ Word. Ich hab mir heute unter größten Suchanstrengungen zwei Makros zusammengefummelt, die mir zukünftig die Arbeit sehr erleichtern werden und da ich bei meiner Suche im Internet keinerlei Makros mit dieser Funktionalität finden konnte, dacht ich mir, ich poste sie mal hier.

1. Da die meisten Portale und Foren keine HTML Tags akzeptieren und auch kein TinyMCE haben, sondern mit vorgefertigten Tags arbeiten, brauchte ich ein Makro, das mir kursiven und fettgedruckten Text sucht und in die entsprechenden Tags schreibt. Aus “ein Text mit kursiver und fetter Schrift” sollte am Ende “ein Text mit [i]kursiver[/i] und [b]fetter[/b] Schrift” werden (die Tags mit den eckigen Klammern werden beim Animexx verwendet, kann man dann aber beliebig für seine Zwecke ändern). Das Makro sieht dann so aus:

  1. Sub kursiv_bold_ersetzen()
  2. '
  3. ' kursiv_bold_ersetzen Makro
  4. ' Makro aufgezeichnet am 01.02.2008 von Salieri
  5. '
  6. Selection.Find.ClearFormatting
  7. Selection.Find.Font.Italic = True
  8. Selection.Find.Replacement.ClearFormatting
  9. With Selection.Find
  10. .Text = ""
  11. .Replacement.Text = "[i]^&[/i]"
  12. .Forward = True
  13. .Wrap = wdFindContinue
  14. .Format = True
  15. .MatchCase = False
  16. .MatchWholeWord = False
  17. .MatchWildcards = False
  18. .MatchSoundsLike = False
  19. .MatchAllWordForms = False
  20. End With
  21. Selection.Find.Execute Replace:=wdReplaceAll
  22. Selection.Find.ClearFormatting
  23. Selection.Find.Font.Bold = True
  24. Selection.Find.Replacement.ClearFormatting
  25. With Selection.Find
  26. .Text = ""
  27. .Replacement.Text = "[b]^&[/b]"
  28. .Forward = True
  29. .Wrap = wdFindContinue
  30. .Format = True
  31. .MatchCase = False
  32. .MatchWholeWord = False
  33. .MatchWildcards = False
  34. .MatchSoundsLike = False
  35. .MatchAllWordForms = False
  36. End With
  37. Selection.Find.Execute Replace:=wdReplaceAll
  38. End Sub

Ich habe keinerlei Ahnung von Word Makros, mag also sein dass diverse Dinge, die Word mir da reinschreibt, überflüssig sind. Ich weiß nich mal, was für ne Programmiersprache das ist. Wichtig ist aber, dass es funktioniert. Selection.Find.Font.Italic = True gibt die Formatierung an und .Replacement.Text = “[b]^&[/b]” die Art, wie die Ergebnisse verarbeitet werden. Das ^& ist wohl in dem Fall der entsprechende Platzhalter. Es geht, aber ganz verstanden hab ich das System dahinter noch nicht. Denn im nächsten Beispiel sieht der Platzhalter anders aus:

2. Da diese Tags überall unterschiedlich sind, hab ich mir auch gleich ein Makro geschrieben, um das ganze Dokument von einem Tagsystem ins andere überführen zu können. In meinem Beispiel überführe ich einen für Fanfiktion.de formatierten Text in einen Animexx konformen Text. Im FFde sind kursive Texte mit [style type=”italic”]text[/style] markiert, fettgedruckte mit [style type=”bold”]text[/style]. Da das schließende Tag jeweils gleich ist, war’s mit einer einfachen Ersetzung nicht getan, also mussten Platzhalter für die Suche her und das Ergebnis sieht so aus:

  1. Sub ffde_nach_animexx()
  2. '
  3. ' ffde_nach_animexx Makro
  4. ' Makro aufgezeichnet am 01.02.2008 von Salieri
  5. '
  6. Selection.Find.ClearFormatting
  7. Selection.Find.Replacement.ClearFormatting
  8. With Selection.Find
  9. .Text = "\[style type=""bold""\](*)\[/style\]"
  10. .Replacement.Text = "[b]\1[/b]"
  11. .Forward = True
  12. .Wrap = wdFindContinue
  13. .Format = False
  14. .MatchCase = False
  15. .MatchWholeWord = False
  16. .MatchAllWordForms = False
  17. .MatchSoundsLike = False
  18. .MatchWildcards = True
  19. End With
  20. Selection.Find.Execute Replace:=wdReplaceAll
  21. With Selection.Find
  22. .Text = "\[style type=""italic""\](*)\[/style\]"
  23. .Replacement.Text = "[i]\1[/i]"
  24. .Forward = True
  25. .Wrap = wdFindContinue
  26. .Format = False
  27. .MatchCase = False
  28. .MatchWholeWord = False
  29. .MatchAllWordForms = False
  30. .MatchSoundsLike = False
  31. .MatchWildcards = True
  32. End With
  33. Selection.Find.Execute Replace:=wdReplaceAll
  34. End Sub