In der "boxes.php" wird immer PHP: $GLOBALS['coo_template_control']->get_menubox_status(...) verwendet. D.h., PHP muss immer wieder den "$GLOBALS"-Array durchsuchen, um das Objekt zu finden. Besser ist es, das Objekt einmalig einer Variablen zuzuweisen, und dann diese zu verwenden. (Ähnliches gilt für "$_SESSION['style_edit_mode'] == 'edit'" und "$this->get_('coo_product')->isProduct()".) Spart wieder eine Millisekunde.... PHP: # $coo_template_control created in application_top.php$coo_template_control=$GLOBALS['coo_template_control'];if ($coo_template_control->get_menubox_status('categories')) include(DIR_WS_BOXES.'categories.php');if ($coo_template_control->get_menubox_status('content')) include(DIR_WS_BOXES.'content.php');if ($coo_template_control->get_menubox_status('filter')) include(DIR_WS_BOXES.'filter.php');if ($coo_template_control->get_menubox_status('gm_bookmarks')) include(DIR_WS_BOXES.'gm_bookmarks.php');if ($coo_template_control->get_menubox_status('gm_counter')) include(DIR_WS_BOXES.'gm_counter.php');if ($coo_template_control->get_menubox_status('gm_scroller')) include(DIR_WS_BOXES.'gm_scroller.php');if ($coo_template_control->get_menubox_status('gm_trusted_shops_widget')) include(DIR_WS_BOXES.'gm_trusted_shops_widget.php');if ($coo_template_control->get_menubox_status('infobox')) include(DIR_WS_BOXES.'infobox.php');if ($coo_template_control->get_menubox_status('information')) include(DIR_WS_BOXES.'information.php');if ($coo_template_control->get_menubox_status('languages')) include(DIR_WS_BOXES.'languages.php');if ($coo_template_control->get_menubox_status('last_viewed')) include(DIR_WS_BOXES.'last_viewed.php');if ($coo_template_control->get_menubox_status('login')) include(DIR_WS_BOXES.'loginbox.php');if ($coo_template_control->get_menubox_status('manufacturers')) include(DIR_WS_BOXES.'manufacturers.php');if ($coo_template_control->get_menubox_status('newsletter')) include(DIR_WS_BOXES.'newsletter.php');if ($coo_template_control->get_menubox_status('paypal')) include(DIR_WS_BOXES.'paypal.php');if ($coo_template_control->get_menubox_status('search')) include(DIR_WS_BOXES.'search.php');if ($coo_template_control->get_menubox_status('trusted')) include(DIR_WS_BOXES.'trusted.php');if ($coo_template_control->get_menubox_status('ekomi')) include(DIR_WS_BOXES.'ekomi.php');if ($_SESSION['style_edit_mode'] == 'edit' || $_SESSION['customers_status']['customers_status_id'] === '0' && (int)$_SESSION['customer_id'] > 0) include(DIR_WS_BOXES.'admin.php');if ($coo_template_control->get_menubox_status('add_quickie')) if ($_SESSION['style_edit_mode'] == 'edit' || $_SESSION['customers_status']['customers_status_show_price']!='0') include(DIR_WS_BOXES.'add_a_quickie.php'); if ($coo_template_control->get_menubox_status('bestsellers')) if ($_SESSION['style_edit_mode'] == 'edit' || !$this->get_('coo_product')->isProduct()) include(DIR_WS_BOXES.'best_sellers.php'); if ($coo_template_control->get_menubox_status('currencies')) if ($_SESSION['style_edit_mode'] == 'edit' || substr_wrapper(basename($PHP_SELF), 0, 8) != 'checkout') include(DIR_WS_BOXES.'currencies.php'); if ($coo_template_control->get_menubox_status('manufacturers_info')) if ($_SESSION['style_edit_mode'] == 'edit' || $this->get_('coo_product')->isProduct()) include(DIR_WS_BOXES.'manufacturer_info.php'); if ($coo_template_control->get_menubox_status('order_history')) if ($_SESSION['style_edit_mode'] == 'edit' || isset($_SESSION['customer_id'])) include(DIR_WS_BOXES.'order_history.php'); if ($coo_template_control->get_menubox_status('reviews')) if ($_SESSION['style_edit_mode'] == 'edit' || $_SESSION['customers_status']['customers_status_read_reviews'] == 1) include(DIR_WS_BOXES.'reviews.php'); if ($coo_template_control->get_menubox_status('specials')) if ($_SESSION['style_edit_mode'] == 'edit' || !$this->get_('coo_product')->isProduct()) include(DIR_WS_BOXES.'specials.php'); if ($coo_template_control->get_menubox_status('whatsnew')) if ($_SESSION['style_edit_mode'] == 'edit' || substr_wrapper(basename($PHP_SELF), 0, 8) != 'advanced') include(DIR_WS_BOXES.'whats_new.php'); # BOF YOOCHOOSE if ((defined('YOOCHOOSE_ACTIVE') && YOOCHOOSE_ACTIVE) || $_SESSION['style_edit_mode'] == 'edit') { if ($coo_template_control->get_menubox_status('yoochoose_also_clicked')) include(DIR_WS_BOXES . 'yoochoose_also_clicked.php'); if ($coo_template_control->get_menubox_status('yoochoose_top_selling')) include(DIR_WS_BOXES . 'yoochoose_top_selling.php');}# EOF YOOCHOOSE$this->set_content_data('tpl_path','templates/'.CURRENT_TEMPLATE.'/');
Nach der Installation sind in "lang/german" noch folgende Sprach-Dateien enthalten: "gm_guestbook.php" und "masterpayment_callback.php". EDIT: Der Installer/Updater sollte auch nicht-standard-Gambio-Sprachdateien während der Installation in die DB verschieben,
Die bisher in "boxes/source/classes/" befindlichen VIEW-Klassen wurden in "system/views/ verlagert.... Was gut und schlecht ist,,,, Gut wg. Vereinheitlichung, Schlecht dann, wenn man shopspezifisch Änderungen machen will. Wenn die Klassen im Template liegen, könnte man einfach shopspezifische Varianten dort weiterhin ablegen. Könnte man jetzt immer noch machen da das "boxes/source/classes"-Verzeichnis immer noch gescanned wird. "source/classes" sollte aber in "boxes/source/views" umbenannt werden, damit ist das deutlicher, was da drin enthalten ist. Man könnte das zwar auch durch Überladung regeln... Aber "user_classes/overloads" ist nicht shop-spezifisch, so dass man da immer das Problem hat, für welchen Shop man welches Overload mitverteilen muss. In dem Template-Verzeichnis ist das einfacher.
Fehler in "ManufacturersContentView.inc.php": PHP: foreach($this->manufacturer_array as $t_manufacturer) { $t_manufacturers_name = ((strlen_wrapper($t_manufacturer['manufacturers_name']) > MAX_DISPLAY_MANUFACTURER_NAME_LEN) ? substr_wrapper($t_manufacturer['manufacturers_name'], 0, MAX_DISPLAY_MANUFACTURER_NAME_LEN) . '..' : $t_manufacturer['manufacturers_name']); $t_manufacturers_array[] = array('id' => $t_manufacturer['manufacturers_id'], 'text' => $t_manufacturers_name); } ersetzen mit: PHP: foreach($this->manufacturer_array as $t_manufacturer) { $t_manufacturers_array[] = array('id' => $t_manufacturer['id'], 'text' => $t_manufacturer['text']); }
"ShopContentContentControl.inc.php" PHP: $coo_captcha = MainFactory::create_object('Captcha', array('vvcode_input')); wird nur bei Mail-Funktionen gebraucht, daher dorthin verlagern. PHP: if($this->v_data_array['GET']['coID'] == 7) { $coo_captcha = MainFactory::create_object('Captcha', array('vvcode_input'));
"ShopContentContentControl.inc.php" Wo wird denn "$this->breadcrumb" definiert??? Ich laufe da in einen "undefinded" Fehler,,,
Ich bin im Moment dabei, mich durch die "Innereien" der Version 2.1 zu "kämpfen", meine Eindrücke dazu: durch das "Refactoring" der bisher prozeduralen Module als Klassen hat man jetzt wirklich sehr gute Möglichkeiten, updatesichere Änderungen/Erweiterungen fast überall zu realisieren. Dass dabei die alte xxCommerce-Struktur (endlich) über Bord geworfen wurde, ist sehr zu begrüßen. Allerdings erfordert das ein komplettes Umdenken wie man jetzt Erweiterungen im System einbringt. Eigentlich alles, was man bisher so kannte, gilt nicht mehr.... Ich finde es toll, aber mir steht noch einige Arbeit bevor, meine ganzen Änderungen systemkonform zu überarbeiten. Da hat Gambio einen prima Job gemacht, der sicher viel Gedanken, Zeit und Arbeit gekostet hat... Aus meiner praktischen Erfahrung würde ich einige Dinge noch weiter treiben, ich werde das dann ansprechen, und (so weit möglich) eine Lösung vorschlagen. Eine Sache hatte ich ja schon vorgeschlagen: die weitere Vereinheitlichung der Artikellistings durch Verwendung eines für alle gültigen Artikellisting-Controllers. Da ich so was bei mir benötige, bin ich dabei, das umzusetzen.
Wenn ich das richtig sehe, kann die "includes/application_bottom.php" auch gelöscht werden.... In "HeaderContentView.inc.php" wird shopgate noch ohne Prüfung eingebunden.
In "NewProductsMainContentView.inc.php" PHP: $t_date_new_products = date("Y.m.d", mktime(1, 1, 1, date(m), date(d) - MAX_DISPLAY_NEW_PRODUCTS_DAYS, date(Y)) ); ändern zu: PHP: $t_date_new_products = date("Y-m-d",mktime(1, 1, 1, date(m), date(d) - MAX_DISPLAY_NEW_PRODUCTS_DAYS, date(Y))); Das Datum ist in der DB im Format "Y-m-d" ("2014-03-02") und nicht "Y.m.d" ("2014.03.02") gespeichert.
Ich habe das jetzt mal realisiert, wie ich mir das vorstelle: Es gibt jetzt den Controller "ArticleListingContentControl", der die eigentliche Arbeit der Datenaufbereitung aller Artikellisten erledigt: PHP: <?php/* --------------------------------------------------------------ArticleListingContentControl.inc.php 2014-04-05 AvengerGambio GmbHhttp://www.gambio.deCopyright (c) 2014 Gambio GmbHCopyright (c) 2014 Avenger, entwicklung@powertemplate.deController for article listings Released under the GNU General Public License (Version 2)[http://www.gnu.org/licenses/gpl-2.0.html]--------------------------------------------------------------based on:(c) 2000-2001 The Exchange Project (earlier name of osCommerce)(c) 2002-2003 osCommerce(bestsellers.php,v 1.47 2003/05/27); www.oscommerce.com(c) 2003 nextcommerce (bestsellers.php,v 1.12 2003/08/17); www.nextcommerce.org(c) 2003 XT-Commerce - community made shopping http://www.xt-commerce.com ($Id: bestsellers.php 1292 2005-10-07 16:10:55Z mz $)Released under the GNU General Public License---------------------------------------------------------------------------------------*/// include needed functionrequire_once(DIR_FS_INC . 'xtc_date_long.inc.php');require_once(DIR_FS_INC . 'xtc_date_short.inc.php');require_once(DIR_FS_INC . 'xtc_get_vpe_name.inc.php');class ArticleListingContentControl extends ContentView{ protected $customers_status_id; protected $customers_fsk18_display = 0; protected $languages_id; protected $products_count = 6; protected $fsk_lock; protected $group_check; public function __construct() { parent::__construct(); $this->customers_status_id=$_SESSION['customers_status']['customers_status_id']; if ($this->customers_fsk18_display == 0) { $this->fsk_lock = ' AND p.products_fsk18 != 1 '; } else { $this->fsk_lock = ''; } if (GROUP_CHECK == 'true') { $this->group_check = ' AND p.group_permission_' . $this->customers_status_id . ' = 1 '; } else { $this->group_check = ''; } $this->set_flat_assigns(true); } protected function set_validation_rules() { $this->validation_rules_array['customers_status_id'] = array('type' => 'int'); $this->validation_rules_array['customers_fsk18_display'] = array('type' => 'int'); $this->validation_rules_array['languages_id'] = array('type' => 'int'); $this->validation_rules_array['products_count'] = array('type' => 'int'); } protected function set_deprecated_array() { $this->deprecated_array[1][] = 'TEXT_ADD_TO_CART'; $this->deprecated_array[1][] = 'gm_thumbnail_width'; $this->deprecated_array[1][] = 'gm_thumbnail_height'; $this->deprecated_array[1][] = 'thumbnail_heigth'; } function prepare_data() { $t_uninitialized_array = $this->get_uninitialized_variables(array( 'customers_status_id', 'languages_id') ); if (empty($t_uninitialized_array)) { if ($this->products_count > 0) { $t_query = $this->build_sql_query(); $t_result = xtc_db_query($t_query); if (xtc_db_num_rows($t_result) > 0) { while($t_articles = xtc_db_fetch_array($t_result)) { $coo_product = MainFactory::create_object('product',array((int)$t_articles['products_id'])); if ($coo_product->isProduct) { $this->content_array['module_content'][] = $coo_product->buildDataArray($coo_product->data); } } $this->add_thumbnail(); $this->content_array['TEXT_ADD_TO_CART'] = TEXT_ADD_TO_CART; $this->content_array['TRUNCATE_PRODUCTS_NAME'] = gm_get_conf('TRUNCATE_PRODUCTS_NAME'); } } else { $this->build_html = false; } } else { trigger_error("Variable(s) " . implode(', ', $t_uninitialized_array) . " do(es) not exist in class " . get_class($this) . " or is/are null", E_USER_ERROR); } } protected function add_thumbnail() { $gm_image_len = PRODUCT_IMAGE_THUMBNAIL_HEIGHT; if ($gm_image_len < PRODUCT_IMAGE_THUMBNAIL_WIDTH) { $gm_image_len = PRODUCT_IMAGE_THUMBNAIL_WIDTH; } $this->content_array['gm_thumbnail_heigth'] = $gm_image_len + 8; $this->content_array['gm_thumbnail_width'] = $gm_image_len + 8; $this->content_array['thumbnail_heigth'] = PRODUCT_IMAGE_THUMBNAIL_HEIGHT + 40; }} Die einzelnen Artikellisting-Views beerben diesen Controller, und setzen nur noch die für sie notwendigen Daten (Selection-SQL, Anzahl der gewünschten Artikel in der Liste (kann durch Überladung bei Bedarf geändert werden!), Template-Datei). Der "NewProductsMainContentView.inc.php" sieht dann z.B. so aus: PHP: <?php/* --------------------------------------------------------------NewProductsMainContentView.inc.php 2014-02-28 gmGambio GmbHhttp://www.gambio.deCopyright (c) 2014 Gambio GmbHCopyright (c) 2014 Avenger, entwicklung@powertemplate.deUse common ArticleListingContentControl class Released under the GNU General Public License (Version 2)[http://www.gnu.org/licenses/gpl-2.0.html]--------------------------------------------------------------based on:(c) 2000-2001 The Exchange Project (earlier name of osCommerce)(c) 2002-2003 osCommerce(products_new.php,v 1.25 2003/05/27); www.oscommerce.com(c) 2003 nextcommerce (products_new.php,v 1.16 2003/08/18); www.nextcommerce.org(c) 2003 XT-Commerce - community made shopping http://www.xt-commerce.com ($Id: products_new.php 1292 2005-10-07 16:10:55Z mz $)Released under the GNU General Public License-----------------------------------------------------------------------------------------Third Party contributions:Enable_Disable_Categories 1.3 Autor: Mikel Williams | mikel@ladykatcostumes.comReleased under the GNU General Public License---------------------------------------------------------------------------------------*/class NewProductsMainContentView extends ArticleListingContentControl{ public function __construct() { parent::__construct(); $this->set_content_template('module/products_new_main.html'); $this->products_count=(int)MAX_RANDOM_SELECT_NEW; } protected function build_sql_query() { if(MAX_DISPLAY_NEW_PRODUCTS_DAYS != '0') { $t_date_new_products = date("Y-m-d",mktime(1, 1, 1, date(m), date(d) - MAX_DISPLAY_NEW_PRODUCTS_DAYS, date(Y))); $t_days = ' AND p.products_date_added > "' . $t_date_new_products . '" '; } $t_products_new_query = " SELECT p.products_id FROM " . TABLE_PRODUCTS . " p, " . TABLE_PRODUCTS_DESCRIPTION . " pd WHERE p.products_status = '1' AND p.products_id = pd.products_id AND pd.language_id = '" . $this->languages_id . "' " . $this->t_group_check . " " . $this->fsk_lock . " " . $t_days . " ORDER BY RAND() LIMIT " . $this->products_count; return $t_products_new_query; }} Damit habe ich erreicht, dass alle Artikellisten-Templates jetzt konsistent alle relevanten Artikel-Daten zur Verfügung haben, auch evtl. zusätzliche eigene Daten-Felder, die durch Überladung der "buildDataArray"-Methode der "products"-Klasse eingeführt werden können... Und ich habe den Verarbeitungscode nur noch einmalig im Controller statt in jedem View. Und ich kann mir relativ einfach eine neue Artikelliste "basteln".... Eine Bestsellers-Liste kann ich mir z.B. so schaffen: PHP: <?php/* --------------------------------------------------------------BestsellersMainContentView.inc.php 2014-04-05 AvengerGambio GmbHhttp://www.gambio.deCopyright (c) 2014 Gambio GmbHCopyright (c) 2014 Avenger, entwicklung@powertemplate.deAllow bestsellers listing on startpageUse common ArticleListingContentControl class Released under the GNU General Public License (Version 2)[http://www.gnu.org/licenses/gpl-2.0.html]based on:(c) 2000-2001 The Exchange Project (earlier name of osCommerce)(c) 2002-2003 osCommerce(bestsellers.php,v 1.47 2003/05/27); www.oscommerce.com(c) 2003 nextcommerce (bestsellers.php,v 1.12 2003/08/17); www.nextcommerce.org(c) 2003 XT-Commerce - community made shopping http://www.xt-commerce.com ($Id: bestsellers.php 1292 2005-10-07 16:10:55Z mz $)---------------------------------------------------------------------------------------*/class BestsellersMainContentView extends ArticleListingContentControl{ public function __construct() { parent::__construct(); $this->set_content_template('module/bestseller_products.html'); $this->products_count==max(4,(int)MAX_RANDOM_SELECT_NEW); } protected function build_sql_query() { $t_bestsellers_query = "SELECT DISTINCT p.products_id FROM ". TABLE_PRODUCTS." p, ". TABLE_PRODUCTS_DESCRIPTION." pd, ". TABLE_PRODUCTS_TO_CATEGORIES." p2c, ". TABLE_CATEGORIES." cWHERE c.categories_status='1' AND p.products_status = '1' ".$this->fsk_lock." ".$this->group_check." AND p.products_ordered > 0 AND p.products_id = pd.products_id AND p.products_id = p2c.products_id AND c.categories_id = p2c.categories_id AND pd.language_id = '".(int) $_SESSION['languages_id']."'ORDER BY rand(), p.products_ordered descLIMIT ".$this->products_count; return $t_bestsellers_query; }} Im Anhang habe ich diese Dateien mal beigefügt. Die werden dort im "user_classes"-Verzeichnis abgelegt, können aber genau so in das "system"-Verzeichnis wandern.
SQL interpretiert auch die "falsche" Notation korrekt. Habs grad mal ausprobiert. Trotzdem sollte das angepasst werden, ja. Dein ArticleListingContentControl ist eine gute Idee. Da bietet sich eigentlich eine abstract class an.
Das funktioniert in der Regel nicht ohne Anpassungen der Sprachdateien. In der 2.0er Struktur gibt es einige Sprachdateien, die PHP-Logik und Variable Sprachkonstantenwerte enthalten, was zu Problemen beim Parsen der Dateien und/oder zu Ausführungsfehlern nach dem Import führt. Es war schon ein riesen Akt die Standardsprachen importfähig zu machen. Man beachte, dass beim Update nicht die alten Sprachdateien importiert werden, sondern dass die Sprachdateien, die importiert werden, im Updater gesondert vorliegen. Wir hatten keine Stelle im Shop ausfindig machen können, die die Klasse noch (sinnvoll) nutzt. Daher haben wir sie als überflüssig erachtet und entfernt.
Ich habe es gemessen. Bei der geringen Anzahl an Aufrufen gibt es keinen messbaren Unterschied. Beide Varianten sind mal schneller. Bei 10000-facher Ausführung liegt der Vorteil bei meiner langsamen lokalen Serverumgebung im Schnitt bei 0,000003 Sekunden pro Aufruf. Ich bevorzuge dann lieber die GLOBALS-Variante, da dann sofort ersichtlich ist, dass man es mit einer (bösen, eigentlich zu vermeidenden) globalen Variable zu tun hat.
Wurde für den "MasterAdmin" noch nie angezeigt! Leg mal einen zweiten User mit Adminrechte an, dann kommt auch das Menü wieder!
mach dir nix draus Steffen, hab das letztens auch gesucht und dachte bin blind weils bei mir immer fehlte und bei anderen da war.
Ok, das scheint Sinn zu machen! Nur ist das jetzt doof da ich als MasterAdmin nicht das Recht habe das ImagesProcessing durchlaufen zu lassen. Es erscheint in dem DIV wo er eigentlich die Bilder zählt die Seite nochmal...... Grübel Grübel.... Werd wohl mal in die DB schauen müssen -> DB-Tabelle admin_access