Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Extensión imprescindible......................................................................................................................12
Cómo quitar la doble selección de atributo en productos configurables...............................................12
Traducir la etiqueta “Price from”...........................................................................................................14
Solucionando el problema con el código HTML en el precio en información adicional.........................14
Solucionando problema. El precio en la caja de añadir al carrito cuando se selecciona el atributo no
cambia..................................................................................................................................................15
Cambiar posición del símbolo de la moneda........................................................................................16
Hacer que las imágenes cambien más rápido en SCP.........................................................................16
Modificación en el listado de subcategorías. Mostrando a dos columnas............................................41
Incrementando la seguridad de la carpeta que contiene los PDF.........................................................47
Modificando Magento
Todos estos cambios se realizan sobre la plantilla Default de Magento 1.4.1
Versión 1.0 del Documento (octubre de 2010)
Eliminamos la línea:
<p class="welcome-msg"><?php echo $this->getWelcome()?></p>
Existe otro fichero en esta misma ruta Mage_CatalogSearch.csv que también contiene este texto, como de momento no
sabemos a que corresponde lo cambiaremos también por el mismo texto que hayamos cambiado en el archivo anterior.
Y lo ubicamos en el lugar donde se referencia la columna derecha quedando el código como sigue:
<block type="core/text_list" name="right" as="right" translate="label">
<label>Right Column</label>
<block type="page/template_links" name="top.links" as="topLinks"/>
</block>
Por si acaso:
<?=$this->getLayout()->getBlock('top.links')->toHtml()?>
Eliminamos las líneas que hacen referencia a la división quick access, que son esta:
<div class="quick-access">
<?php echo $this->getChildHtml('topSearch') ?>
<?php echo $this->getChildHtml('topLinks') ?
<?php echo $this->getChildHtml('store_language') ?>
</div>
con lo que el código nos quedaría del siguiente modo:
<div class="header">
<?php if ($this->getIsHomePage()):?>
<h1 class="logo"><strong><?php echo $this->getLogoAlt() ?></strong><a
href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><img src="<?php echo $this->getLogoSrc() ?>"
alt="<?php echo $this->getLogoAlt() ?>" /></a></h1>
<?php else:?>
<a href="<?php echo $this->getUrl('') ?>" title="<?php echo $this-
>getLogoAlt() ?>" class="logo"><strong><?php echo $this->getLogoAlt() ?
></strong><img src="<?php echo $this->getLogoSrc() ?>" alt="<?php echo $this-
>getLogoAlt() ?>" /></a>
<?php endif?>
<?php echo $this->getChildHtml('topContainer'); ?>
</div>
Bien la imagen incluida se llama en el ejemplo cabecera.gif, y además le hemos asignado un estilo de la hoja
de estilo que se llama logoright. De este modo también podremos controlar determinados aspectos sobre
como se muestra la imagen en la misma hoja de estilos. En el ejemplo el código lo hemos incluido en la
plantilla Default en la sección HEADER, justo entre el estilo .header h1.logo y el estilo .header .quick-access.
La línea que hemos incluido es tal y como sigue:
.header .logoright { float:right; margin:40px 0 3px 3px; }
En el archivo: /app/design/frontend/default/mi_tema/template/catalog/navigation/top.phtml
Lo haremos de tal modo que el archivo mencionado quede así:
<div class="nav-container">
<ul id="nav">
<?php echo $_menu; ?>
<li class="mini-search"><?=$this->getLayout()->getBlock('top.search')->toHtml()?
></li>
</ul>
</div>
Si nos fijamos en la línea de código introducida le hemos asignado a la etiqueta <li> una nueva clase que
tendremos que crear dentro de la sección de Navigation de la hoja de estilos. Este nuevo estilo que
agregamos nos centrará verticalmente el formulario de búsqueda y lo alineará a la derecha.
#nav .mini-search {float:right; margin:0 auto; padding:3px 0 0 0; }
Ahora vamos a perfeccionar nuestro formulario de búsqueda y elimnaremos la etiqueta (label) que además
aparece en inglés. Iremos al archivo:
/app/design/frontend/default/mi_tema/template/catalogsearch/form.mini.pahtml
y buscamos la siguiente línea:
<label for="search"><?php echo $this->__('Search:') ?></label>
La comentamos y listo:
<!-- <label for="search"><?php echo $this->__('Search:') ?></label> -->
Nos fijamos en la instrucción before=”-”, que también fuerza a que el carrito de compra se posicione el
primero, y además tendrá prioridad por tratarse de un módulo que dispone de su propio layout (o eso creo),
bien lo cambiamos para que el carrito quede por encima del modulo de comparación de productos, por lo que
el código nos queda:
<reference name="right">
<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml" before="catalog.compare.sidebar">
Bien pues aquí vemos que el comparar productos tiene la instrucción before, con lo que entra en
contradicción con la modificación que hicimos en el archivo checkout.xml, simplemente cambiamos la
instrucción por after... y listo.
Donde dice “left” ponemos “right”. Con este simple cambio hemos hecho todo lo dicho.
Y añadimos la siguiente línea justo en la ubicación que se indica, la línea está en negrita:
<reference name="top.links">
<action method="addLink" translate="label title"
module="customer"><label>Log In</label><url
helper="customer/getLoginUrl"/><title>Log
In</title><prepare/><urlParams/><position>100</position></action>
<action method="addLink" translate="label title"
module="customer"><label>Register</label><url
helper="customer/getRegisterUrl"/><title>Register</title><prepare/><urlParams
/><position>20</position></action>
</reference>
-->
<customer_logged_out>
<reference name="right">
</reference>
Bien, si queremos publicarlo (sobre todo para ver como queda la inclusión de un nuevo botón en este
bloque), simplmente descomentamos el código.
Para incluir el botón tenemos que editar el fichero de plantilla correspondiente a este mini formulario:
/app/design/frontend/default/mi_tema/template/customer/form
Y justo despues de la etiqueta que cierra el formulario (</form) y antes de la que etiqueta con la que finaliza el
fichero (</div>), incluimos el siguiente código:
<div class="actions">
<button class="button"
onclick="location.href='/customer/account/create'"><span><span><?php echo
$this->__('Register') ?></span></span></button>
</div>
Ahora solo tenemos que ajustar los estilos que le estamos aplicando al botón.
<action
method="setImgSrc"><src>images/media/col_right_callout.jpg</src></action>
</block>
</reference>
Bien, cortamos esta línea (en negrita) y la ubicamos en el bloque izquierda, justo encima de este bloque,
quedaría así:
<reference name="left">
<block type="catalog/product_compare_sidebar" after="cart_sidebar"
name="catalog.compare.sidebar"
template="catalog/product/compare/sidebar.phtml"/>
<block type="core/template" name="left.permanent.callout"
template="callouts/left_col.phtml">
<action
method="setImgSrc"><src>images/media/col_left_callout.jpg</src></action>
<action method="setImgAlt" translate="alt"
module="catalog"><alt>Our customer service is available 24/7. Call us at
(555) 555-0123.</alt></action>
<action method="setLinkUrl"><url>checkout/cart</url></action>
</block>
Pues bien, si modificaba el archivo links para incluirle aspecto de bloque resultaba que, como es normal, este
aspecto o estilo también se aplicaba a los enlaces del footer puesto que tanto estos como los top links tienen
el mismo archivo de origen en la plantilla, es decir, links.phtml.
Para solventar esto hay que replicar el archivo links.phtml de tal modo que cuando sea llamado por los Top
Links, el archivo referenciado sea diferente del archivo referenciado por el footer.
A esta réplica le aplicamos los estilos de un bloque de contenido mediante div´s y luego solo tenemos que
referenciar la réplica modificada y crear los estilos personalizados.
Así pues, vamos allá:
Primer paso: Creamos la réplica del archivo links.phtml y le aplicamos los estilos que posteriormente
crearemos. En la ruta de links.phtml creamos el archivo links2.phtml con el mismo contenido que el original y
con las siguientes modificaciones. Se muestra el archivo final:
<?php $_links = $this->getLinks(); ?>
<?php if(count($_links)>0): ?>
<div class="block block-account-per">
<div class="block-title-per">
<strong><span>OPCIONES DEL USUARIO</span></strong>
</div>
<div class="block-content-per">
<ul class=""block-content-per li""<?php if($this->getName()): ?> id="<?php
echo $this->getName() ?>"<?php endif;?>>
<?php foreach($_links as $_link): ?>
<li<?php if($_link->getIsFirst()||$_link->getIsLast()): ?> class="<?
php if($_link->getIsFirst()): ?>first<?php endif; ?><?php if($_link-
>getIsLast()): ?> last<?php endif; ?>"<?php endif; ?> <?php echo $_link-
>getLiParams() ?>><?php echo $_link->getBeforeText() ?><a href="<?php echo
$_link->getUrl() ?>" title="<?php echo $_link->getTitle() ?>" <?php echo
$_link->getAParams() ?>><?php echo $_link->getLabel() ?></a><?php echo
$_link->getAfterText() ?></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php endif; ?>
Lo único que cambiamos respecto a la línea inicial es la ruta del archivo de la plantilla, el resto es igual. Es
decir en block type, pese a que referencia la ruta, no la cambiamos la dejamos como incialmente, tampoco
cambiamos el nombre (name) ni la forma de referenciarlo (as), sólo la ruta y el archivo al que apunta la
referencia.
Esta línea, en mi caso, la he incluido en el bloque derecho por lo que su ubicación es como sigue:
<block type="core/text_list" name="right" as="right" translate="label">
<label>Right Column</label>
<!-- <block type="page/template_links" before="-"
name="top.links" as="topLinks"/>-->
<block type="page/template_links" before="-"
name="top.links" as="topLinks" template="page/template/links2.phtml"/>
</block>
Hay que observar que la línea comentada es precisamente la original, que previamente se encontraba dentro
de la cabecera pero que yo la cambié al lboque derecho anteriormente.
Tercer paso: por último, debemos crear los estilos que hemos asignado a links2.phtml. Yo me he limitado a
copiar el estilo de la sección Block: Account, pegándolo como una nueva sección justo debajo de la orginal, y
posteriormente renombrándolo:
/* Block: Account Personalizado */
.block-account-per { border-color:#bbb; }
.block-account-per .block-title-per { background:#fc9d36 url(../images/bkg_block-
title-account.gif) 0 100% repeat-x; border:0; padding:3px 10px; }
.block-account-per .block-title-per strong { font-size:12px; color:#fff; }
.block-account-per .block-content-per { background:#fbfaf6; padding:7px 10px 7px; }
.block-account-per .block-content-per li a { display:block; border-bottom:1px solid
#ddd; padding:3px 0; color:#5f5d5c; text-decoration:none !important; }
.block-account-per .block-content-per li a:hover { color:#ea7900; }
.block-account-per .block-content-per li.last a { border-bottom:0; }
.block-account-per .block-content-per li.current { border-bottom:1px solid #ddd;
padding:3px 0; color:#ea7900; }
.block-account-per .block-content-per li.current.last { border-bottom:0; }
Y eso es todo. Cuánto trabajo me costó, cuánto tiempo, para algo que así visto parece muy simple.
Productos Configurables
Extensión imprescindible
Simple Configurable Products. Esta extensión permite que los productos configurables cojan el precio del
producto simple asociado y no el follón que monta Magento al respecto. Pero también permite que los datos
del producto simple asociado sean mostrados cuando se selecciona el atributo que le corresponde, inclusive
la imagen. Lo que la hace una extensión imprescindible.
Si tenemos instalado el Simple Configurable Products puede ocurrir que al crear un producto configurable con
al menos un atributo para seleccionar por el cliente, nos aparezca dos veces el desplegable de la selección,
que además están relacionados porque mientras no seleccionemos la opción en el primero que nos parece,
no podremos hacer selección en el segundo, lo que lleva a confusión, además de suponer un aso inútil para
el cliente. Bien para quitar el que nos parece primero, lo que haremos es editar el archivo
//app/design/frontend/default/mitema/template/catalog/product/view/type/configurable.phtml
El contenido completo de este archivo es:
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE_AFL.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category design
* @package base_default
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free
License (AFL 3.0)
*/
?>
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this-
>getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label><?php echo $_attribute->getLabel() ?><span
class="required"> *</span></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<select name="super_attribute[<?php echo $_attribute-
>getAttributeId() ?>]" id="attribute<?php echo $_attribute-
>getAttributeId() ?>" class="required-entry super-attribute-select">
<option><?php echo $this->__('Choose an Option...') ?></option>
</select>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>
Pues borramos o comentamos las siguientes líneas con lo que el archivo no queda así (en el caso de
borrado):
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE_AFL.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category design
* @package base_default
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free
License (AFL 3.0)
*/
?>
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this-
>getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>
Por ejemplo.
with:
<td class="data"><?php echo html_entity_decode($_helper-
>productAttribute($_product, $_data['value'], $_data['code'])); ?> </td>
the html_entity_decode will replace the > and other html special chars with < “ and >
Anyway it works for me now
Esta opción ha funcionado correctamente. La segunda ni siquiera la he probado, pero aquí está:
Segunda opción: De un correo recibido de Matt Dean.
For the display of Price in the additional attributes table it just looks like a Magento bug to me.
My quick fix would be to do the following:
in: app/code/core/Mage/Catalog/Helper/Output.php change line 106 from:
if ($attribute && ($attribute->getFrontendInput() != 'media_image')
to
if ($attribute && ($attribute->getFrontendInput() != 'media_image' &&
$attribute->getFrontendInput() != 'price')
La respuesta me la da San Matt Dean, en un correo electrónico cuya primera parte dice:
So did you try changing price_clone.phtml so that it uses
$this->getPrice($_product, false)
instead of
$this->getPrice($_product, false, '_clone')
Cambiar posición del símbolo de la moneda
http://www.magentocommerce.com/boards/viewthread/57000/
En español
http://foros.mgnt.es/showthread.php?1492-Cambiar-posicion-simbolo-del-_
Ir a la carpeta lib/Zend/Locale/data y edtar el fichero es.xml
Buscar la cadena de texto:
<pattern>¤ #,##0.00</pattern>
y cambiar la posición de #,##0.00 delante de los símbolos.
Pero a mi me aparece: <pattern>#,##0.00 ¤Â</pattern>
y las À no se para que son. Avisar que en este caso el editor VI puede jugarte una mala pasada, y eso es lo
que me pasaba a mi. Yo al final tuve que editar el fichero en otro ordenador con Linux y subirlo al servidor (ojo
con los permisos al subirlo).
Pero antes de hacer nada, debéis vaciar una serie de directorios, puesto que aunque tengáis la caché de
Magento deshabilitada parece que en este caso como que no le afecta. Si no vaciáis esas carpeta os podréis
encontrar con la desagradable sorpresa de no poder entrar en el panel de administración porque os arroja un
error, justo el que se indica en el epígrafe siguiente. También debemos limpiar la caché del navegador.
Parece que el símbolo de moneda es muy delicado.
Los directorios a vaciar son:
• /var/cache
• /var/locks
• /var/report
• Yo por si acaso también borreo el directorio de sesiones /var/session
Ahora limpiamos la caché, temporales, etc... del navegador y ya debe funcionar.
Me lo dijo Matt Dean basta con poner a no la opción de configuración de la extensión SCP “Update gallery
images as well as main image?”.
De este modo las imágenes tardan mucho menos en cargar y es casi inmediato.
Implementando los Impuesto
Del enlace: http://lab.redmallorca.com/como-configurar-el-iva-en-magento/
Primero nos vamos a Ventas->Impuestos->Impuestos al producto. Aquí daremos de alta un nuevo tipo de
impuesto al producto. En nuestro caso debemos dar de alta ds tipos de impuestos:
1. Reducido (IVA al 8%) para los productos comercializados.
2. Normal (IVA al 18%) para el transporte.
Estos tipos de impuestos los tendremos disponibles en la ficha de los productos.
Ahora vamos a dar de alta los impuestos al cliente, que será el tipo de impuesto que le asignaremos a cada
uno de nuestros grupos de clientes. Accedemos a Ventas->Impuestos->Impuestos al cliente y damos de alta
un nuevo tipo, en este caso sólo tendremos Cliente final. En el apartado de clientes->Grupos de Clientes del
panel de administración podemos asignar a cada grupo de nuestros clientes una tasa de impuestos diferente.
De hecho es necesario hacer esto para que los impuestos sean aplicados.
Ahora vamos a especificar las zonas y tasas correspondientes para la gestión de los impuestos de nuestra
tienda. Para ello accedemos a Ventas->Impuestos->Gestionar zonas de impuesto y tasas. Aquí podemos
especificar las tasas de impuesto de cada país, provincia o código postal de los clientes de nuestra
tienda. A las provincias que estén exentas de impuestos, les asignaremos una tasa de 0.
Disponemos de la opción de exportar e importar la información de impuestos para poder automatizar estos
pasos a través de un editor de archivos csv. Puede ser muy útil para agilizar la operación y no tener que
repetir pasos si queremos, por ejemplo, poner una nueva tasa al 4% o al 7%.
Por último, vamos a enlazar toda la información que hemos creado, dando de alta una nueva regla de
impuesto. Para ello, accedemos a Ventas->Impuestos->Gestionar reglas de impuestos. Simplemente le
damos un nombre a la regla y vamos seleccionando las opciones que nos aparecen, entre ellas veremos los
impuestos al cliente e impuestos al producto que hemos creado, así como las tasas.
Ya hemos creado las reglas de impuestos necesarias, que recordemos combinan impuestos al cliente,
impuestos al producto, y tasas de impuestos que están creadas en virtud de las zonas (país, provincia e
incluso códigos postales). De esta forma es casi imposible que no podamos establecer los impuestos por
raros y tergiversados que estos sean.
Pero nos queda un aspecto importante para poner en marcha nuestros impuestos. Lo primero es que
debemos tener correctamente ajustados o configurados los siguientes parámetros en Configuración (Sistema
->Configuración).
1. Cofiguración General -> General. Aquí debemos establecer el país por defecto de la tienda y los
demás parámetros que nos solicitan sobre opciones locales y paises en los que se habilita la venta.
2. Configuración General ->Ventas -> Impuestos. Aquí estableceremos todas las opciones generales
sobre la aplicación de impuestos, incluyendo si incluiremos los precios con IVA, si se mostrarán con
IVA o sin IVA, etc. Esto último es interesante saberlo puesto que nos permitirá meter los precios de
los artículos incluso antes de establecer las relgas de impuestos, ya que los podremos meter con IVA
o si él y en la opción de configuración le diremos a Magento si lo hemos incluido con o sin IVA.
Despues ir a CMS > Static Blocks. Click en Add New Block y llenar así
Block Title: Sub Category Listing
Identifier: sub_category_listing
Status: Enabled
Content: {{block type="catalog/navigation" template="catalog/navigation/sub_category_listing.phtml"}}
Click Save
Ahora hay que habilitar el static blok en las categorías madres
Ir a: Catalog > Manage Categories.
Ir a “General Information” y elegir una imagen para la categoría en examinar
Entonces clikear en la categoría madre que tiene subcategorias, ir a la solapa “Display Settings”.
Llenar los campos de la siguiente manera:
Display Mode: Static Block Only
CMS Block: Sub Category Listing
Is Anchor: Yes
Contenido de los ficheros:
Contenido del archivo Category.php (ocupa 20 pàginas)
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
* @package Mage_Catalog
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien
(http://www.varien.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software
License (OSL 3.0)
*/
/**
* Catalog category model
*
* @category Mage
* @package Mage_Catalog
* @author Magento Core Team <core@magentocommerce.com>
*/
class Mage_Catalog_Model_Resource_Eav_Mysql4_Category extends
Mage_Catalog_Model_Resource_Eav_Mysql4_Abstract
{
/**
* Category tree object
*
* @var Varien_Data_Tree_Db
*/
protected $_tree;
/**
* Catalog products table name
*
* @var string
*/
protected $_categoryProductTable;
/**
* Id of 'is_active' category attribute
*
* @var int
*/
protected $_isActiveAttributeId = null;
/**
* Store id
*
* @var int
*/
protected $_storeId = null;
/**
* Class constructor
*/
public function __construct()
{
$resource = Mage::getSingleton('core/resource');
$this->setType('catalog_category')
->setConnection(
$resource->getConnection('catalog_read'),
$resource->getConnection('catalog_write')
);
$this->_categoryProductTable = $this-
>getTable('catalog/category_product');
}
/**
* Set store Id
*
* @param integer $storeId
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function setStoreId($storeId)
{
$this->_storeId = $storeId;
return $this;
}
/**
* Return store id
*
* @return integer
*/
public function getStoreId()
{
if (is_null($this->_storeId)) {
return Mage::app()->getStore()->getId();
}
return $this->_storeId;
}
/**
* Retrieve category tree object
*
* @return Varien_Data_Tree_Db
*/
protected function _getTree()
{
if (!$this->_tree) {
$this->_tree = Mage::getResourceModel('catalog/category_tree')
->load();
}
return $this->_tree;
}
/**
* Process category data before delete
* update children count for parent category
* delete child categories
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _beforeDelete(Varien_Object $object)
{
parent::_beforeDelete($object);
/**
* Update children count for all parent categories
*/
$parentIds = $object->getParentIds();
$childDecrease = $object->getChildrenCount() + 1; // +1 is itself
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count'=>new Zend_Db_Expr('`children_count`-'.
$childDecrease)),
$this->_getWriteAdapter()->quoteInto('entity_id IN(?)',
$parentIds)
);
/**
* Recursion use a lot of memmory, that why we run one request for
delete children
*/
/*if ($child = $this->_getTree()->getNodeById($object->getId())) {
$children = $child->getChildren();
foreach ($children as $child) {
$childObject = Mage::getModel('catalog/category')-
>load($child->getId())->delete();
}
}*/
$select = $this->_getWriteAdapter()->select()
->from($this->getEntityTable(), array('entity_id'))
->where($this->_getWriteAdapter()->quoteInto('`path` LIKE ?',
$object->getPath().'/%'));
$childrenIds = $this->_getWriteAdapter()->fetchCol($select);
if (!empty($childrenIds)) {
$this->_getWriteAdapter()->delete(
$this->getEntityTable(),
$this->_getWriteAdapter()->quoteInto('entity_id IN (?)',
$childrenIds)
);
}
/**
* Add deleted children ids to object
* This data can be used in after delete event
*/
$object->setDeletedChildrenIds($childrenIds);
return $this;
}
/**
* Process category data before saving
* prepare path and increment children count for parent categories
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _beforeSave(Varien_Object $object)
{
parent::_beforeSave($object);
if (!$object->getId()) {
$object->setPosition($this->_getMaxPosition($object->getPath()) +
1);
$path = explode('/', $object->getPath());
$level = count($path);
$object->setLevel($level);
if ($level) {
$object->setParentId($path[$level - 1]);
}
$object->setPath($object->getPath() . '/');
$toUpdateChild = explode('/',$object->getPath());
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('children_count'=>new
Zend_Db_Expr('`children_count`+1')),
$this->_getWriteAdapter()->quoteInto('entity_id IN(?)',
$toUpdateChild)
);
}
return $this;
}
/**
* Process category data after save category object
* save related products ids and update path value
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _afterSave(Varien_Object $object)
{
/**
* Add identifier for new category
*/
if (substr($object->getPath(), -1) == '/') {
$object->setPath($object->getPath() . $object->getId());
$this->_savePath($object);
}
$this->_saveCategoryProducts($object);
return parent::_afterSave($object);
}
/**
* Update path field
*
* @param Mage_Catalog_Model_Category $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _savePath($object)
{
if ($object->getId()) {
$this->_getWriteAdapter()->update(
$this->getEntityTable(),
array('path'=>$object->getPath()),
$this->_getWriteAdapter()->quoteInto('entity_id=?', $object-
>getId())
);
}
return $this;
}
$result = 0;
try {
$result = (int) $this->getReadConnection()->fetchOne($select);
} catch (Exception $e) {
}
return $result;
}
/**
* Save category products
*
* @param Mage_Catalog_Model_Category $category
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _saveCategoryProducts($category)
{
$category->setIsChangedProductList(false);
/**
* new category-product relationships
*/
$products = $category->getPostedProducts();
/**
* Example re-save category
*/
if (is_null($products)) {
return $this;
}
/**
* old category-product relationships
*/
$oldProducts = $category->getProductsPosition();
$productTable = $this->getTable('catalog/product');
$productUpdateSql = sprintf('UPDATE `%s` AS `e` SET
`category_ids`=(SELECT
GROUP_CONCAT(`category_id`) FROM `%s` AS `cp` WHERE
`cp`.`product_id`=`e`.`entity_id`)
WHERE `e`.`entity_id` IN(?)', $productTable, $this-
>_categoryProductTable);
/**
* Delete products from category
*
*/
if (!empty($delete)) {
$deleteIds = array_keys($delete);
$this->_getWriteAdapter()->delete($this->_categoryProductTable,
$this->_getWriteAdapter()->quoteInto('product_id in(?)',
$deleteIds) .
$this->_getWriteAdapter()->quoteInto(' AND category_id=?',
$category->getId())
);
$sql = $this->_getWriteAdapter()->quoteInto($productUpdateSql,
$deleteIds);
$this->_getWriteAdapter()->query($sql);
}
/**
* Add products to category
*
*/
if (!empty($insert)) {
$insertSql = array();
foreach ($insert as $k => $v) {
$insertSql[] = '('.(int)$category->getId().','.(int)$k.','.
(int)$v.')';
}
$sql = sprintf(
'INSERT INTO `%s` (`category_id`,`product_id`,`position`)
VALUES%s',
$this->_categoryProductTable,
join(',', $insertSql)
);
$this->_getWriteAdapter()->query($sql);
$insertIds = array_keys($insert);
$sql = $this->_getWriteAdapter()->quoteInto($productUpdateSql,
$insertIds);
$this->_getWriteAdapter()->query($sql);
}
/**
* Update product positions in category
*
*/
if (!empty($update)) {
foreach ($update as $k => $v) {
$cond = array(
$this->_getWriteAdapter()->quoteInto('category_id=?',
(int)$category->getId()),
$this->_getWriteAdapter()->quoteInto('product_id=?',
(int)$k)
);
$where = join(' AND ', $cond);
$bind = array(
'position' => (int)$v
);
$this->_getWriteAdapter()->update($this-
>_categoryProductTable, $bind, $where);
}
}
if (!empty($insert) || !empty($delete)) {
$productIds = array_unique(array_merge(array_keys($insert),
array_keys($delete)));
Mage::dispatchEvent('catalog_category_change_products', array(
'category' => $category,
'product_ids' => $productIds
));
}
return $this;
}
/**
* Get store identifiers where category is presented
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getStoreIds($category)
{
if (!$category->getId()) {
return array();
}
$nodePath = $this->_getTree()
->getNodeById($category->getId())
->getPath();
$nodes = array();
foreach ($nodePath as $node) {
$nodes[] = $node->getId();
}
$stores = array();
$storeCollection = Mage::getModel('core/store')->getCollection()-
>loadByCategoryIds($nodes);
foreach ($storeCollection as $store) {
$stores[$store->getId()] = $store->getId();
}
$entityStoreId = $category->getStoreId();
if (!in_array($entityStoreId, $stores)) {
array_unshift($stores, $entityStoreId);
}
if (!in_array(0, $stores)) {
array_unshift($stores, 0);
}
return $stores;
}
/**
* Get positions of associated to category products
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getProductsPosition($category)
{
$select = $this->_getWriteAdapter()->select()
->from($this->_categoryProductTable, array('product_id',
'position'))
->where('category_id=?', $category->getId());
$positions = $this->_getWriteAdapter()->fetchPairs($select);
return $positions;
}
/**
* Get chlden categories count
*
* @param int $categoryId
* @return int
*/
public function getChildrenCount($categoryId)
{
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'children_count')
->where('entity_id=?', $categoryId);
$child = $this->_getReadAdapter()->fetchOne($select);
return $child;
}
/**
* Move category to another parent
*
* @param int $categoryId
* @param int $newParentId
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function move($categoryId, $newParentId)
{
$category = Mage::getModel('catalog/category')->load($categoryId);
$oldParent = $category->getParentCategory();
$newParent = Mage::getModel('catalog/category')->load($newParentId);
$childrenCount = $this->getChildrenCount($category->getId()) + 1;
// update parent id
$this->_getWriteAdapter()->query("UPDATE
{$this->getEntityTable()} SET parent_id = {$newParent->getId()}
WHERE entity_id = {$categoryId}");
return $this;
}
/**
* Check if category id exist
*
* @param int $id
* @return bool
*/
public function checkId($id)
{
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id=?', $id);
return $this->_getReadAdapter()->fetchOne($select);
}
/**
* Check array of category identifiers
*
* @param array $ids
* @return array
*/
public function verifyIds(array $ids)
{
$validIds = array();
$select = $this->_getWriteAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id IN(?)', $ids);
$query = $this->_getWriteAdapter()->query($select);
while ($row = $query->fetch()) {
$validIds[] = $row['entity_id'];
}
return $validIds;
}
/**
* Get count of active/not active children categories
*
* @param Mage_Catalog_Model_Category $category
* @param bool $isActiveFlag
* @return int
*/
public function getChildrenAmount($category, $isActiveFlag = true)
{
$storeId = Mage::app()->getStore()->getId();
$attributeId = $this->_getIsActiveAttributeId();
$table = Mage::getSingleton('core/resource')-
>getTableName('catalog/category') . '_int';
$select = $this->_getReadAdapter()->select()
->from(array('m'=>$this->getEntityTable()),
array('COUNT(m.entity_id)'))
->joinLeft(
array('d'=>$table),
"d.attribute_id = '{$attributeId}' AND d.store_id = 0 AND
d.entity_id = m.entity_id",
array()
)
->joinLeft(
array('c'=>$table),
"c.attribute_id = '{$attributeId}' AND c.store_id =
'{$storeId}' AND c.entity_id = m.entity_id",
array()
)
->where('m.path like ?', $category->getPath() . '/%')
->where('(IFNULL(c.value, d.value) = ?)', $isActiveFlag);
return $this->_getReadAdapter()->fetchOne($select);
}
/**
* Get "is_active" attribute identifier
*
* @return int
*/
protected function _getIsActiveAttributeId()
{
if (is_null($this->_isActiveAttributeId)) {
$select = $this->_getReadAdapter()->select()
->from(array('a'=>$this->getTable('eav/attribute')),
array('attribute_id'))
->join(array('t'=>$this->getTable('eav/entity_type')),
'a.entity_type_id = t.entity_type_id')
->where('entity_type_code = ?', 'catalog_category')
->where('attribute_code = ?', 'is_active');
$this->_isActiveAttributeId = $this->_getReadAdapter()-
>fetchOne($select);
}
return $this->_isActiveAttributeId;
}
/**
* Rebuild associated products index
*
* @param array $categoryIds
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
public function refreshProductIndex($categoryIds = array(), $productIds =
array(), $storeIds = array())
{
/**
* Prepare visibility and status attributes information
*/
$statusAttribute = Mage::getSingleton('eav/config')-
>getAttribute('catalog_product', 'status');
$visibilityAttribute = Mage::getSingleton('eav/config')-
>getAttribute('catalog_product', 'visibility');
$statusAttributeId = $statusAttribute->getId();
$visibilityAttributeId = $visibilityAttribute->getId();
$statusTable = $statusAttribute->getBackend()->getTable();
$visibilityTable = $visibilityAttribute->getBackend()-
>getTable();
/**
* Select categories data
*/
$select = $this->_getReadAdapter()->select()
->from($this->getTable('catalog/category'))
->order('level')
->order('path');
if (is_array($categoryIds) && !empty($categoryIds)) {
$select->where('entity_id IN (?)', $categoryIds);
} elseif (is_numeric($categoryIds)) {
$select->where('entity_id=?', $categoryIds);
}
$categories = $this->_getWriteAdapter()->fetchAll($select);
$storesCondition = '';
if (!empty($storeIds)) {
$storesCondition = $this->_getWriteAdapter()->quoteInto(
' AND s.store_id IN (?)', $storeIds
);
}
/**
* Get information about stores root categories
*/
$stores = $this->_getWriteAdapter()->fetchAll("
SELECT
s.store_id, s.website_id, c.path AS root_path
FROM
{$this->getTable('core/store')} AS s,
{$this->getTable('core/store_group')} AS sg,
{$this->getTable('catalog/category')} AS c
WHERE
sg.group_id=s.group_id
AND c.entity_id=sg.root_category_id
{$storesCondition}
");
$indexTable = $this->getTable('catalog/category_product_index');
$productCondition = '';
if (!empty($productIds)) {
$productCondition = $this->_getWriteAdapter()->quoteInto(
' AND product_id IN (?)', $productIds
);
}
$insProductCondition = str_replace('product_id', 'cp.product_id',
$productCondition);
foreach ($categories as $category) {
$categoryId = $category['entity_id'];
$path = $category['path'];
$this->_getWriteAdapter()->delete(
$indexTable,
'category_id='.$categoryId. ' AND store_id='.$storeId.
$productCondition
);
$this->_getWriteAdapter()->query($query);
}
}
return $this;
}
return $this->_getReadAdapter()->fetchCol($select);
}
/**
* Get products count in category
*
* @param unknown_type $category
* @return unknown
*/
public function getProductCount($category)
{
$productTable =Mage::getSingleton('core/resource')-
>getTableName('catalog/category_product');
$select = $this->getReadConnection()->select();
$select->from(
array('main_table'=>$productTable),
array(new Zend_Db_Expr('COUNT(main_table.product_id)'))
)
->where('main_table.category_id = ?', $category->getId())
->group('main_table.category_id');
$counts =$this->getReadConnection()->fetchOne($select);
return intval($counts);
}
/**
* Deprecated since 1.1.7
*
* @param Varien_Object $object
* @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category
*/
protected function _saveCountChidren($object)
{
$chidren = $object->getChildren();
if (strlen($chidren)>0) {
$chidrenCount = count(explode(',', $chidren));
} else {
$chidrenCount = 0;
}
$this->_getWriteAdapter()->update($this->getEntityTable(),
array('children_count'=>$chidrenCount),
$this->_getWriteAdapter()->quoteInto('entity_id=?', $object-
>getId())
);
return $this;
}
/**
* Deprecated
*
* @param Varien_Object $object
* @return unknown
*/
protected function _saveInStores(Varien_Object $object)
{
if (!$object->getMultistoreSaveFlag()) {
$stores = $object->getStoreIds();
foreach ($stores as $storeId) {
if ($object->getStoreId() != $storeId) {
$newObject = clone $object;
$newObject->setStoreId($storeId)
->setMultistoreSaveFlag(true)
->save();
}
}
}
return $this;
}
/**
* Deprecated
*/
protected function _updateCategoryPath($category, $path)
{
return $this;
if ($category->getNotUpdateDepends()) {
return $this;
}
foreach ($path as $pathItem) {
if ($pathItem->getId()>1 && $category->getId() != $pathItem-
>getId()) {
$category = Mage::getModel('catalog/category')
->load($pathItem->getId())
->save();
}
}
return $this;
}
/**
* Retrieve categories
*
* @param integer $parent
* @param integer $recursionLevel
* @param boolean|string $sorted
* @param boolean $asCollection
* @param boolean $toLoad
* @return Varien_Data_Tree_Node_Collection|
Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection
*/
public function getCategories($parent, $recursionLevel = 0,
$sorted=false, $asCollection=false, $toLoad=true)
{
$tree = Mage::getResourceModel('catalog/category_tree');
/** @var $tree Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Tree
*/
$nodes = $tree->loadNode($parent)
->loadChildren($recursionLevel)
->getChildren();
if ($asCollection) {
return $tree->getCollection();
}
return $nodes;
}
/**
* Return parent categories of category
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getParentCategories($category)
{
$pathIds = array_reverse(explode(',', $category->getPathInStore()));
$categories = Mage::getResourceModel('catalog/category_collection')
->setStore(Mage::app()->getStore())
->addAttributeToSelect('name')
->addAttributeToSelect('url_key')
->addAttributeToSelect('image')
->addFieldToFilter('entity_id', array('in'=>$pathIds))
->addFieldToFilter('is_active', 1)
->load()
->getItems();
return $categories;
}
/**
* Enter description here...
*
* @param Mage_Catalog_Model_Category $category
* @return unknown
*/
public function getChildrenCategories($category)
{
$collection = $category->getCollection();
/* @var $collection
Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection */
$collection->addAttributeToSelect('url_key')
->addAttributeToSelect('name')
->addAttributeToSelect('image')
->addAttributeToSelect('all_children')
->addAttributeToSelect('is_anchor')
->addAttributeToFilter('is_active', 1)
->addIdFilter($category->getChildren())
->setOrder('position', 'ASC')
->joinUrlRewrite()
->load();
return $collection;
}
/**
* Return children ids of category
*
* @param Mage_Catalog_Model_Category $category
* @param boolean $recursive
* @return array
*/
public function getChildren($category, $recursive = true)
{
$attributeId = $this->_getIsActiveAttributeId();
$select = $this->_getReadAdapter()->select()
->from(array('m' => $this->getEntityTable()), 'entity_id')
->joinLeft(
array('d' => $this->getEntityTable() . '_int'),
"d.attribute_id = '{$attributeId}' AND d.store_id = 0 AND
d.entity_id = m.entity_id",
array()
)
->joinLeft(
array('c' => $this->getEntityTable() . '_int'),
"c.attribute_id = '{$attributeId}' AND c.store_id =
'{$category->getStoreId()}' AND c.entity_id = m.entity_id",
array()
)
->where('(IFNULL(c.value, d.value) = ?)', '1')
->where('path LIKE ?', "{$category->getPath()}/%");
if (!$recursive) {
$select->where('level <= ?', $category->getLevel() + 1);
}
$_categories = $this->_getReadAdapter()->fetchAll($select);
$categoriesIds = array();
foreach ($_categories as $_category) {
$categoriesIds[] = $_category['entity_id'];
}
return $categoriesIds;
// $this->_getTree()->load();
// return $this->_getTree()->getChildren($category->getId(), false);
}
/**
* Return all children ids of category (with category id)
*
* @param Mage_Catalog_Model_Category $category
* @return array
*/
public function getAllChildren($category)
{
$children = $this->getChildren($category);
$myId = array($category->getId());
$children = array_merge($myId, $children);
return $children;
// $this->_getTree()->load();
// $children = $this->_getTree()->getChildren($category->getId());
//
// $myId = array($category->getId());
// if (is_array($children)) {
// $children = array_merge($myId, $children);
// } else {
// $children = $myId;
// }
//
// return $children;
}
/**
* Check is category in list of store categories
*
* @param Mage_Catalog_Model_Category $category
* @return boolean
*/
public function isInRootCategoryList($category)
{
$innerSelect = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), new Zend_Db_Expr("CONCAT(path, '/
%')"))
->where('entity_id = ?', Mage::app()->getStore()-
>getRootCategoryId());
$select = $this->_getReadAdapter()->select()
->from($this->getEntityTable(), 'entity_id')
->where('entity_id = ?', $category->getId())
->where(new Zend_Db_Expr("path LIKE ({$innerSelect-
>__toString()})"));
return (bool) $this->_getReadAdapter()->fetchOne($select);
// $tree = $this->_getTree();
// $tree->load();
// $children = $tree->getChildren(Mage::app()->getStore()-
>getRootCategoryId(), true);
// if (!in_array($category->getId(), $children)) {
// return false;
// }
// return true;
}
}
Esta modificación viene en el mismo enlace mencionado al comienzo, y consiste en cambiar el fichero
sub_category_listing.phtml ara que muestre las subcategorías en dos solumans. También ah y que incluir
nuevos estilos en la hoja de estilos:
El contenido del fichero sub_category_listing.phtml es el siguiente:
<?php
$category = $this->getCurrentCategory();
$id = $category->getId();
?>
<?php $_categories=$this->getCurrentChildCategories(); ?>
<div class="list-type-grid category-listing">
<?php $i=0; foreach ($_categories as $_category): ?>
<?php if($i==0): ?>
<ol class="grid-row">
<?php endif; ?>
<li class="item">
<?php if($_category->getIsActive()): ?>
<div class="product-image">
<a href="<?php echo $_category->getURL() ?>" title="<?php
echo $this->htmlEscape($_category->getName()) ?>">
<img src="<?php echo
$_category->getImageUrl() ?>" width="140" alt="<?php echo $this-
>htmlEscape($_category->getName()) ?>" />
</a>
</div>
<h5><a href="<?php echo $_category->getURL() ?>" title="<?php echo
$this->htmlEscape($_category->getName()) ?>"><?php echo $this->htmlEscape($_category-
>getName()) ?></a></h5>
<?php echo $_category->getDescription() ?>
<?php endif; ?>
</li>
<?php ($i = $i+1); ?>
<?php if($i==2):?>
</ol>
<?php ($i = 0); ?>
<?php endif; ?>
<?php endforeach ?>
<script type="text/javascript">decorateGeneric($$('.grid-row'), ['last',
'odd', 'even']);</script>
</div>
Lo que la primera parte hace es tomar el "título" de los atributos (Fijado en la sección de Gestión de atributos
en back end) y cambia el "título" a minúsculas y los espacios por "-" (en el caso de que el nombre del atributo
tenga más de una palabra).
Entonces la segunda parte inyecta la variable $ tmpTitle como una etiqueta de "clase" para su uso por CSS
con un poco de magia!.
Ahora todo los que se necestia hacer es ir al archivo CSS y por ejemplo, si queremos ocultar un atributo
como la Categoría, hacer una entrada CSS como la siguiente:
.layered-nav .category { display: none; }
He encontrado que esta técnica me da más control general. Por ejemplo, en algunas categorías, puede ser
que se desee mostrar Precio mientras que en otras no.
Opción 2. No funciona
Del enlace: http://www.imagedia.com/2010/04/remove-categories-from-shop-by-options-in-magento/
Consiste en sustituir el contenido del archivo:
app/design/frontend/default/your_template/template/catalog/layer/view.phtml
Por el siguiente código:
<?php
/**
* Category layered navigation
*
* @see Mage_Catalog_Block_Layer_View
*/
?>
<?php if($this->canShowBlock()): ?>
<div class=”box layered-nav”>
<div class=”head”>
<h3><?php echo $this->__(’Shop by’) ?></h3>
</div>
<div class=”border-creator”>
<?php echo $this->getStateHtml() ?>
<?php if($this->canShowOptions()): ?>
<div class=”narrow-by”>
<h4><?php echo $this->__(’Browsing Options’) ?></h4>
<dl id=”narrow-by-list”>
<?php $_filters = $this->getFilters() ?>
<?php foreach ($_filters as $_filter): ?>
<?php if($_filter->getItemsCount()): ?>
<?php if($_filter->getName() != “Category”){ ?>
<dt><?php echo $this->__($_filter->getName()) ?></dt>
<dd>
<?php echo $_filter->getHtml() ?>
</dd>
<?php } endif; ?>
<?php endforeach; ?>
</dl>
<script type=”text/javascript”>decorateDataList(’narrow-by-list’)</script>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<!– [ends] .browse-by // –>
Opción 4: Usando una extensión. No la he probado, aunque dice que vale para todas las versiones de
Magento.
La llave de la extensión es: magento-community/Adtrak_DisableCategoryFilter-0.1.0
El enlace donde se encuentra: http://www.magentocommerce.com/extension/packages/module/1678/disable-
layered-nav-category-filter#releases
estas líneas se encuentran en la sección del fichero Category layered navigation layout
Lo que he hecho es comentar la línea que referencia a product_viewed.phtml para mantener el original, y
después la he copiado y modificado según aparece en el resultado final a continuación, también he cambiado
la posición de right a left en la etiqueta <reference name>:
<remove name="right.reports.product.viewed" />
<reference name="left">
<!-- <block type="reports/product_viewed"
before="right.permanent.callout" name="left.reports.product.viewed"
template="reports/product_viewed.phtml" />-->
<block type="reports/product_viewed"
name="left.reports.product.viewed" template="reports/product_viewed.phtml" />
</reference>
</catalog_category_layered_nochildren>
Bien mediante este cambio conseguimos que en la vista de catálogo los productos vistos recientemente
aparezcan a la izquierda, pero como las páginas de vistas de subcategorías realmente son listados o lo que
es lo mismo reportes, entonces me dirijo al archivo reports.xml. El contenido de este archivo se limita a:
<layout version="0.1.0">
<default>
<!-- Mage_Reports -->
<reference name="right">
<block type="reports/product_viewed"
before="right.permanent.callout" name="right.reports.product.viewed"
template="reports/product_viewed.phtml" />
<block type="reports/product_compared"
before="right.permanent.callout" name="right.reports.product.compared"
template="reports/product_compared.phtml" />
</reference>
</default>
</layout>
Bien pues tendremos que cambiarlo para que cambie de posición el bloque de productos vistos
recientemente que está referenciado en el primer block type. Dejando el contenido del archivo del siguiente
modo:
<layout version="0.1.0">
<default>
<!-- Mage_Reports -->
<reference name="left">
<block type="reports/product_viewed"
before="right.permanent.callout" name="right.reports.product.viewed"
template="reports/product_viewed.phtml" />
</reference>
<reference name="right">
<!--<block type="reports/product_viewed" before="right.permanent.callout"
name="right.reports.product.viewed" template="reports/product_viewed.phtml" />-->
<block type="reports/product_compared"
before="right.permanent.callout" name="right.reports.product.compared"
template="reports/product_compared.phtml" />
</reference>
</default>
</layout>
(PENDIENTE) Colocando Banners en Magento
Una vez hecho lo anterior me di cuenta que si te situabas encima del enlace al fichero te daba la ruta, si la
copias y la pegas en el navegador te muestra el directory Index, vamos que ve lo que hay ahí, y tal y como
están las cosas es poco recomendable. Así que intenté mejorar la seguridad, ¿cómo?, buscando en Google y
con los famosos ficheros .htaccess
Bien, para evitar que te listen el índice de la carpeta, en la misma creamos un .htaccess en el que incluimos
la siguiente línea:
Options -Indexes
Así nos mostrará la típica página de Apache con el Forbidden...perooo....en esta página se nos muestra tanto
el sistema operativo como el apache y su versión, tampoco me gusta. Así que busqué un poco más, y de
nuevo el ficherito .htaccess nos va a ser útil.
Incluí la siguiente línea en el mismo, y listo, ahora la página que me muestra es la que tiene por defecto
Magento para las páginas no encontradas:
ErrorDocument 403 /html/errors/404.php
Con estas dos líneas y el ficherito hemos contribuido en algo a la seguridad de nuestra tienda.
Si alguien que lea este documento sabe como hacerlo, pues que aporte.
En ese mismo post viene otra forma de hacerlo pero es algo más complicada. A mi esta me funcionó.
Y la sustituimos por:
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>
Ok...si ahora refrescamos la pàgina (teniendo la caché de Magento deshabilitada), veremos que la columna
aparece a la derecha pero que los bloques han cambiado, no nos aparece el Menú de Mi Cuenta, ni el carrito,
ni el perrito, etc....¿Por qué?. Veamos la sección justo anterior a la que hemos visto de este archivo, donde
pone:
<!--
Customer account pages, rendered for all tabs in dashboard
-->
Bien pues en ambas líneas vamos a cambiar la palabra left por right. Ahora si nos aparece el menú de Mi
Cuenta y el Carrito, es más éste nos aparece duplicado. Pero no nos aparece los productos vistos
recientemente y el perrito. Ese me da igual porque no lo quiero en esta página, pero quiero que aparezcan
los productos vistos recientemente y obviamente quitar un carrito de la compra, así como otro menú que
tengo yo de opciones de usuario creado con los toplinks.
Para eso sólo tenemos que repasar el código de ambas secciones y veremos las referencias a lo que
queremos o no queremos.
Bien para quitar el menú opciones de usuario que yo tengo (que son los toplinks convertidos en bloque, ya
hemos visto como hacerlo en este documento), y que según revisamos en el fichero customer.xml se cargan
en todas aquellas páginas en lo que no se diga lo contrario, tendremos que hacer precisamente eso: Decirle
lo contrario. Y para eso nos sirve la etiqueta <remove>
En la sección:
<!--
Customer account pages, rendered for all tabs in dashboard
-->
Que lo que nos dice es que son las páginas de la cuenta del cliente, que se reproducen para todas las
etiquetas (enlaces) en el panel de control, añadimos los siguiente antes del final de la sección, quedando tal
que así:
</reference>
<remove name="top.links"></remove>
</customer_account>
Así evitamos que el bloque que creé con los toplinks aparezca.
Ahora vamos a quitar uno de los carritos....queremos que nos compren pero mejor no ser pesados.
En la misma sección que en el caso anterior vamos a comentar las líneas que referencian el bloque del
Carrito, por lo que la sección quedaría así:
<reference name="right">
<block type="customer/account_navigation"
name="customer_account_navigation" before="-"
template="customer/account/navigation.phtml">
<action method="addLink" translate="label"
module="customer"><name>account</name><path>customer/account/</path><label>Ac
count Dashboard</label></action>
<action method="addLink" translate="label"
module="customer"><name>account_edit</name><path>customer/account/edit/</path
><label>Account Information</label></action>
<action method="addLink" translate="label"
module="customer"><name>address_book</name><path>customer/address/</path><lab
el>Address Book</label></action>
</block>
<!--<block type="checkout/cart_sidebar" name="cart_sidebar"
template="checkout/cart/sidebar.phtml">
<action
method="addItemRender"><type>simple</type><block>checkout/cart_item_renderer<
/block><template>checkout/cart/sidebar/default.phtml</template></action>
<action
method="addItemRender"><type>grouped</type><block>checkout/cart_item_renderer
_grouped</block><template>checkout/cart/sidebar/default.phtml</template></act
ion>
<action
method="addItemRender"><type>configurable</type><block>checkout/cart_item_ren
derer_configurable</block><template>checkout/cart/sidebar/default.phtml</temp
late></action>
</block>
-->
Como se ve hemos comentado el bloque al completo, y así eliminamos uno de los carritos de compra.
Más cosas, ahora queremos que debajo del carrito nos aparezca el bloque de productos vistos
recientemente,
Para eso en la misma sección debemos añadir el bloque de productos vistos recientemente y decirle que
debe ir después del carrito de compra. Pues nada incluimos la siguiente línea:
<block type="reports/product_viewed" before="right.permanent.callout"
name="left.reports.product.viewed" template="reports/product_viewed.phtml" />
A que molan los layout...parecen complejos pero cuando le coges el rollo facilitan mucho las cosas.
Bien pues el problema reside en las etiquetas “strong”, si las quitamos el texto se traduce perfectamente, y
además el enlace aparece en negrita igualmente. Las líneas quedarían así:
"There are <a href=""%s"">%s items</a> in your cart.","Hay <a href=""%s"">%s artÃ-
culos</a> en su cesta."
"There is <a href=""%s"">1 item</a> in your cart.","Hay <a href=""%s"">1 artÃculo</a>
en su cesta."
Y listo.
Por:
$currency = $this->convertToServiredCurrency($order->getOrderCurrencyCode());
Un detalle de mucho interés. Resulta que la línea comment=null la comenté en modo pruebas y funcionó el
módulo. Cuando pasé al modo REAL el módulo no funcionaba y siempre me daba error de Número de
Pedido Repetido, la descomenté y el módulo salió andando.
Ahora no vamos al final de la función mencionada, justo antes de $order->save(); y buscamos la línea (que
está justo antes de order->save), y delante de ella pegamos el código que se muestra a continuación,
quedando el final de la función como se ve:
if (!$orderStatus) {
$orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
}
$order->setState($orderState, $orderStatus,$comment,true);
$order->save();
El estilo que he aplicado al texto es una copia del estilo notice-msg, y lo he llamado notice-msg-propio, al
objeto de ajustarlo a esta plantilla y no modificar el original con lo que me podría encontrar con sorpresas
desagradables.
Ahora en la hoja de estilos crearemos este estilo, y hay que hacerlo en dos líneas, porque existen dos líneas
que lo referencian. Lo que hacemos es copiar esas dos líneas y duplicarlas, cambiarles el nombre y luego
ajustar los valores a nuestra conveniencia. A continuación se muestran esta líneas en negrita y en la posición
en que yo las he puesto:
.notice-msg { border-style:solid !important; border-width:1px !important;
background-position:10px 9px !important; background-repeat:no-repeat !
important; min-height:24px !important; padding:8px 8px 8px 32px !important;
font-size:11px !important; font-weight:bold !important; }
.notice-msg-propio { border-style:solid !important; border-width:1px !important;
background-position:5px 5px !important; background-repeat:no-repeat !important; min-
height:17px !important; padding:8px 8px 3px 24px !important; font-size:11px !
important; font-weight:bold !important; margin:10px 0px 0px 150px !important;
float:left !important; }
.error-msg { border-color:#f16048; background-color:#faebe7; background-
image:url(../images/i_msg-error.gif); color:#df280a; }
.success-msg { border-color:#446423; background-color:#eff5ea; background-
image:url(../images/i_msg-success.gif); color:#3d6611; }
.note-msg,
.notice-msg { border-color:#fcd344; background-color:#fafaec; background-
image:url(../images/i_msg-note.gif); color:#3d6611; }
.notice-msg-propio { border-color:#fcd344; background-color:#fafaec;
background-image:url(../images/i_msg-note.gif); color:#3d6611; }
Nota: Las líneas en castellano debemos borrarlas si no, nos dará error de sintáxis. Las líneas están
simplemente para indicar que hace cada bloque de código.
Guardamos este fichero y desde la consola ejecutamos lo siguiente:
mysql -u nombre_usuario -p nombre_base_de_datos < borra_ordenes.sql
Cuando vuelvas a entrar en tu cuenta de cliente o como administrador verás que no hay pedidos, y en el
panel de administración los importes están a cero.
Ahora buscamos foreach ($_shippingRateGroups as $code => $_rates): ?> que estará justo debajo
de lo que acabamos de añadir y que si estamos en la versión 1.4 de Magento la línea aparece tal que así:
<?php $_sole = count($_shippingRateGroups) == 1; foreach
($_shippingRateGroups as $code => $_rates): ?>
Bien, pues justo debajo de esto añadimos dos líneas más quedando tal que así:
<?php $_sole = count($_shippingRateGroups) == 1; foreach
($_shippingRateGroups as $code => $_rates): ?>
<?php /* Added 2 lines here */ ?>
<?php if($this->getCarrierName($code)=='Transporte Gratis')
$freeshipping_available_flag=1;?>
<?php if(($this->getCarrierName($code)=='Tarifa Plana') and
($freeshipping_available_flag)) continue; ?>
<dt><?php echo $this->getCarrierName($code) ?></dt>
Ahora cuando el pedido supere el importe marcado para el envío gratuito sólo nos aparece este método y no
ambos.
En este mismo post dice que cambiando determinada línea el botón de chequeo del método de envío nos
aparecerá marcado, pero a mi no me ha funcionado. Este método consiste en sustituir la línea:
<input name="shipping_method" type="radio" value="<?php echo $_rate-
>getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if($_rate-
>getCode()===$this->getAddressShippingMethod()) echo ' checked="checked"' ?>
class="radio" />
Por:
<input name="shipping_method" type="radio" value="<?php echo $_rate-
>getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if(($_rate-
>getCode()===$this->getAddressShippingMethod()) or ($_rate->getMethodTitle()
== 'Transporte Gratis')) echo ' checked="checked"'?> class="radio" />
Si alguien sabe dónde está el error o como hacerlo para que así sea, pues que contribuya.