You are here

eshop σε drupal

21 posts / 0 new
Τελευταία δημοσίευση
eshop σε drupal

θα ήθελα να ρωτήσω αν υπάρχει κάποιο module για την δημιουργία eshop και αν γνωρίζεται κάποιο που να επιτρέπει σύγκριση προϊόντων.

Υπάρχει το ubercart module για την έκδοση 6 και το ολοκαίνουριο (τόσο καινούριο που είναι σε beta) Drupal Commerce για την έκδοση 7.

και τα 2 αυτά modules υποστηρίζονται από πλειάδα άλλων modules οπότε ψάξε σε αυτά για σύγκριση προϊόντων

Δυστυχώς το Ubercart έχει μεγάλα προβλήματα σε Multilanguage.

@jddeli Καθώς αυτή τη στιγμή φτιάχνω ένα multilanguage ubercart site , μπορείς να γίνεις λίγο πιο συγκεκριμένος όσον αφορά τα προβλήματα;

και γώ στήσει μεγάλο Ubercart eshop χωρίς ιδιαίτερα προβλήματα στο multilingual.
Αρκεί να το έχεις στήσει σωστά το θέμα multilingual στο drupal οπως βέβαια σε κάθε Multilingual drupal site.
Eπείσης για specific Ubercart προβλήματα στο translation δες και αυτό
http://www.firewing1.com/node/27

Έχω κοιτάξει το http://www.firewing1.com/node/27 αλλά πουθενά δεν βρήκα λύση στο πώς μεταφράζεις attributes ή πώς λύνεις το πρόβλημα με stock/ στατιστικά δεδομένου ότι θεωρεί το προϊόν και τη μετάφραση του ως 2 διαφορετικά πράγματα (αφού είναι 2 διαφορετικά nodes)

καταρχήν η απάντηση πήγαινε στον jddeli αλλα οκ
ρίξε μια ματιά εδώ
http://www.epavlis.gr/forest/%CF%83%CE%B5%CE%BD%CF%84%CE%BF%CE%BD%CE%B9-... για παράδειγμα.Αλλαξε γλώσσα και θα δείς οτι μιά χαρά μεταφράζονται τα attributes. Μέσα απο το translate interface εχω ορίσει τις αντιστοιχίες.
Τώρα πρόβλημα με το stock και τα στατιστικά για ποιό λόγο να έχεις ???
Ναι έχεις απόλυτο δίκιο οτι η μετάφραση είναι ένα διαφορετικό Node αλλά εσύ δεν χειρίζεσαι τα προϊόντα ως Nodes αλλά ώς sku.
Όταν κάνεις mass stock update απο cvs ενημερώνεις το sku οπότε ενημερώνονται και τα 2 Nodes και το ίδιο ισχύει και όταν πέρνεις reports.
Δεν σου λέει πόσες φορές πουλήθηκε το Node αλλα το sku.

Και μιας που πιάσαμε την κουβέντα για ubercart και multilingual θυμήθηκα που είχα αντιμετωπίσει προβλήματα με το multilingual στο ubercart και αυτό ήταν το catalog module του Ubercart το οποίο όπως αναφέρει και στο λινκ που έδωσα παραπάνω σαν λύση δίνει το per item term... το οποίο όμως προφανώς δεν είναι καθόλου βολικό.
Ετσι απο ένα thread στο φορουμ του ubercart βρέθηκε λύση που είναι το reright fuctions του catalog στο template.php μιας και με λίγο search δεν βρήκα το thread αν χρειαστεί κανεις μπορώ απλά να του στείλω τo template.php για να cloparei τα functions... (δεν βρίσκω κάποιο λόγο να ποστάρω εδώ τώρα μια κουμουτζα που πιθανών να μην ενδιαφέρει και κανέναν.)

Δυστυχώς τα attributes δεν έχουν multilanguage ώστε στην δευτερή γλώσσα να είναι σωστά.
Μέγεθος Μικρό Μεγάλο είναι και στα ελληνικά και στα αγγλικά.

Αυτό που γίνετε σε αυτή τη περίπτωση jddeli είναι να κάνεις ίδια attributes σε διαφορετικές γλώσσες (π.χ. μέγεθος: μικρό, μεγάλο / size: small, big) και σε κάθε μετάφραση των nodes να διαλέξεις το αντίστοιχο.

Ανάλογη περίπτωση είναι και οι μονάδες μέτρησης σε Ευρώπη και Αμερική όπως εκατοστά/ίντσες, τα νούμερα των παπουτσιών κτλ.

@jddeli Μέγεθος Μικρό Μεγάλο είναι και στα ελληνικά και στα αγγλικά.

@ gpitoulias

οπως μπορείς να δείς στα screenshots δεν έχω φτίαξει 2 attributes σε διαφορετικες γλώσσες ούτε έχω βάλει τις επιλογές σε 2 γλώσσες...

Επειδή με το multilanguage se drupal εχω κάψει αρκετα εγκεφαλικά κύτταρα σε περιπτώσεις που κάτι δεν είναι traslatable μέσω απο το translate interface η λύση στη γενική περίπτωση είναι η εξής.
Πάω και βρίσκω το function που κάνει print αυτό που θέλω να κάνω translate. Μπορεί εκεί όπως είναι στεγνά να πάω και να το βάλω σε ένα t() και να δουλέψει Αλλα προσωπικά για λόγους σωστής λογικής και για να μην έχω προβλήματα με το update των modules πάω και κάνω override το function στο template.php μου προσθέτωντας το t() και ότι άλλο θέλω ανα περίπτωση.

@boboss
Ναι το έχω κάνει και έτσι αλλά την πάτησα και εγώ σε ένα update (όπως λες και εσύ) όποτε στη λύση του να πειράζεις κώδικα καταφεύγω μόνο όταν δεν υπάρχει εναλλακτικός τρόπος.

Δηλαδή πρέπει να φτιάξω attribute ελληνικό κα ενα αγγλικό.
Μετά στο προιόν ανάλογα με την γλώσσα να προσθέσω το αντίστιχο attribute ελληνικό αγγλικό?

Οπως θέλεις εσύ ή αυτο ή τη λύση που προτεινε ο boboss.

Μετά από αρκετό ψάξιμο γύρω από drupal και multilingual eshop κατέληξα ότι αυτή τη στιγμή υπάρχουν 2 λύσεις:

Είτε d6 με ubercart όπου θέλει αρκετό template overriding για να περνάν μέσα από την t() τα attributes.

Είτε d7 με drupal commerce, όπου το ψάχνω αυτή τη στιγμή να δω κατά πόσο είναι εφικτό σήμερα με τα περισσότερα modules σε dev. Όταν θα ξέρω περισσότερα για το αν είναι εφικτό θα ενημερώσω.

@boboss μπορείς να μας στείλεις τον κώδικα που έχεις στο template.php για να κάνεις multilingual τα attributes; Ξεκίνησα και γω να κάνω override theme functions προσθέτοντας t(), αλλά αν το έχεις κάνει ήδη θα μου γλύτωνε πολύ κόπο.

Και εμένα θα με ενδιέφερε να μάθω πως. Πραγματικά αν οι άνθρωποι που έχουν φτιάξη λύσης όπως ο @boboss φτιάχνουν site βοηθάνε όλοι την κοινότητα και γινόμαστε περισσότερη.

So... lets σεντόνι begins...
@ jddeli Ρε αδερφέ βάλε εναν ορθογραφικό έλεγχο ... Όλοι δεν τα πάμε καλά με την ορθογραφία αλλα εσύ βγάζεις μάτια .. περισσότερΗ δεν έγινα 27 χρόνια τώρα μη με κάνεις στα γεράματα
Λίγη θεωρία...
Αν σου δωσω να φας ψαρια, θα χορτασεις για σημερα. Αν σου μαθω να ψαρευεις ομως, θα τρως οποτε πεινας. (Κινέζικη παροιμία).
Τί θέλει να πεί ο ποιητής...
Το να ζητάς έτοιμες λύσεις δεν είναι καλό σε γενικές γραμμές. Δεν είναι καλό ούτε για μένα που σου δίνω την λύση αλλα ούτε για σένα που την πέρνεις...
Εγώ αισθάνομαι χαζός απο την μια γιατί σου δίνω εσένα έτοιμη τροφή για την οποία εγώ σπατάλησα χρόνο και χρήμα για να την παράγω και εσύ θα την εκμεταλευτείς έτοιμη ενώ απο την πλευρά σου θα έπρεπε να αισθάνεσαι χαζός που δεν μπορείς να λύσεις ένα πρόβλημα χωρίς την εξάρτηση απο κάποιον άλλο...
Αυτή είναι η μία οπτική.
Απο την άλλη μπαίνεις στην λογική της κοινώτητας οπου το κάθε μέλλος θα πρέπει να βοηθάει τους αλλους ώστε όλοι μαζί να προχωράνε μπρωστά.
Απο πλευράς μου διαλέγω το β.
To the point now...
@kostask
[quote]Είτε d7 με drupal commerce, όπου το ψάχνω αυτή τη στιγμή να δω κατά πόσο είναι εφικτό σήμερα με τα περισσότερα modules σε dev. Όταν θα ξέρω περισσότερα για το αν είναι εφικτό θα ενημερώσω.[/quote]
Προς το παρόν ξεχνάμε το commerce... Ενώ η λογική πίσω απο το commerce ΤΑ ΣΠΑΕΙ είναι οτι πιο σωστό έχω δεί μέχρι στιγμής σε προσέγγιση open source eshop είναι πολύ φρέσκο ακόμα για να περάσουμε σε production ειδικά εμείς οι έλληνες που έχουμε και το θέμα του multilingual...Αλλα και γενικότερα απο το λίγο που έχω παίξει με το commerce έχω δεί modules να σκάνε, βασικά modules να λείπουν κλπ κάτι που με αποθάρείνει να το χρησημοποιήσω ...
[quote]μπορείς να μας στείλεις τον κώδικα που έχεις στο template.php για να κάνεις multilingual τα attributes; Ξεκίνησα και γω να κάνω override theme functions προσθέτοντας t(), αλλά αν το έχεις κάνει ήδη θα μου γλύτωνε πολύ κόπο.[/quote].
Στο epavlis που σας έχω δωσει σαν παράδειγμα δεν έχω φτιάξει τα attribute multilingual στο template.php αλλά πάνω στο ίδιο το module
Το παραθέτω παρακάτω
Βέβαια απο την στιγμή που έχεις τον κώδικα δεν είναι τίποτα να τον περάσεις στο template με οverides ... Αλλά και έτσι κάνει δουλεια στο uc_attribute.module.

<?php
// $Id: uc_attribute.module,v 1.12.2.38 2010/01/27 22:23:31 islandusurper Exp $

/**
 * @file
 * Ubercart Attribute module.
 *
 * Allows customers to buy slightly different products from the same listing.
 *
 * Many manufacturers provide options to their products. This module provides a way
 * for store administrators to consolidate these options into one product instead of
 * listing each combination separately. This is accomplished through the use of Drupal's
 * hook system.
 */

require_once('uc_attribute.ca.inc');

/******************************************************************************
 * Drupal Hooks                                                               *
 ******************************************************************************/

/**
 * Implementation of hook_help().
 */
function uc_attribute_help($path, $arg) {
  switch ($path) {
    // Help messages for the attributes overview on products and classes.
    case 'node/%/edit/attributes':
      return t('Add attributes to this product using the add attributes form. You may then adjust the settings for these attributes on this page and go on to configure their options in the Options tab.', array('!url' => url('node/'. $arg[1] .'/edit/attributes/add')));
    case 'admin/store/products/classes/%/attributes':
      return t('Add attributes to the product class using the add attributes form. You may then adjust the settings for these attributes on this page and go on to configure their options in the Options tab.', array('!url' => url('admin/store/products/classes/'. $arg[4] .'/attributes/add')));

    // Help message for adding an attribute to a product or class.
    case 'node/%/edit/attributes/add':
    case 'admin/store/products/classes/%/attributes/add':
      return t('Select the attributes you want to add and submit the form.');

    // Help message for adjusting the options on a product or class.
    case 'node/%/edit/options':
    case 'admin/store/products/classes/%/options':
      return t('Use the checkboxes to enable options for attributes and the radio buttons to specify defaults for the enabled options. Use the other fields to override the default settings for each option. Attributes with no enabled options will be displayed as text fields.');

    // Help message for the product Adjustments tab.
    case 'node/%/edit/adjustments':
      return t('Enter an alternate SKU to be used when the specified set of options are chosen and the product is added to the cart. Warning: Adding or removing attributes from this product will reset all the SKUs on this page to the default product SKU.');
  }
}

/**
 * Implementation of hook_menu().
 */
function uc_attribute_menu() {
  $items['admin/store/attributes'] = array(
    'title' => 'Attributes',
    'description' => 'Create and edit attributes and options.',
    'page callback' => 'uc_attribute_admin',
    'access arguments' => array('administer attributes'),
    'type' => MENU_NORMAL_ITEM,
    'weight' => -1,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/overview'] = array(
    'title' => 'Overview',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/store/attributes/add'] = array(
    'title' => 'Add an attribute',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_form'),
    'access arguments' => array('administer attributes'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 5,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/settings/attributes'] = array(
    'title' => 'Attribute settings',
    'description' => 'Configure the attribute settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_admin_settings'),
    'access arguments' => array('administer attributes'),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/edit'] = array(
    'title' => 'Edit attribute',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_form', 3),
    'access arguments' => array('administer attributes'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/delete'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_delete_confirm', 3),
    'access arguments' => array('administer attributes'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/options'] = array(
    'title' => 'Options',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_options_form', 3),
    'access arguments' => array('administer attributes'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/options/overview'] = array(
    'title' => 'Overview',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/options/add'] = array(
    'title' => 'Add an option',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_option_form', 3, NULL),
    'access arguments' => array('administer attributes'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 5,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/options/%uc_attribute_option/edit'] = array(
    'title' => 'Edit option',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_option_form', 3, 5),
    'access arguments' => array('administer attributes'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/attributes/%uc_attribute/options/%uc_attribute_option/delete'] = array(
    'title' => 'Delete option',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_attribute_option_delete_confirm', 3, 5),
    'access arguments' => array('administer attributes'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_attribute.admin.inc',
  );

  // Menu items for default product class attributes and options.
  $items['admin/store/products/classes/%uc_product_class/attributes'] = array(
    'title' => 'Attributes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_object_attributes_form', 4, 'class'),
    'access callback' => 'uc_attribute_product_class_access',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['admin/store/products/classes/%uc_product_class/options'] = array(
    'title' => 'Options',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_object_options_form', 4, 'class'),
    'access callback' => 'uc_attribute_product_class_access',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'file' => 'uc_attribute.admin.inc',
  );

  // Insert subitems into the edit node page for product types.
  $items['node/%node/edit/attributes'] = array(
    'title' => 'Attributes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_object_attributes_form', 1, 'product', 'overview'),
    'access callback' => 'uc_attribute_product_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['node/%node/edit/attributes/add'] = array(
    'title' => 'Attributes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_object_attributes_form', 1, 'product', 'add'),
    'access callback' => 'uc_attribute_product_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['node/%node/edit/options'] = array(
    'title' => 'Options',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_object_options_form', 1, 'product'),
    'access callback' => 'uc_attribute_product_option_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'file' => 'uc_attribute.admin.inc',
  );
  $items['node/%node/edit/adjustments'] = array(
    'title' => 'Adjustments',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_product_adjustments_form', 1),
    'access callback' => 'uc_attribute_product_option_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
    'file' => 'uc_attribute.admin.inc',
  );

  return $items;
}

/**
 * Access callback for editing a product class's attributes and options.
 */
function uc_attribute_product_class_access() {
  return user_access('administer product classes') && user_access('administer attributes');
}

/**
 * Access callback for editing a product's attributes.
 */
function uc_attribute_product_access($node) {
  if ($node->type == 'product_kit') {
    return FALSE;
  }

  return uc_product_is_product($node) && node_access('update', $node) && (user_access('administer attributes') || user_access('administer product attributes'));
}

/**
 * Access callback for editing a product's options.
 */
function uc_attribute_product_option_access($node) {
  if ($node->type == 'product_kit') {
    return FALSE;
  }

  return uc_product_is_product($node) && node_access('update', $node) && (user_access('administer attributes') || user_access('administer product attributes') || user_access('administer product options'));
}

/**
 * Implementation of hook_perm().
 */
function uc_attribute_perm() {
  return array('administer attributes', 'administer product attributes', 'administer product options');
}

/**
 * Implementation of hook_init().
 */
function uc_attribute_init() {
  drupal_add_css(drupal_get_path('module', 'uc_attribute') .'/uc_attribute.css');
}

/**
 * Implementation of hook_theme().
 */
function uc_attribute_theme() {
  return array(
    'uc_attribute_add_to_cart' => array(
      'arguments' => array('form' => NULL),
    ),
    'uc_object_attributes_form' => array(
      'arguments' => array('form' => NULL),
      'file' => 'uc_attribute.admin.inc',
    ),
    'uc_object_options_form' => array(
      'arguments' => array('form' => NULL),
      'file' => 'uc_attribute.admin.inc',
    ),
    'uc_attribute_options_form' => array(
      'arguments' => array('form' => NULL),
      'file' => 'uc_attribute.admin.inc',
    ),
    'uc_product_attributes' => array(
      'arguments' => array('product' => NULL),
      'file' => 'uc_attribute.admin.inc',
    ),
  );
}

/**
 * Implementation of hook_form_alter().
 */
function uc_attribute_form_alter(&$form, $form_state, $form_id) {
  if (strpos($form_id, 'add_product_form')) {
    $node =& $form['node']['#value'];
    // If the node has a product list, add attributes to them
    if (isset($form['sub_products']) && count(element_children($form['sub_products']))) {
      foreach (element_children($form['sub_products']) as $key) {
        $form['sub_products'][$key]['attributes'] = _uc_attribute_alter_form(node_load($key));
        if (is_array($form['sub_products'][$key]['attributes'])) {
          $form['sub_products'][$key]['attributes']['#tree'] = TRUE;
          $form['sub_products'][$key]['#type'] = 'fieldset';
        }
      }
    }
    // If not, add attributes to the node.
    else {
      $form['attributes'] = _uc_attribute_alter_form($node);

      if (is_array($form['attributes'])) {
        $form['attributes']['#tree'] = TRUE;
        $form['attributes']['#weight'] = -1;
      }
    }
  }
}

/**
 * Implementation of hook_uc_form_alter().
 *
 * Attach option selectors to the form with the "Add to Cart" button.
 *
 * This function also handles selecting attributes for products added to orders
 * manually.
 */
function uc_attribute_uc_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'add_to_cart_form') || strpos($form_id, 'add_product_form')) {
    $node =& $form['node']['#value'];
    // If the node has a product list, add attributes to them
    if (isset($form['products']) && count(element_children($form['products']))) {
      foreach (element_children($form['products']) as $key) {
        $form['products'][$key]['attributes'] = _uc_attribute_alter_form(node_load($key));
        if (is_array($form['products'][$key]['attributes'])) {
          $form['products'][$key]['attributes']['#tree'] = TRUE;
          $form['products'][$key]['#type'] = 'fieldset';
        }
      }
    }
    // If not, add attributes to the node.
    else {
      $form['attributes'] = _uc_attribute_alter_form($node);

      if (is_array($form['attributes'])) {
        $form['attributes']['#tree'] = TRUE;
        $form['attributes']['#weight'] = -1;
      }
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function uc_attribute_nodeapi(&$node, $op, $arg3 = NULL, $arg4 = NULL) {
  if (uc_product_is_product($node->type)) {
    switch ($op) {
      case 'load':
        $attributes = uc_product_get_attributes($node->nid);
        if (is_array($attributes) && !empty($attributes)) {
          $node->attributes = $attributes;
          return array('attributes' => $attributes);
        }
        break;
      case 'insert':
        switch ($GLOBALS['db_type']) {
          case 'mysqli':
          case 'mysql':
            db_query("INSERT IGNORE INTO {uc_product_attributes} (nid, aid, label, ordering, required, display, default_option) SELECT %d, aid, label, ordering, required, display, default_option FROM {uc_class_attributes} WHERE pcid = '%s'", $node->nid, $node->type);
            db_query("INSERT IGNORE INTO {uc_product_options} (nid, oid, cost, price, weight, ordering) SELECT %d, oid, cost, price, weight, ordering FROM {uc_class_attribute_options} WHERE pcid = '%s'", $node->nid, $node->type);
            break;
          case 'pgsql':
            db_query("INSERT INTO {uc_product_attributes} (nid, aid, label, ordering, required, display, default_option) SELECT %d, aid, label, ordering, required, display, default_option FROM {uc_class_attributes} WHERE pcid = '%s'", $node->nid, $node->type);
            db_query("INSERT INTO {uc_product_options} (nid, oid, cost, price, weight, ordering) SELECT %d, oid, cost, price, weight, ordering FROM {uc_class_attribute_options} WHERE pcid = '%s'", $node->nid, $node->type);
            break;
        }

        break;
      case 'delete':
        db_query("DELETE FROM {uc_product_options} WHERE nid = %d", $node->nid);
        db_query("DELETE FROM {uc_product_adjustments} WHERE nid = %d", $node->nid);
        db_query("DELETE FROM {uc_product_attributes} WHERE nid = %d", $node->nid);
        break;
      case 'update index':
        $output = '';
        $attributes = uc_product_get_attributes($node->nid);
        foreach ($attributes as $attribute) {
          $output .= '

'. _uc_attribute_get_name($attribute) .'

'; foreach ($attribute->options as $option) { $output .= t($option->name) .' '; } $output .= "\n"; } $result = db_query("SELECT model FROM {uc_product_adjustments} WHERE nid = %d", $node->nid); while ($adjustment = db_fetch_object($result)) { $output .= '

'. $adjustment->model ."

\n"; } return $output; } } } /****************************************************************************** * Ubercart Hooks * ******************************************************************************/ /** * Implementation of hook_uc_product_models(). */ function uc_attribute_uc_product_models($node) { $models = array(); // Get all the SKUs for all the attributes on this node. $adjustments = db_query("SELECT model FROM {uc_product_adjustments} WHERE nid = %d", $node->nid); while ($adjustment = db_fetch_object($adjustments)) { if (!in_array($adjustment->model, $models)) { $models[] = $adjustment->model; } } return $models; } /** * Store the customer's choices in the cart. */ function uc_attribute_add_to_cart_data($form_values) { if (isset($form_values['attributes'])) { return array('attributes' => $form_values['attributes']); } else { return array('attributes' => array()); } } /** * Implemenation of hook_order_product_alter(). */ function uc_attribute_order_product_alter(&$product, $order) { // Convert the attribute and option ids to their current names. This // preserves the important data in case the attributes or options are // changed later. if (is_array($product->data['attributes']) && is_numeric(key($product->data['attributes']))) { $attributes = array(); $options = _uc_cart_product_get_options($product); foreach ($options as $aid => $option) { $attributes[$option['attribute']][] = $option['name']; } $product->data['attributes'] = $attributes; } } /** * Implementation of hook_product_class(). */ function uc_attribute_product_class($type, $op) { switch ($op) { case 'delete': db_query("DELETE FROM {uc_class_attributes} WHERE pcid = '%s'", $type); db_query("DELETE FROM {uc_class_attribute_options} WHERE pcid = '%s'", $type); break; } } /** * Implementation of hook_cart_item(). */ function uc_attribute_cart_item($op, &$item) { switch ($op) { case 'load': $options = _uc_cart_product_get_options($item); $op_costs = 0; $op_prices = 0; $op_weight = 0; foreach ($options as $option) { $op_costs += $option['cost']; $op_prices += $option['price']; $op_weight += $option['weight']; } $item->cost += $op_costs; $item->price += $op_prices; $item->weight += $op_weight; $combination = array(); foreach ((array)$item->data['attributes'] as $aid => $value) { if (is_numeric($value)) { $attribute = uc_attribute_load($aid, $item->nid, 'product'); if ($attribute && ($attribute->display == 1 || $attribute->display == 2)) { $combination[$aid] = $value; } } } ksort($combination); $result = db_query("SELECT model FROM {uc_product_adjustments} WHERE nid = %d AND combination LIKE '%s'", $item->nid, serialize($combination)); $model = db_result($result); if (!empty($model)) { $item->model = $model; } break; } } /** * Implementation of hook_product_description(). */ function uc_attribute_product_description($product) { $description = array( 'attributes' => array( '#product' => array( '#type' => 'value', '#value' => $product, ), '#theme' => 'uc_product_attributes', '#weight' => 1, ), ); $desc =& $description['attributes']; // Cart version of the product has numeric attribute => option values so we // need to retrieve the right ones $weight = 0; if (empty($product->order_id)) { foreach (_uc_cart_product_get_options($product) as $option) { if (!isset($desc[$option['aid']])) { $desc[$option['aid']]['#attribute_name'] = $option['attribute']; $desc[$option['aid']]['#options'] = array($option['name']); } else { $desc[$option['aid']]['#options'][] = $option['name']; } $desc[$option['aid']]['#weight'] = $weight++; } } else { foreach ((array)$product->data['attributes'] as $attribute => $option) { $desc[] = array( '#attribute_name' => $attribute, '#options' => $option, '#weight' => $weight++, ); } } return $description; } /****************************************************************************** * Module Functions * ******************************************************************************/ /** * Load an attribute from the database. * * @param $attr_id * The id of the attribute. * @param $nid * If given, the attribute will have the options that have been assigned to * that $type for the attribute. * @param $type * Determines whether $nid refers to a node or product class. $nid is ignored * if $type is not 'product' or 'class'. * @return * An attribute object with its options. */ function uc_attribute_load($attr_id, $nid = NULL, $type = '') { if ($nid) { switch ($type) { case 'product': $attribute = db_fetch_object(db_query("SELECT a.aid, a.name, a.label AS default_label, a.ordering AS default_ordering, a.required AS default_required, a.display AS default_display, a.description, pa.label, pa.default_option, pa.required, pa.ordering, pa.display FROM {uc_attributes} AS a LEFT JOIN {uc_product_attributes} AS pa ON a.aid = pa.aid AND pa.nid = %d WHERE a.aid = %d", $nid, $attr_id)); $result = db_query("SELECT po.nid, po.oid, po.cost, po.price, po.weight, po.ordering, ao.name, ao.aid FROM {uc_product_options} AS po LEFT JOIN {uc_attribute_options} AS ao ON po.oid = ao.oid AND nid = %d WHERE aid = %d ORDER BY po.ordering, ao.name", $nid, $attr_id); break; case 'class': $attribute = db_fetch_object(db_query("SELECT a.aid, a.name, a.label AS default_label, a.ordering AS default_ordering, a.required AS default_required, a.display AS default_display, a.description, ca.default_option, ca.label, ca.required, ca.ordering, ca.display FROM {uc_attributes} AS a LEFT JOIN {uc_class_attributes} AS ca ON a.aid = ca.aid AND ca.pcid = '%s' WHERE a.aid = %d", $nid, $attr_id)); $result = db_query("SELECT co.pcid, co.oid, co.cost, co.price, co.weight, co.ordering, ao.name, ao.aid FROM {uc_class_attribute_options} AS co LEFT JOIN {uc_attribute_options} AS ao ON co.oid = ao.oid AND co.pcid = '%s' WHERE ao.aid = %d ORDER BY co.ordering, ao.name", $nid, $attr_id); break; default: $attribute = db_fetch_object(db_query("SELECT * FROM {uc_attributes} WHERE aid = %d", $attr_id)); $result = db_query("SELECT * FROM {uc_attribute_options} WHERE aid = %d ORDER BY ordering, name, label", $attr_id); break; } if (isset($attribute->default_ordering) && is_null($attribute->ordering)) { $attribute->ordering = $attribute->default_ordering; } if (isset($attribute->default_required) && is_null($attribute->required)) { $attribute->required = $attribute->default_required; } if (isset($attribute->default_display) && is_null($attribute->display)) { $attribute->display = $attribute->default_display; } if (isset($attribute->default_label) && is_null($attribute->label)) { $attribute->label = t($attribute->default_label); } if (empty($attribute->label)) { $attribute->label = $attribute->name; } } else { $attribute = db_fetch_object(db_query("SELECT * FROM {uc_attributes} WHERE aid = %d", $attr_id)); $result = db_query("SELECT * FROM {uc_attribute_options} WHERE aid = %d ORDER BY ordering, name", $attr_id); } if ($attribute) { $attribute->options = array(); while ($option = db_fetch_object($result)) { $attribute->options[$option->oid] = $option; } } return $attribute; } /** * Load the option identified by $oid. */ function uc_attribute_option_load($oid) { return db_fetch_object(db_query("SELECT * FROM {uc_attribute_options} WHERE oid = %d", $oid)); } /** * Load all attributes associated with a product node. */ function uc_product_get_attributes($nid) { $attributes = array(); $result = db_query("SELECT upa.aid FROM {uc_product_attributes} AS upa LEFT JOIN {uc_attributes} AS ua ON upa.aid = ua.aid WHERE upa.nid = %d ORDER BY upa.ordering, ua.name", $nid); while ($attribute = db_fetch_object($result)) { $attributes[$attribute->aid] = uc_attribute_load($attribute->aid, $nid, 'product'); } return $attributes; } /** * Load all attributes associated with a product class. */ function uc_class_get_attributes($pcid) { $attributes = array(); $result = db_query("SELECT uca.aid FROM {uc_class_attributes} AS uca LEFT JOIN {uc_attributes} AS ua ON uca.aid = ua.aid WHERE uca.pcid = '%s' ORDER BY uca.ordering, ua.name", $pcid); while ($attribute = db_fetch_object($result)) { $attributes[$attribute->aid] = uc_attribute_load($attribute->aid, $pcid, 'class'); } return $attributes; } /** * Get the options chosen for a product that is in the cart. * * @param $item * An element of the array returned by uc_cart_get_contents. * @return * Array of options chosen by a customer, indexed by attribute ids. Each * element stores the attribute name and the option object chosen. */ function _uc_cart_product_get_options($item) { $options = array(); $data = $item->data; $node = node_load($item->nid); $index = 0; if (!empty($data['attributes']) && is_array($data['attributes'])) { foreach ($data['attributes'] as $aid => $selected) { if (isset($node->attributes[$aid])) { $attribute = $node->attributes[$aid]; $name = _uc_attribute_get_name($attribute); // Only discrete options can affect the price of an item. if ($attribute->display && count($attribute->options)) { // There may be many selected options, or just one. foreach ((array)$selected as $oid) { if ($oid > 0) { $options[$index] = (array)$attribute->options[$oid]; $options[$index]['attribute'] = $name; $index++; } } } else { // Handle textfield attributes. $options[$index] = array( 'attribute' => $name, 'aid' => $aid, 'oid' => 0, 'name' => $selected, 'cost' => 0, 'price' => 0, 'weight' => 0, ); } $index++; } } } else { $options = array(); } return $options; } /** * Helper function for uc_attribute_form_alter(). * * @see theme_uc_attribute_add_to_cart() */ function _uc_attribute_alter_form($product) { // If the product doesn't have attributes, return the form as it is. if (!isset($product->attributes)) { $product->attributes = uc_product_get_attributes($product->nid); } if (!is_array($product->attributes) || empty($product->attributes)) { return NULL; } $nid = $product->nid; $qty = $product->default_qty; if (!$qty) { $qty = 1; } // Load all product attributes for the given nid. $priced_attributes = uc_attribute_priced_attributes($nid); $attributes = $product->attributes; $form_attributes = array(); $context = array( 'revision' => 'formatted', ); // Loop through each product attribute and generate its form element. foreach ($attributes as $attribute) { $context['subject']['attribute'] = $attribute; // Build the attribute's options array. $options = array(); foreach ($attribute->options as $option) { $context['subject']['option'] = $option; switch (variable_get('uc_attribute_option_price_format', 'adjustment')) { case 'total': $context['type'] = 'product'; $context['subject']['node'] = $product; $price_info = array( 'price' => $product->sell_price + $option->price, 'qty' => $qty, ); $display_price = in_array($attribute->aid, $priced_attributes) ? ', '. uc_price($price_info, $context) : ''; if (count($priced_attributes) == 1 && $attribute->display != 3) { break; } case 'adjustment': $context['type'] = 'attribute_option'; $price_info = array( 'price' => $option->price, 'qty' => $qty, ); $display_price = ($option->price != 0 ? ', '. ($option->price > 0 ? '+' : '') . uc_price($price_info, $context) : ''); break; case 'none': default: $display_price = ''; break; } $options[$option->oid] = t($option->name); if ($attribute->display == 2) { // Select options are check_plain()ed, but radio button labels are not. $options[$option->oid] = check_plain($options[$option->oid]); } $options[$option->oid] .= $display_price; } if (count($attribute->options) && $attribute->display > 0) { if ($attribute->required) { if ($attribute->display == 1) { $options = array('' => t('Please select')) + $options; } unset($attribute->default_option); } switch ($attribute->display) { case 1: $attr_type = 'select'; break; case 2: $attr_type = 'radios'; break; case 3: $attr_type = 'checkboxes'; break; } $form_attributes[$attribute->aid] = array( '#type' => $attr_type, '#description' => check_markup($attribute->description), '#default_value' => ($attr_type == "checkboxes" ? array() : $attribute->default_option), '#options' => $options, '#required' => $attribute->required, ); } else { $form_attributes[$attribute->aid] = array( '#type' => 'textfield', '#description' => check_markup($attribute->description), '#default_value' => $attribute->required == FALSE ? $attribute->options[$attribute->default_option]->name : '', '#required' => $attribute->required, ); } $name = _uc_attribute_get_name($attribute, FALSE); if (!is_null($name)) { $form_attributes[$attribute->aid]['#title'] = check_plain($name); } $form_attributes['#theme'] = 'uc_attribute_add_to_cart'; } return $form_attributes; } /** * Return an array of display types used as options when creating attributes. */ function _uc_attribute_display_types() { return array( 0 => t('Text field'), 1 => t('Select box'), 2 => t('Radio buttons'), 3 => t('Checkboxes'), ); } /** * Get the price affecting attributes for a product * * @param $nid * The nid of a product. * @return * Array of attribute ids that have price affecting options. */ function uc_attribute_priced_attributes($nid) { $attributes = db_query("SELECT DISTINCT (pa.aid) FROM {uc_product_attributes} AS pa INNER JOIN {uc_attribute_options} AS ao ON ao.aid = pa.aid INNER JOIN {uc_product_options} AS po ON (po.oid = ao.oid AND po.nid = pa.nid) WHERE pa.nid = %d AND po.price <> 0 AND pa.display <> 0", $nid); $aids = array(); while ($attribute = db_fetch_array($attributes)) { $aids[] = $attribute['aid']; } return $aids; } /** * Display the attribute selection form elements. * * @ingroup themeable * @see _uc_attribute_alter_form() */ function theme_uc_attribute_add_to_cart($form) { $output = '
'; $stripes = array('even' => 'odd', 'odd' => 'even'); $parity = 'even'; foreach (element_children($form) as $aid) { $parity = $stripes[$parity]; $classes = array('attribute', 'attribute-'. $aid, $parity); $output .= '
'; $output .= drupal_render($form[$aid]); $output .= '
'; } $output .= drupal_render($form) .'
'; return $output; } /** * Returns the attribute name to display. * * An attribute with a label set returns that label except when set to * ''. In this case, a NULL is returned. The $title argument forces the * function to return the name property instead of label when label is set to * ''. * * The NULL return value is typically used by forms so they know to hide the * #title property of the element. * * @param $attribute * Attribute object * @param $title * TRUE indicates the function is to return the attribute name when its label * is set to ''. * @return * When the attribute label is set and not '', it is returned. * Otherwise, the attribute name is returned when $title is TRUE and NULL is * returned when $title is FALSE. */ function _uc_attribute_get_name($attribute, $title = TRUE) { if (!$title && $attribute->label == '') { return NULL; } else { return (empty($attribute->label) || ($attribute->label == '' && $title) ? t($attribute->name) : t($attribute->label)); } }

Στο gant που ετοιμάζω αυτή την περίοδο προσπαθώ και γώ να τα περάσω όλα αυτά σαν overides στο template.php για να μην έχω τα θέματα που ανέφερα ποιό πάνω με τα updates.
Αλλά τα δεν έχω φτάσει ακόμα στα attributes .
Αυτό που μπορώ να δώσω μέχρι στιγμής απο template.php σε multi είναι το θέμα του catalog που το θεωρώ εξήσου critical για ένα ubercart eshop με το attributes...
Οπότε έχουμε και λέμε.

function uc_catalog_set_breadcrumb_multilingual($tid) {
  static $breadcrumbs = array();
  static $terms = array();
  if (variable_get('uc_catalog_breadcrumb', TRUE)) {
    if (empty($breadcrumbs)) {
      if (variable_get('site_frontpage', 'node') != 'catalog') {
        $breadcrumbs[] = l(t('Home'), '');
      }
      if ($tid != 0) {
				//fix by alexku start
        //$breadcrumbs[] = l(variable_get('uc_catalog_name', t('Catalog')), 'catalog');
				global $language;
				$catalog_name = variable_get('uc_catalog_name', 'Catalog');
				$catalog_id = variable_get('uc_catalog_vid', '1');
				$translated_name = i18nstrings("taxonomy:vocabulary:$catalog_id:name", $catalog_name, $language->language, FALSE);
				$breadcrumbs[] = l($translated_name, variable_get('uc_catalog_url', 'catalog'));
				//fix by alexku end
      }
    }
    $parents = taxonomy_get_parents_all($tid);
    // Remove current term from the breadcrumb.
    array_shift($parents);
    $types = uc_product_types();
    while (count($parents)) {
      $current = array_pop($parents);
      //fix by miraclegr start
      $current->name = tt("taxonomy:term:$current->tid:name", $current->name, NULL, FALSE);
      
      if ($current->description) {
        $current->description = tt("taxonomy:term:$current->tid:description", $current->description, NULL, FALSE);
      }
      //fix by miraclegr end
      if (!in_array($current->tid, $terms)) {
        $n = 0;
        foreach ($types as $type) {
          $n += taxonomy_term_count_nodes($current->tid, $type);
        }
        $current->nodes = $n;
        $breadcrumbs[] = l($current->name . (variable_get('uc_catalog_breadcrumb_nodecount', FALSE) && $current->nodes ? ' ('. $current->nodes .')' : ''), uc_catalog_path($current));
        $terms[] = $current->tid;
      }
    }
    //print '
'. print_r($breadcrumbs, TRUE) .'

';
return $breadcrumbs;
}
else {
return NULL;
}
}

function _uc_catalog_navigation_multilingual($branch) {
static $terms;
static $breadcrumb;
static $types;

//fix by alexku start
global $language;
if ($branch->tid) {
$branch->name = i18nstrings("taxonomy:term:$branch->tid:name", $branch->name, $language->language, TRUE);
if ($branch->description) {
$branch->description = i18nstrings("taxonomy:term:$branch->tid:description", $branch->description, $language->language, FALSE);
}
}
//fix by alexku end

if (empty($types)) {
$types = uc_product_types();
}

$num = 0;
foreach ($types as $type) {
$num += taxonomy_term_count_nodes($branch->tid, $type);
}

// No nodes in category or descendants. Not in path and display nothing.
if (!$num) {
return array(FALSE, '');
}

$branch_path = uc_catalog_path($branch);
if (!isset($breadcrumb)) {
$breadcrumb = drupal_get_breadcrumb();
}
$vid = variable_get('uc_catalog_vid', 0);
if ($_GET['q'] == $branch_path) {
// The URL points to this term.
$here = TRUE;
}
else {
$here = FALSE;
}
if (!isset($terms)) {
$terms = taxonomy_node_get_terms_by_vocabulary(menu_get_object('node', 1), $vid);
}
// Determine whether to expand menu item.
if ((arg(0) == 'node' && array_key_exists($branch->tid, $terms))) {
$inpath = FALSE;
foreach ($breadcrumb as $link) {
if (strpos($link, drupal_get_path_alias($branch_path)) !== FALSE) {
$inpath = TRUE;
}
}
}
else {
$inpath = $here;
}

// Checks to see if node counts are desired in navigation
$num_text = '';
if (variable_get('uc_catalog_block_nodecount', TRUE)) {
$num_text = ' ('. $num .')';
}

$lis = array();
$expand = variable_get('uc_catalog_expand_categories', FALSE);
$link = l($branch->name . $num_text, $branch_path);
if ($expand || count($branch->children)) {
foreach ($branch->children as $twig) {
// Expand if children are in the menu path. Capture their output.
list($child_in_path, $lis[]) = _uc_catalog_navigation_multilingual($twig);
if ($child_in_path) {
$inpath = $child_in_path;
}
}
}
$output = theme("uc_catalog_item", $here, $link, $lis, $expand, $inpath, count($branch->children));

// Tell parent category your status, and pass on output.
return array($inpath, $output);
}

function THEME_preprocess_block(&$variables, $hook) {
if ($variables['block']->module == 'uc_catalog' && $variables['block']->delta == '0') {
$subject = &$variables['block']->subject;
global $language;
$catalog_name = variable_get('uc_catalog_name', 'Catalog');
$catalog_id = variable_get('uc_catalog_vid', '1');
$subject = i18nstrings("taxonomy:vocabulary:$catalog_id:name", $catalog_name, $language->language, FALSE);

if (variable_get('uc_catalog_block_title', FALSE)) {
$subject = l($subject, 'catalog');
}
}
}

function THEME_preprocess_node(&$vars, $hook) {
$node = (object)$vars;

if (uc_product_is_product($node->type) && variable_get('uc_catalog_breadcrumb', TRUE)) {
$crumbs = array();
if (variable_get('site_frontpage', 'node') != 'catalog') {
$crumbs[] = l(t('Home'), '');
}
$terms = taxonomy_node_get_terms_by_vocabulary($node, variable_get('uc_catalog_vid', 0));
if (count($terms)) {
//fix by alexku start
//$crumbs[] = l(variable_get('uc_catalog_name', t('Catalog')), variable_get('uc_catalog_url', 'catalog'));
global $language;
$catalog_name = variable_get('uc_catalog_name', 'Catalog');
$catalog_id = variable_get('uc_catalog_vid', '1');
$translated_name = i18nstrings("taxonomy:vocabulary:$catalog_id:name", $catalog_name, $language->language, FALSE);
$crumbs[] = l($translated_name, variable_get('uc_catalog_url', 'catalog'));
//fix by alexku end
$used_tids = array();
foreach ($terms as $term) {
if (!isset($parents[$term->tid])) {
$parents[$term->tid] = taxonomy_get_parents_all($term->tid);
}
//drupal_set_message('

'. print_r($parents[$term->tid], TRUE) .'

');
foreach (array_reverse($parents[$term->tid]) as $parent) {
//fix by alexku start
$parent->name = i18nstrings("taxonomy:term:$parent->tid:name", $parent->name, $language->language, FALSE);
if ($parent->description) {
$parent->description = i18nstrings("taxonomy:term:$parent->tid:description", $parent->description, $language->language, FALSE);
}
//fix by alexku end
if (!in_array($parent->tid, $used_tids)) {
$crumbs[] = l($parent->name, uc_catalog_path($parent));
$used_tids[] = $parent->tid;
}
}
}
}
drupal_set_breadcrumb($crumbs);
}
}

function THEME_uc_catalog_browse($tid = 0) {
global $language;
drupal_add_css(drupal_get_path('module', 'uc_catalog') .'/uc_catalog.css');

$output = '';
$catalog = uc_catalog_get_page((int)$tid);
//fix by alexku start
//check if we are on the catalog or on the category page
if (!$catalog->tid) {
//if on catalog page
$catalog->name = i18nstrings("taxonomy:vocabulary:$catalog->vid:name", $catalog->name, $language->language, FALSE);
if ($catalog->description) {
$catalog->description = i18nstrings_tt("taxonomy:vocabulary:$catalog->vid:description", $catalog->description, $language->language, FALSE);
}
}
else {
//if on category (term) page
$catalog->name = i18nstrings("taxonomy:term:$catalog->tid:name", $catalog->name, $language->language, FALSE);
if ($catalog->description) {
$catalog->description = i18nstrings("taxonomy:term:$catalog->tid:description", $catalog->description, $language->language, FALSE);
}
}
//fix by alexku end
drupal_set_title(check_plain($catalog->name));
drupal_set_breadcrumb(uc_catalog_set_breadcrumb($catalog->tid));
$types = uc_product_types();
$links = array();
$child_list = array();

foreach ($catalog->children as $child) {

//fix by alexku start
$child->name = i18nstrings("taxonomy:term:$child->tid:name", $child->name, $language->language, FALSE);
if ($child->description) {
$child->description = i18nstrings("taxonomy:term:$child->tid:description", $child->description, $language->language, FALSE);
}
//fix by alexku end
if (!empty($child->nodes)) {
$links[] = array('title' => $child->name . (variable_get('uc_catalog_breadcrumb_nodecount', FALSE) ? ' ('. $child->nodes .')' : ''), 'href' => uc_catalog_path($child),
'attributes' => array('rel' => 'tag'),
);

}
if (!empty($child->image)) {
$image = '

';
if (module_exists('imagecache')) {
$image .= l(theme('imagecache', 'uc_category', $child->image['filepath']), uc_catalog_path($child), array('html' => TRUE));
}
else {
$image .= l(theme('image', $child->image['filepath']), uc_catalog_path($child), array('html' => TRUE));
}
$image .= '

';
}
else {
$image = '

';
}
$grandchildren = array();
$j = 0;
$max_gc_display = 3;
foreach ($child->children as $i => $grandchild) {
if ($j > $max_gc_display) {
break;
}
$g_child_nodes = 0;
foreach ($types as $type) {
$g_child_nodes += taxonomy_term_count_nodes($grandchild->tid, $type);
}
if ($g_child_nodes) {
$grandchildren[$i] = l($grandchild->name, uc_catalog_path($grandchild), array('class' => 'subcategory'));
$j++;
}
}
//$grandchildren = array_slice($grandchildren, 0, intval(count($grandchildren) / 2) + 1, TRUE);
if ($j > $max_gc_display) {
array_push($grandchildren, l(t('More...'), uc_catalog_path($child), array('class' => 'subcategory')));
}
if ($child->nodes) {
$cell_link = $image .''. l($child->name, uc_catalog_path($child)) .'';
if (variable_get('uc_catalog_show_subcategories', TRUE)) {
$cell_link .= "
". implode(', ', $grandchildren) ."\n";
}
$child_list[] = $cell_link;
}
}
if (!empty($catalog->image)) {
if (module_exists('imagecache')) {
$output .= theme('imagecache', 'uc_thumbnail', $catalog->image['filepath'], $catalog->name, $catalog->name, array('class' => 'category'));
}
else {
$output .= theme('image', $catalog->image['filepath'], $catalog->name, $catalog->name, array('class' => 'category'));
}
}

// Build an ORDER BY clause for the SELECT query based on table sort info.
if (empty($_REQUEST['order'])) {
$order = 'ORDER BY p.ordering, n.title, n.nid';
}
else {
$order = tapirsort_sql(uc_product_table_header());
}

$sql = "SELECT DISTINCT(n.nid), n.sticky, n.title, n.created, p.model, p.sell_price, p.ordering
FROM {node} n
INNER JOIN {term_node} tn ON n.vid = tn.vid
INNER JOIN {uc_products} AS p ON n.vid = p.vid
WHERE tn.tid = %d AND n.status = 1
AND n.type IN (". db_placeholders($types, 'varchar') .") ". $order;

$sql_count = "SELECT COUNT(DISTINCT(n.nid))
FROM {node} n
INNER JOIN {term_node} tn ON n.vid = tn.vid
INNER JOIN {uc_products} AS p ON n.vid = p.vid
WHERE tn.tid = %d
AND n.status = 1
AND n.type IN (". db_placeholders($types, 'varchar') .")";

$sql = db_rewrite_sql($sql);
$sql_count = db_rewrite_sql($sql_count);
$sql_args = array($catalog->tid);
foreach ($types as $type) {
$sql_args[] = $type;
}
$catalog->products = array();

$result = pager_query($sql, variable_get('uc_product_nodes_per_page', 12), 0, $sql_count, $sql_args);
while ($node = db_fetch_object($result)) {

$catalog->products[] = $node->nid;
}

if (count($catalog->products)) {

if (count($links)) {
$output .= theme('links', $links, array('class' => 'links inline uc-categories')) ."
\n";
}
$output .= $catalog->description;
$output .= theme('uc_catalog_products', $catalog->products);
$output .= theme('pager');
}
else {
// Display table of child categories similar to an osCommerce site's front page.
$columns = variable_get('uc_catalog_category_columns', 3);
$cat_rows = array();
$row = array();
$i = 1;
foreach ($child_list as $cell) {
$row[] = array('data' => $cell, 'class' => 'category');
if ($i % $columns == 0) {
$cat_rows[] = $row;
$row = array();
}
$i++;
}
if (count($row) > 0 && count($row) < $columns) {
if (count($cat_rows) >= 1) {
$row = array_merge($row, array_fill(count($row), $columns - count($row), array('data' => ' ', 'class' => 'category')));
}
$cat_rows[] = $row;
}
$output .= $catalog->description;
$output .= theme('table', array(), $cat_rows, array('class' => 'category'));
}

return $output;
}

function THEME_uc_catalog_item($here, $link, $lis, $expand, $inpath, $count_children ) {
$output = '';

if ($expand || $count_children) {
if ($here) {
$output = '

  • '. $link ."\n";
    if (count($lis)) {
    $output .= '
      ';
      foreach ($lis as $li) {
      $output .= $li ."\n";
      }
      $output .= "

    \n";
    }
    $output .= "

  • ";
    }
    elseif ($expand || $inpath) {
    $output = '

  • '. $link ."\n";
    if (count($lis)) {
    $output .= '
      ';
      foreach ($lis as $li) {
      $output .= $li;
      }
      $output .= "

    \n";
    }
    $output .= "

  • ";
    }
    else {
    $output = '

  • '. $link ."
  • \n";
    }
    }
    else {
    $output = '

  • '. ($inpath ? '' : '') . $link . ($inpath ? '' : '') ."
  • \n";
    }

    return $output;
    }

    function THEME_uc_catalog_block($menu_tree) {
    $output = '

    ';

    return $output;
    }

    Απο τη στιγμή που ασχολείσαι και σύ με ubercart θα μπορούσαμε να κάνουμε ένα sprint να περάσουμε όλα αυτά τα απαρέτητα overides σε ενα template να τα έχουμε στην φαρέτρα μας. Στην συλογή μου υπάρχουν αρκετά overrides σε μή translatable χρήσημα modules σε template όπως του megamenu για παράδειγμα ... και πολύ περισσότερα ακόμα "πειραγμένα" modules που περιμένουν στην ουρά.
    Ακόμα πάνω σε ubercart πάιζουν και "πειραγμενα" modules για το cart κλπ

    @boboss Ευχαριστώ πολύ για το σεντόνι. Αφού το μελετήσω θα επανέλθω με σχόλια και σκοπό να φτιάξουμε το template που θα κάνει τα απαραίτητα overides για το ubercart. Επίσης αν χρειαστεί να κάνουμε hacks στο ubercart προτείνω αντί για αυτό να φτιάξουμε ένα module που θα κάνει implement τα αντίστοιχα hooks. Είμαι της λογικής every time you hack core (or contrib) god kills a kitten :) ... λατρεύω τις γάτες :)

    Θα ανοίξω χωριστό thread για αυτό το θέμα.

    Όσον αφορά το D7 commerce, το δοκίμασα για μια δυο μέρες αλλά μου φάνηκε:

    α. αρκετά πιο σύνθετο σε διαχειριστική λογική (Αν έχω 1 μπλουζάκι σε 6 χρώματα και 5 μεγέθη, θέλω 5χ6 products ;;;)
    β. Αρκετά ανώριμο, πρώτη φορά βάζω τόσα modules σε dev, alpha και beta
    γ. Δεν υπάρχουν κάποιες δυνατότητες που μου είναι απαραίτητες, όπως ένα textfield που να συμπληρώνει ο χρήστης πριν την κάνει add to cart ένα προϊόν (πχ για ένα όνομα και ημερομηνία σε δαχτυλίδι γάμου)

    από την άλλη όσον αφορά την πολυγλωσσικότητα δεν συνάντησα προβλήματα στις δοκιμές μου. Απλά για τους παραπάνω λόγους θα προτιμήσω το d6 ubercart για ανάπτυξη που πρέπει να παραδοθεί το καλοκαίρι του 2011.

    [quote]Είμαι της λογικής every time you hack core (or contrib) god kills a kitten :) ... λατρεύω τις γάτες :)[/quote]
    σε μένα το λές για τις γάτες
    (το νέο μέλος της codestar στη στιγμή που το εκπαιδεύαμε. Παρατήρησε ενδιαφέρον που δίχνει).
    Αν σε βολευει περισσότερο να στα ρίξω σε ένα dropbox αυτά γιατί ετσι όπως έχουν Postaριστει εδω δεν βολέυει να τα μελετήσεις.
    D7 commerce
    α) Αυτή δεν είναι όμως η λογική που δουλεύει μια επιχείριση και έξω απο το νέτ ?? Το ροζ Large μπλουζάκι δεν είναι διαφορέτικό απο το Κιτρινο Medium με διαφορετικό κωδικό ,φωτογραφία,απόθεμα και στοιχεία?
    β) θα συμφωνήσω με τα χίλια
    γ) Γιατί δεν μπορείς να το κάνεις αυτό? Μάλλον που δεν μπορείς να το κάνεις?? Πλέον με τα fields στο core μπορείς να βάλεις fields στο node στην καλάθι και γενικά παντού.

    Πίσω στο Ubercart. Θα είναι πολύ καλή κίνηση να φτιάξουμε αυτό το template Θα βοηθηθούμε και μείς στα επόμεα Project μας και θα βοηθήσουμε και όσους θέλουν να μπούν στο έργο του ubercart. Αν και βλέπω οτι αρκετά modules αρχίζουν να γίνονται comptible με το i18. Πχ το megamenu που ανέφερα παραπάνω είδα σήμερα οτι στην dev παίζει με το i18.Τωρα για αυτό που λές για τo Hacking κλπ ναι θα συμφωνήσω απόλυτα αλλα απο τη θεωρεία στην πράξη έχει μια διαφορά. Όταν έχεις ένα project που τρέχει και θέλεις να κάνεις δουλειά σου είναι πολύ έυκολο να μπεις στη διαδικασία "να οριστε πείραξα εδώ δυο γραμμούλες και όλα δουλεύουν ρολόι.. Ναι ρε μην αγχώνεσαι θυματε τι πως το έκανα.. Αντε πάμε παρακάτω να λυσουμε και τα άλλα θέματα που έχουμε τώρα έχουμε μείνει πίσω... ) και τα αποτελέσματα γνωστά σε όλους μας.

    Καθώς αυτό το thread παραείναι μεγάλο συνεχίζω τη συζήτηση για ubercart σε d6 στο thread: http://mydrupal.gr/ubercart-σε-drupal-6-μεταφράζοντας-τα-attributes

    Θα επανέλθω και για το drupal commerce σε d7 σε χωριστό thread, όταν βρω λίγο χρόνο να πειραματιστώ παραπάνω.