diff --git a/.htaccess b/.htaccess index 7417c20ce1..546f18e6f3 100644 --- a/.htaccess +++ b/.htaccess @@ -55,10 +55,10 @@ # disable user agent verification to not break multiple image upload php_flag suhosin.session.cryptua off - + ########################################### # turn off compatibility with PHP4 when dealing with objects - + php_flag zend.ze1_compatibility_mode Off @@ -77,8 +77,10 @@ ## enable apache served files compression ## http://developer.yahoo.com/performance/rules.html#gzip - # Insert filter - #SetOutputFilter DEFLATE + # Insert filter on all content + ###SetOutputFilter DEFLATE + # Insert filter on selected content types only + #AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript # Netscape 4.x has some problems... #BrowserMatch ^Mozilla/4 gzip-only-text/html @@ -88,6 +90,7 @@ # MSIE masquerades as Netscape, but it is fine #BrowserMatch \bMSIE !no-gzip !gzip-only-text/html + # Don't compress images #SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary diff --git a/.htaccess.sample b/.htaccess.sample index 9148669894..92b1f11404 100644 --- a/.htaccess.sample +++ b/.htaccess.sample @@ -54,12 +54,12 @@ # disable user agent verification to not break multiple image upload php_flag suhosin.session.cryptua off - + ########################################### # turn off compatibility with PHP4 when dealing with objects - + php_flag zend.ze1_compatibility_mode Off - + @@ -76,8 +76,10 @@ ## enable apache served files compression ## http://developer.yahoo.com/performance/rules.html#gzip - # Insert filter - #SetOutputFilter DEFLATE + # Insert filter on all content + ###SetOutputFilter DEFLATE + # Insert filter on selected content types only + #AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript # Netscape 4.x has some problems... #BrowserMatch ^Mozilla/4 gzip-only-text/html @@ -87,6 +89,7 @@ # MSIE masquerades as Netscape, but it is fine #BrowserMatch \bMSIE !no-gzip !gzip-only-text/html + # Don't compress images #SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary diff --git a/app/Mage.php b/app/Mage.php index bc4fd43fd2..4720e398ae 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -82,7 +82,7 @@ final class Mage { public static function getVersion() { - return '1.2.1.2'; + return '1.3.0'; } /** diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Permissions/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/Permissions/Collection.php index 28787e916d..b3db9126de 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Permissions/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Permissions/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Role.php b/app/code/core/Mage/Admin/Model/Mysql4/Role.php index 35885b2c81..2d39c87658 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Role.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Role.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Role/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/Role/Collection.php index 765743abbe..fe66c06821 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Role/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Role/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ @@ -35,7 +35,7 @@ protected function _construct() * Enter description here... * * @param int $userId - * @return Mage_Permissions_Model_Mysql4_Role_Collection + * @return Mage_Admin_Model_Mysql4_Role_Collection */ public function setUserFilter($userId) { diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Roles.php b/app/code/core/Mage/Admin/Model/Mysql4/Roles.php index 4160cf8db3..d6ecda18ce 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Roles.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Roles.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Roles/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/Roles/Collection.php index d2641a4813..42e25e5e01 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Roles/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Roles/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Roles/User/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/Roles/User/Collection.php index 5cd3e18da0..aaea32e672 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Roles/User/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Roles/User/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Rules.php b/app/code/core/Mage/Admin/Model/Mysql4/Rules.php index 7bf87e1fc4..257dde77b3 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Rules.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Rules.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/Rules/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/Rules/Collection.php index 484147ca24..9b1c0bbd65 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/Rules/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/Rules/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Mysql4/User.php b/app/code/core/Mage/Admin/Model/Mysql4/User.php index 4fb8586563..3c7061ff7c 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/User.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/User.php @@ -201,7 +201,7 @@ public function _saveRelations(Mage_Core_Model_Abstract $user) } } - public function _getRoles(Mage_Core_Model_Abstract $user) + public function getRoles(Mage_Core_Model_Abstract $user) { if ( !$user->getId() ) { return array(); diff --git a/app/code/core/Mage/Admin/Model/Mysql4/User/Collection.php b/app/code/core/Mage/Admin/Model/Mysql4/User/Collection.php index 8a1d0d920e..d63c4d8e9a 100644 --- a/app/code/core/Mage/Admin/Model/Mysql4/User/Collection.php +++ b/app/code/core/Mage/Admin/Model/Mysql4/User/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Observer.php b/app/code/core/Mage/Admin/Model/Observer.php index 6565c54508..a205c1d872 100644 --- a/app/code/core/Mage/Admin/Model/Observer.php +++ b/app/code/core/Mage/Admin/Model/Observer.php @@ -55,7 +55,13 @@ public function actionPreDispatchAdmin($event) $user = $session->login($username, $password, $request); } if (!$request->getParam('forwarded')) { - if($request->getParam('isAjax')) { + if ($request->getParam('isIframe')) { + $request->setParam('forwarded', true) + ->setControllerName('index') + ->setActionName('deniedIframe') + ->setDispatched(false); + } + elseif($request->getParam('isAjax')) { $request->setParam('forwarded', true) ->setControllerName('index') ->setActionName('deniedJson') diff --git a/app/code/core/Mage/Admin/Model/Role.php b/app/code/core/Mage/Admin/Model/Role.php index 13ca2cf0ec..2bbdd57691 100644 --- a/app/code/core/Mage/Admin/Model/Role.php +++ b/app/code/core/Mage/Admin/Model/Role.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Roles.php b/app/code/core/Mage/Admin/Model/Roles.php index 365df4c486..1902ee42f9 100644 --- a/app/code/core/Mage/Admin/Model/Roles.php +++ b/app/code/core/Mage/Admin/Model/Roles.php @@ -26,6 +26,11 @@ class Mage_Admin_Model_Roles extends Mage_Core_Model_Abstract { + /** + * @var string + */ + protected $_eventPrefix = 'admin_roles'; + protected function _construct() { $this->_init('admin/roles'); diff --git a/app/code/core/Mage/Admin/Model/Rules.php b/app/code/core/Mage/Admin/Model/Rules.php index 5708897a6d..8feb518229 100644 --- a/app/code/core/Mage/Admin/Model/Rules.php +++ b/app/code/core/Mage/Admin/Model/Rules.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Admin * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Admin/Model/Session.php b/app/code/core/Mage/Admin/Model/Session.php index 5e80ac643c..d6a5d1e391 100644 --- a/app/code/core/Mage/Admin/Model/Session.php +++ b/app/code/core/Mage/Admin/Model/Session.php @@ -1,182 +1,197 @@ - - */ -class Mage_Admin_Model_Session extends Mage_Core_Model_Session_Abstract -{ - - /** - * Whether it is the first page after successfull login - * - * @var boolean - */ - protected $_isFirstPageAfterLogin; - - /** - * Class constructor - * - */ - public function __construct() - { - $this->init('admin'); - } - - /** - * Try to login user in admin - * - * @param string $username - * @param string $password - * @param Mage_Core_Controller_Request_Http $request - * @return Mage_Admin_Model_User|null - */ - public function login($username, $password, $request=null) - { - if (empty($username) || empty($password)) { - return; - } - - $user = Mage::getModel('admin/user')->login($username, $password); - if ( $user->getId() && $user->getIsActive() != '1' ) { - if ($request && !$request->getParam('messageSent')) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Your Account has been deactivated.')); - $request->setParam('messageSent', true); - } - } elseif (!Mage::getModel('admin/user')->hasAssigned2Role($user->getId())) { - if ($request && !$request->getParam('messageSent')) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Access Denied.')); - $request->setParam('messageSent', true); - } - } else { - if ($user->getId()) { - $session = Mage::getSingleton('admin/session'); - $session->setIsFirstVisit(true); - $session->setUser($user); - $session->setAcl(Mage::getResourceModel('admin/acl')->loadAcl()); - if ($request) { - header('Location: ' . $request->getRequestUri()); - exit; - } - - } else { - if ($request && !$request->getParam('messageSent')) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Invalid Username or Password.')); - $request->setParam('messageSent', true); - } - } - } - return $user; - } - - /** - * Refresh ACL resources stored in session - * - * @param Mage_Admin_Model_User $user - * @return Mage_Admin_Model_Session - */ - public function refreshAcl($user=null) - { - if (is_null($user)) { - $user = $this->getUser(); - } - if (!$user) { - return $this; - } - if (!$this->getAcl() || $user->getReloadAclFlag()) { - $this->setAcl(Mage::getResourceModel('admin/acl')->loadAcl()); - } - if ($user->getReloadAclFlag()) { - $user->unsetData('password'); - $user->setReloadAclFlag('0')->save(); - } - return $this; - } - - /** - * Check current user permission on resource and privilege - * - * Mage::getSingleton('admin/session')->isAllowed('admin/catalog') - * Mage::getSingleton('admin/session')->isAllowed('catalog') - * - * @param string $resource - * @param string $privilege - * @return boolean - */ - public function isAllowed($resource, $privilege=null) - { - $user = $this->getUser(); - $acl = $this->getAcl(); - - if ($user && $acl) { - if (!preg_match('/^admin/', $resource)) { - $resource = 'admin/'.$resource; - } - - try { - if ($acl->isAllowed($user->getAclRole(), 'all', null)){ - return true; - } - } catch (Exception $e) {} - - try { - return $acl->isAllowed($user->getAclRole(), $resource, $privilege); - } catch (Exception $e) { - return false; - } - } - return false; - } - - /** - * Check if user is logged in - * - * @return boolean - */ - public function isLoggedIn() - { - return $this->getUser() && $this->getUser()->getId(); - } - - /** - * Check if it is the first page after successfull login - * - * @return boolean - */ - public function isFirstPageAfterLogin() - { - if (is_null($this->_isFirstPageAfterLogin)) { - $this->_isFirstPageAfterLogin = $this->getData('is_first_visit', true); - } - return $this->_isFirstPageAfterLogin; - } - + + */ +class Mage_Admin_Model_Session extends Mage_Core_Model_Session_Abstract +{ + + /** + * Whether it is the first page after successfull login + * + * @var boolean + */ + protected $_isFirstPageAfterLogin; + + /** + * Class constructor + * + */ + public function __construct() + { + $this->init('admin'); + } + + /** + * Try to login user in admin + * + * @param string $username + * @param string $password + * @param Mage_Core_Controller_Request_Http $request + * @return Mage_Admin_Model_User|null + */ + public function login($username, $password, $request = null) + { + if (empty($username) || empty($password)) { + return; + } + + try { + /* @var $user Mage_Admin_Model_User */ + $user = Mage::getModel('admin/user'); + $user->login($username, $password); + if ($user->getId()) { + if (Mage::getSingleton('adminhtml/url')->useSecretKey()) { + Mage::getSingleton('adminhtml/url')->renewSecretUrls(); + } + $session = Mage::getSingleton('admin/session'); + $session->setIsFirstVisit(true); + $session->setUser($user); + $session->setAcl(Mage::getResourceModel('admin/acl')->loadAcl()); + if ($requestUri = $this->_getRequestUri($request)) { + header('Location: ' . $requestUri); + exit; + } + } + else { + Mage::throwException(Mage::helper('adminhtml')->__('Invalid Username or Password.')); + } + } + catch (Mage_Core_Exception $e) { + if ($request && !$request->getParam('messageSent')) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + $request->setParam('messageSent', true); + } + } + + return $user; + } + + /** + * Refresh ACL resources stored in session + * + * @param Mage_Admin_Model_User $user + * @return Mage_Admin_Model_Session + */ + public function refreshAcl($user=null) + { + if (is_null($user)) { + $user = $this->getUser(); + } + if (!$user) { + return $this; + } + if (!$this->getAcl() || $user->getReloadAclFlag()) { + $this->setAcl(Mage::getResourceModel('admin/acl')->loadAcl()); + } + if ($user->getReloadAclFlag()) { + $user->unsetData('password'); + $user->setReloadAclFlag('0')->save(); + } + return $this; + } + + /** + * Check current user permission on resource and privilege + * + * Mage::getSingleton('admin/session')->isAllowed('admin/catalog') + * Mage::getSingleton('admin/session')->isAllowed('catalog') + * + * @param string $resource + * @param string $privilege + * @return boolean + */ + public function isAllowed($resource, $privilege=null) + { + $user = $this->getUser(); + $acl = $this->getAcl(); + + if ($user && $acl) { + if (!preg_match('/^admin/', $resource)) { + $resource = 'admin/'.$resource; + } + + try { + if ($acl->isAllowed($user->getAclRole(), 'all', null)){ + return true; + } + } catch (Exception $e) {} + + try { + return $acl->isAllowed($user->getAclRole(), $resource, $privilege); + } catch (Exception $e) { + return false; + } + } + return false; + } + + /** + * Check if user is logged in + * + * @return boolean + */ + public function isLoggedIn() + { + return $this->getUser() && $this->getUser()->getId(); + } + + /** + * Check if it is the first page after successfull login + * + * @return boolean + */ + public function isFirstPageAfterLogin() + { + if (is_null($this->_isFirstPageAfterLogin)) { + $this->_isFirstPageAfterLogin = $this->getData('is_first_visit', true); + } + return $this->_isFirstPageAfterLogin; + } + + /** + * Custom REQUEST_URI logic + * + * @param Mage_Core_Controller_Request_Http $request + * @return string|null + */ + protected function _getRequestUri($request = null) + { + if (Mage::getSingleton('adminhtml/url')->useSecretKey()) { + return Mage::getSingleton('adminhtml/url')->getUrl('*/*/*', array('_current' => true)); + } elseif ($request) { + return $request->getRequestUri(); + } else { + return null; + } + } } \ No newline at end of file diff --git a/app/code/core/Mage/Admin/Model/User.php b/app/code/core/Mage/Admin/Model/User.php index b80af6f995..3ac0b2878c 100644 --- a/app/code/core/Mage/Admin/Model/User.php +++ b/app/code/core/Mage/Admin/Model/User.php @@ -1,307 +1,364 @@ - - */ -class Mage_Admin_Model_User extends Mage_Core_Model_Abstract -{ - - const XML_PATH_FORGOT_EMAIL_TEMPLATE = 'admin/emails/forgot_email_template'; - const XML_PATH_FORGOT_EMAIL_IDENTITY = 'admin/emails/forgot_email_identity'; - const XML_PATH_STARTUP_PAGE = 'admin/startup/page'; - - /** - * Varien constructor - */ - protected function _construct() - { - $this->_init('admin/user'); - } - - /** - * Save user - * - * @return Mage_Admin_Model_User - */ - public function save() - { - $data = array( - 'firstname' => $this->getFirstname(), - 'lastname' => $this->getLastname(), - 'email' => $this->getEmail(), - 'modified' => now(), - 'extra' => serialize($this->getExtra()) - ); - - if($this->getId() > 0) { - $data['user_id'] = $this->getId(); - } - - if( $this->getUsername() ) { - $data['username'] = $this->getUsername(); - } - - if ($this->getPassword()) { - $data['password'] = $this->_getEncodedPassword($this->getPassword()); - } - - if ($this->getNewPassword()) { - $data['password'] = $this->_getEncodedPassword($this->getNewPassword()); - } - - if ( !is_null($this->getIsActive()) ) { - $data['is_active'] = intval($this->getIsActive()); - } - - $this->setData($data); - $this->_getResource()->save($this); - return $this; - } - - /** - * Delete user - * - * @return Mage_Admin_Model_User - */ - public function delete() - { - $this->_getResource()->delete($this); - return $this; - } - - /** - * Save user roles - * - * @return Mage_Admin_Model_User - */ - public function saveRelations() - { - $this->_getResource()->_saveRelations($this); - return $this; - } - - public function getRoles() - { - return $this->_getResource()->_getRoles($this); - } - - public function deleteFromRole() - { - $this->_getResource()->deleteFromRole($this); - return $this; - } - - public function roleUserExists() - { - $result = $this->_getResource()->roleUserExists($this); - return ( is_array($result) && count($result) > 0 ) ? true : false; - } - - public function add() - { - $this->_getResource()->add($this); - return $this; - } - - public function userExists() - { - $result = $this->_getResource()->userExists($this); - return ( is_array($result) && count($result) > 0 ) ? true : false; - } - - public function getCollection() { - return Mage::getResourceModel('admin/user_collection'); - } - - /** - * Send email with new user password - * - * @return Mage_Admin_Model_User - */ - public function sendNewPasswordEmail() - { - $translate = Mage::getSingleton('core/translate'); - /* @var $translate Mage_Core_Model_Translate */ - $translate->setTranslateInline(false); - - Mage::getModel('core/email_template') - ->setDesignConfig(array('area' => 'adminhtml', 'store' => $this->getStoreId())) - ->sendTransactional( - Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_TEMPLATE), - Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_IDENTITY), - $this->getEmail(), - $this->getName(), - array('user' => $this, 'password' => $this->getPlainPassword())); - - $translate->setTranslateInline(true); - - return $this; - } - - public function getName($separator=' ') - { - return $this->getFirstname() . $separator . $this->getLastname(); - } - - public function getId() - { - return $this->getUserId(); - } - - /** - * Get user ACL role - * - * @return string - */ - public function getAclRole() - { - return 'U' . $this->getUserId(); - } - - /** - * Authenticate user name and password and save loaded record - * - * @param string $username - * @param string $password - * @return boolean - */ - public function authenticate($username, $password) - { - $this->loadByUsername($username); - if (!$this->getId()) { - return false; - } - $auth = Mage::helper('core')->validateHash($password, $this->getPassword()); - if ($auth) { - return true; - } else { - $this->unsetData(); - return false; - } - } - - /** - * Login user - * - * @param string $login - * @param string $password - * @return Mage_Admin_Model_User - */ - public function login($username, $password) - { - if ($this->authenticate($username, $password)) { - $this->getResource()->recordLogin($this); - } - - return $this; - } - - public function reload() - { - $id = $this->getId(); - $this->setId(null); - $this->load($id); - return $this; - } - - public function loadByUsername($username) - { - $this->setData($this->getResource()->loadByUsername($username)); - return $this; - } - - public function hasAssigned2Role($user) - { - return $this->getResource()->hasAssigned2Role($user); - } - - protected function _getEncodedPassword($pwd) - { - return Mage::helper('core')->getHash($pwd, 2); - } - - /** - * Find first menu item that user is able to access - * - * @param Mage_Core_Model_Config_Element $parent - * @param string $path - * @param integer $level - * @return string - */ - public function findFirstAvailableMenu($parent=null, $path='', $level=0) - { - if ($parent == null) { - $parent = Mage::getConfig()->getNode('adminhtml/menu'); - } - foreach ($parent->children() as $childName=>$child) { - $aclResource = 'admin/' . $path . $childName; - if (Mage::getSingleton('admin/session')->isAllowed($aclResource)) { - if (!$child->children) { - return (string)$child->action; - } else if ($child->children) { - $action = $this->findFirstAvailableMenu($child->children, $path . $childName . '/', $level+1); - return $action ? $action : (string)$child->action; - } - } - } - } - - /** - * Find admin start page url - * - * @deprecated Please use getStartupPageUrl() method instead - * @see getStartupPageUrl() - * @return string - */ - public function getStatrupPageUrl() - { - return $this->getStartupPageUrl(); - } - - /** - * Find admin start page url - * - * @return string - */ - public function getStartupPageUrl() - { - $startupPage = Mage::getStoreConfig(self::XML_PATH_STARTUP_PAGE); - $aclResource = 'admin/' . $startupPage; - if (Mage::getSingleton('admin/session')->isAllowed($aclResource)) { - $nodePath = 'adminhtml/menu/' . join('/children/', split('/', $startupPage)) . '/action'; - if ($url = Mage::getConfig()->getNode($nodePath)) { - return $url; - } - } - return $this->findFirstAvailableMenu(); - } - -} + + */ +class Mage_Admin_Model_User extends Mage_Core_Model_Abstract +{ + const XML_PATH_FORGOT_EMAIL_TEMPLATE = 'admin/emails/forgot_email_template'; + const XML_PATH_FORGOT_EMAIL_IDENTITY = 'admin/emails/forgot_email_identity'; + const XML_PATH_STARTUP_PAGE = 'admin/startup/page'; + + protected $_eventPrefix = 'admin_user'; + + /** + * @var Mage_Admin_Model_Roles + */ + protected $_role; + + /** + * Varien constructor + */ + protected function _construct() + { + $this->_init('admin/user'); + } + + /** + * Save user + * + * @return Mage_Admin_Model_User + */ + public function save() + { + $this->_beforeSave(); + $data = array( + 'firstname' => $this->getFirstname(), + 'lastname' => $this->getLastname(), + 'email' => $this->getEmail(), + 'modified' => now(), + 'extra' => serialize($this->getExtra()) + ); + + if($this->getId() > 0) { + $data['user_id'] = $this->getId(); + } + + if( $this->getUsername() ) { + $data['username'] = $this->getUsername(); + } + + if ($this->getPassword()) { + $data['password'] = $this->_getEncodedPassword($this->getPassword()); + } + + if ($this->getNewPassword()) { + $data['password'] = $this->_getEncodedPassword($this->getNewPassword()); + } + elseif ($this->getPassword()) { + $data['new_password'] = $this->getPassword(); + } + + if ( !is_null($this->getIsActive()) ) { + $data['is_active'] = intval($this->getIsActive()); + } + + $this->addData($data); + $this->_getResource()->save($this); + $this->_afterSave(); + return $this; + } + + /** + * Delete user + * + * @return Mage_Admin_Model_User + */ + public function delete() + { + $this->_getResource()->delete($this); + return $this; + } + + /** + * Save user roles + * + * @return Mage_Admin_Model_User + */ + public function saveRelations() + { + $this->_getResource()->_saveRelations($this); + return $this; + } + + public function getRoles() + { + return $this->_getResource()->getRoles($this); + } + + /** + * Get admin role model + * + * @return Mage_Admin_Model_Roles + */ + public function getRole() + { + if (null === $this->_role) { + $this->_role = Mage::getModel('admin/roles'); + $roles = $this->getRoles(); + if ($roles && isset($roles[0]) && $roles[0]) { + $this->_role->load($roles[0]); + } + } + return $this->_role; + } + + public function deleteFromRole() + { + $this->_getResource()->deleteFromRole($this); + return $this; + } + + public function roleUserExists() + { + $result = $this->_getResource()->roleUserExists($this); + return ( is_array($result) && count($result) > 0 ) ? true : false; + } + + public function add() + { + $this->_getResource()->add($this); + return $this; + } + + public function userExists() + { + $result = $this->_getResource()->userExists($this); + return ( is_array($result) && count($result) > 0 ) ? true : false; + } + + public function getCollection() { + return Mage::getResourceModel('admin/user_collection'); + } + + /** + * Send email with new user password + * + * @return Mage_Admin_Model_User + */ + public function sendNewPasswordEmail() + { + $translate = Mage::getSingleton('core/translate'); + /* @var $translate Mage_Core_Model_Translate */ + $translate->setTranslateInline(false); + + Mage::getModel('core/email_template') + ->setDesignConfig(array('area' => 'adminhtml', 'store' => $this->getStoreId())) + ->sendTransactional( + Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_TEMPLATE), + Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_IDENTITY), + $this->getEmail(), + $this->getName(), + array('user' => $this, 'password' => $this->getPlainPassword())); + + $translate->setTranslateInline(true); + + return $this; + } + + public function getName($separator=' ') + { + return $this->getFirstname() . $separator . $this->getLastname(); + } + + public function getId() + { + return $this->getUserId(); + } + + /** + * Get user ACL role + * + * @return string + */ + public function getAclRole() + { + return 'U' . $this->getUserId(); + } + + /** + * Authenticate user name and password and save loaded record + * + * @param string $username + * @param string $password + * @return boolean + * @throws Mage_Core_Exception + */ + public function authenticate($username, $password) + { + $result = false; + try { + $this->loadByUsername($username); + if ($this->getId()) { + if ($this->getIsActive() != '1') { + Mage::throwException(Mage::helper('adminhtml')->__('This account is inactive.')); + } + if (Mage::helper('core')->validateHash($password, $this->getPassword())) { + $result = true; + } + } + + Mage::dispatchEvent('admin_user_authenticated', array( + 'username' => $username, + 'password' => $password, + 'user' => $this, + 'result' => $result, + )); + + if (!$this->hasAssigned2Role($this->getId())) { + Mage::throwException(Mage::helper('adminhtml')->__('Access Denied.')); + } + } + catch (Mage_Core_Exception $e) { + $this->unsetData(); + throw $e; + } + + if (!$result) { + $this->unsetData(); + } + return $result; + } + + /** + * Login user + * + * @param string $login + * @param string $password + * @return Mage_Admin_Model_User + */ + public function login($username, $password) + { + if ($this->authenticate($username, $password)) { + $this->getResource()->recordLogin($this); + } + + // dispatch event regardless the user was logged in or not + Mage::dispatchEvent('admin_user_on_login', array( + 'user' => $this, + 'username' => $username, + 'password' => $password, + )); + + return $this; + } + + public function reload() + { + $id = $this->getId(); + $this->setId(null); + $this->load($id); + return $this; + } + + public function loadByUsername($username) + { + $this->setData($this->getResource()->loadByUsername($username)); + return $this; + } + + public function hasAssigned2Role($user) + { + return $this->getResource()->hasAssigned2Role($user); + } + + protected function _getEncodedPassword($pwd) + { + return Mage::helper('core')->getHash($pwd, 2); + } + + /** + * Find first menu item that user is able to access + * + * @param Mage_Core_Model_Config_Element $parent + * @param string $path + * @param integer $level + * @return string + */ + public function findFirstAvailableMenu($parent=null, $path='', $level=0) + { + if ($parent == null) { + $parent = Mage::getConfig()->getNode('adminhtml/menu'); + } + foreach ($parent->children() as $childName=>$child) { + $aclResource = 'admin/' . $path . $childName; + if (Mage::getSingleton('admin/session')->isAllowed($aclResource)) { + if (!$child->children) { + return (string)$child->action; + } else if ($child->children) { + $action = $this->findFirstAvailableMenu($child->children, $path . $childName . '/', $level+1); + return $action ? $action : (string)$child->action; + } + } + } + } + + /** + * Find admin start page url + * + * @deprecated Please use getStartupPageUrl() method instead + * @see getStartupPageUrl() + * @return string + */ + public function getStatrupPageUrl() + { + return $this->getStartupPageUrl(); + } + + /** + * Find admin start page url + * + * @return string + */ + public function getStartupPageUrl() + { + $startupPage = Mage::getStoreConfig(self::XML_PATH_STARTUP_PAGE); + $aclResource = 'admin/' . $startupPage; + if (Mage::getSingleton('admin/session')->isAllowed($aclResource)) { + $nodePath = 'adminhtml/menu/' . join('/children/', split('/', $startupPage)) . '/action'; + if ($url = Mage::getConfig()->getNode($nodePath)) { + return $url; + } + } + return $this->findFirstAvailableMenu(); + } + +} diff --git a/app/code/core/Mage/Admin/etc/config.xml b/app/code/core/Mage/Admin/etc/config.xml index 57c90f8e71..b3ff73d82a 100644 --- a/app/code/core/Mage/Admin/etc/config.xml +++ b/app/code/core/Mage/Admin/etc/config.xml @@ -78,4 +78,14 @@ + + + + + + admin.xml + + + + diff --git a/app/code/core/Mage/AdminNotification/Model/Feed.php b/app/code/core/Mage/AdminNotification/Model/Feed.php index b87ffbcd65..3da312a056 100644 --- a/app/code/core/Mage/AdminNotification/Model/Feed.php +++ b/app/code/core/Mage/AdminNotification/Model/Feed.php @@ -80,7 +80,8 @@ public function checkUpdate() $feedData = array(); - if ($feedXml = $this->getFeedData()) { + $feedXml = $this->getFeedData(); + if ($feedXml && $feedXml->channel && $feedXml->channel->item) { foreach ($feedXml->channel->item as $item) { $feedData[] = array( 'severity' => (int)$item->severity, diff --git a/app/code/core/Mage/Adminhtml/Block/Backup/Grid.php b/app/code/core/Mage/Adminhtml/Block/Backup/Grid.php index e576b926a1..a18c7214f6 100644 --- a/app/code/core/Mage/Adminhtml/Block/Backup/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Backup/Grid.php @@ -58,8 +58,6 @@ protected function _prepareColumns() { $url7zip = Mage::helper('adminhtml')->__('The archive can be uncompressed with %s on Windows systems', 'http://www.7-zip.org/', '7-Zip'); - $gridUrl = $this->getUrl('*/*/'); - $this->addColumn('time', array( 'header' => Mage::helper('backup')->__('Time'), 'index' => 'time_formated', @@ -83,7 +81,7 @@ protected function _prepareColumns() $this->addColumn('download', array( 'header' => Mage::helper('backup')->__('Download'), - 'format' => 'gz   ('.$url7zip.')', + 'format' => 'gz   ('.$url7zip.')', 'index' => 'type', 'sortable' => false, 'filter' => false @@ -96,7 +94,7 @@ protected function _prepareColumns() 'filter' => false, 'sortable' => false, 'actions' => array(array( - 'url' => $gridUrl .'delete/time/$time/type/$type/', + 'url' => $this->getUrl('*/*/delete', array('time' => '$time', 'type' => '$type')), 'caption' => Mage::helper('adminhtml')->__('Delete'), 'confirm' => Mage::helper('adminhtml')->__('Are you sure you want to do this?') )), diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit/Form.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit/Form.php index eec0ad7b72..20c6342cf4 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit/Form.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit/Form.php @@ -33,6 +33,13 @@ */ class Mage_Adminhtml_Block_Catalog_Category_Edit_Form extends Mage_Adminhtml_Block_Catalog_Category_Abstract { + /** + * Additional buttons on category page + * + * @var array + */ + protected $_additionalButtons = array(); + public function __construct() { parent::__construct(); @@ -107,6 +114,51 @@ public function getResetButtonHtml() return ''; } + /** + * Retrieve additional buttons html + * + * @return string + */ + public function getAdditionalButtonsHtml() + { + $html = ''; + foreach ($this->_additionalButtons as $childName) { + $html .= $this->getChildHtml($childName); + } + return $html; + } + + /** + * Add additional button + * + * @param string $alias + * @param array $config + * @return Mage_Adminhtml_Block_Catalog_Category_Edit_Form + */ + public function addAdditionalButton($alias, $config) + { + $this->setChild($alias . '_button', + $this->getLayout()->createBlock('adminhtml/widget_button')->addData($config)); + $this->_additionalButtons[$alias] = $alias . '_button'; + return $this; + } + + /** + * Remove additional button + * + * @param string $alias + * @return Mage_Adminhtml_Block_Catalog_Category_Edit_Form + */ + public function removeAdditionalButton($alias) + { + if (isset($this->_additionalButtons[$alias])) { + $this->unsetChild($this->_additionalButtons[$alias]); + unset($this->_additionalButtons[$alias]); + } + + return $this; + } + public function getTabsHtml() { return $this->getChildHtml('tabs'); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Available.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Available.php new file mode 100644 index 0000000000..81b923f3c8 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Available.php @@ -0,0 +1,63 @@ + + */ +class Mage_Adminhtml_Block_Catalog_Category_Helper_Sortby_Available + extends Varien_Data_Form_Element_Multiselect +{ +/** + * Retrieve Element HTML fragment + * + * @return string + */ + public function getElementHtml() + { + $disabled = false; + if (!$this->getValue()) { + $this->setData('disabled', 'disabled'); + $disabled = true; + } + $html = parent::getElementHtml(); + + $htmlId = 'use_config_' . $this->getHtmlId(); + $html .= '' + . Mage::helper('adminhtml')->__('Use Config Settings').''; + $html .= ''; + + return $html; + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Default.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Default.php new file mode 100644 index 0000000000..b4ab5e89f5 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Helper/Sortby/Default.php @@ -0,0 +1,63 @@ + + */ +class Mage_Adminhtml_Block_Catalog_Category_Helper_Sortby_Default + extends Varien_Data_Form_Element_Select +{ + /** + * Retrieve Element HTML fragment + * + * @return string + */ + public function getElementHtml() + { + $disabled = false; + if (!$this->getValue()) { + $this->setData('disabled', 'disabled'); + $disabled = true; + } + $html = parent::getElementHtml(); + + $htmlId = 'use_config_' . $this->getHtmlId(); + $html .= '' + . Mage::helper('adminhtml')->__('Use Config Settings').''; + $html .= ''; + + return $html; + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Attributes.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Attributes.php new file mode 100644 index 0000000000..9b401aa1da --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Attributes.php @@ -0,0 +1,135 @@ + + */ +class Mage_Adminhtml_Block_Catalog_Category_Tab_Attributes extends Mage_Adminhtml_Block_Catalog_Form +{ + /** + * Retrieve Category object + * + * @return Mage_Catalog_Model_Category + */ + public function getCategory() + { + return Mage::registry('current_category'); + } + + /** + * Initialize tab + * + */ + public function __construct() { + parent::__construct(); + $this->setShowGlobalIcon(true); + } + + /** + * Prepare form before rendering HTML + * + * @return Mage_Adminhtml_Block_Catalog_Category_Tab_Attributes + */ + protected function _prepareForm() { + $group = $this->getGroup(); + $attributes = $this->getAttributes(); + + $form = new Varien_Data_Form(); + $form->setHtmlIdPrefix('group_' . $group->getId()); + $form->setDataObject($this->getCategory()); + + $fieldset = $form->addFieldset('fieldset_group_' . $group->getId(), array( + 'legend' => Mage::helper('catalog')->__($group->getAttributeGroupName()) + )); + + if ($this->getAddHiddenFields()) { + if (!$this->getCategory()->getId()) { + // path + if ($this->getRequest()->getParam('parent')) { + $fieldset->addField('path', 'hidden', array( + 'name' => 'path', + 'value' => $this->getRequest()->getParam('parent') + )); + } + else { + $fieldset->addField('path', 'hidden', array( + 'name' => 'path', + 'value' => 1 + )); + } + } + else { + $fieldset->addField('id', 'hidden', array( + 'name' => 'id', + 'value' => $this->getCategory()->getId() + )); + $fieldset->addField('path', 'hidden', array( + 'name' => 'path', + 'value' => $this->getCategory()->getPath() + )); + } + } + + $this->_setFieldset($attributes, $fieldset); + + foreach ($attributes as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if ($attribute->getAttributeCode() == 'url_key') { + if ($this->getCategory()->getLevel() == 1) { + $fieldset->removeField('url_key'); + $fieldset->addField('url_key', 'hidden', array( + 'name' => 'url_key', + 'value' => $this->getCategory()->getUrlKey() + )); + } + } + } + + $form->addValues($this->getCategory()->getData()); + + $form->setFieldNameSuffix('general'); + $this->setForm($form); + + return parent::_prepareForm(); + } + + /** + * Retrieve Additional Element Types + * + * @return array + */ + protected function _getAdditionalElementTypes() + { + return array( + 'image' => Mage::getConfig()->getBlockClassName('adminhtml/catalog_category_helper_image') + ); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php index cf87ba201a..9e4d576cb3 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php @@ -117,12 +117,13 @@ protected function _prepareColumns() $this->addColumn('price', array( 'header' => Mage::helper('catalog')->__('Price'), 'type' => 'currency', + 'width' => '1', 'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE), 'index' => 'price' )); $this->addColumn('position', array( 'header' => Mage::helper('catalog')->__('Position'), - 'width' => '70', + 'width' => '1', 'type' => 'number', 'index' => 'position', 'editable' => true diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php index bb04589528..71d9ed3e40 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php @@ -33,38 +33,128 @@ */ class Mage_Adminhtml_Block_Catalog_Category_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { + /** + * Default Attribute Tab Block + * + * @var string + */ + protected $_attributeTabBlock = 'adminhtml/catalog_category_tab_attributes'; + + /** + * Initialize Tabs + * + */ public function __construct() { parent::__construct(); $this->setId('category_info_tabs'); $this->setDestElementId('category_tab_content'); $this->setTitle(Mage::helper('catalog')->__('Category Data')); - $this->setTemplate('widget/tabshoriz.phtml'); + $this->setTemplate('widget/tabshoriz.phtml'); + } + + /** + * Retrieve cattegory object + * + * @return Mage_Catalog_Model_Category + */ + public function getCategory() + { + return Mage::registry('current_category'); + } - //$this->setDestElementId('category_tab_content'); + /** + * Return Adminhtml Catalog Helper + * + * @return Mage_Adminhtml_Helper_Catalog + */ + public function getCatalogHelper() + { + return Mage::helper('adminhtml/catalog'); + } + + /** + * Getting attribute block name for tabs + * + * @return string + */ + public function getAttributeTabBlock() + { + if ($block = $this->getCatalogHelper()->getCategoryAttributeTabBlock()) { + return $block; + } + return $this->_attributeTabBlock; } + /** + * Prepare Layout Content + * + * @return Mage_Adminhtml_Block_Catalog_Category_Tabs + */ protected function _prepareLayout() { - $this->addTab('general', array( - 'label' => Mage::helper('catalog')->__('General Information'), - 'content' => $this->getLayout()->createBlock('adminhtml/catalog_category_tab_general')->toHtml(), - 'active' => true - )); + $categoryAttributes = $this->getCategory()->getAttributes(); + $attributeSetId = $this->getCategory()->getDefaultAttributeSetId(); + $groupCollection = Mage::getResourceModel('eav/entity_attribute_group_collection') + ->setAttributeSetFilter($attributeSetId) + ->load(); + $defaultGroupId = 0; + foreach ($groupCollection as $group) { + /* @var $group Mage_Eav_Model_Entity_Attribute_Group */ + if ($defaultGroupId == 0 or $group->getIsDefault()) { + $defaultGroupId = $group->getId(); + } + } + + foreach ($groupCollection as $group) { + /* @var $group Mage_Eav_Model_Entity_Attribute_Group */ + $attributes = array(); + foreach ($categoryAttributes as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if ($attribute->isInGroup($attributeSetId, $group->getId())) { + $attributes[] = $attribute; + } + } + + // do not add grops without attributes + if (!$attributes) { + continue; + } + + $active = $defaultGroupId == $group->getId(); + $block = $this->getLayout()->createBlock($this->getAttributeTabBlock(), '') + ->setGroup($group) + ->setAttributes($attributes) + ->setAddHiddenFields($active) + ->toHtml(); + $this->addTab('group_' . $group->getId(), array( + 'label' => Mage::helper('catalog')->__($group->getAttributeGroupName()), + 'content' => $block, + 'active' => $active + )); + } + +// $this->addTab('general', array( +// 'label' => Mage::helper('catalog')->__('General Information'), +// 'content' => $this->getLayout()->createBlock('adminhtml/catalog_category_tab_general')->toHtml(), +// 'active' => true +// )); $this->addTab('products', array( 'label' => Mage::helper('catalog')->__('Category Products'), 'content' => $this->getLayout()->createBlock('adminhtml/catalog_category_tab_product', 'category.product.grid')->toHtml(), )); - $this->addTab('design', array( - 'label' => Mage::helper('catalog')->__('Custom Design'), - 'content' => $this->getLayout()->createBlock('adminhtml/catalog_category_tab_design')->toHtml(), + // dispatch event add custom tabs + Mage::dispatchEvent('adminhtml_catalog_category_tabs', array( + 'tabs' => $this )); - $category = Mage::registry('current_category'); + /** + * @todo Adding tab in observer + */ if (Mage::app()->getConfig()->getModuleConfig('Mage_GoogleOptimizer')->is('active', true) - && Mage::helper('googleoptimizer')->isOptimizerActive($category->getStoreId())) { + && Mage::helper('googleoptimizer')->isOptimizerActive($this->getCategory()->getStoreId())) { $this->addTab('googleoptimizer', array( 'label' => Mage::helper('googleoptimizer')->__('Category View Optimization'), 'content' => $this->getLayout()->createBlock('googleoptimizer/adminhtml_catalog_category_edit_tab_googleoptimizer')->toHtml(), diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php index ca047675a4..bbd83d4aac 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tree.php @@ -126,9 +126,6 @@ public function getCollapseButtonHtml() public function getStoreSwitcherHtml() { - if (Mage::app()->isSingleStoreMode()) { - return ''; - } return $this->getChildHtml('store_switcher'); } @@ -243,7 +240,9 @@ protected function _getNodeJson($node, $level = 0) //$item['allowDrop'] = ($level<3) ? true : false; $item['allowDrop'] = true; // disallow drag if it's first level and category is root of a store - $item['allowDrag'] = ($node->getLevel()==1 && $rootForStores) ? false : true; + $item['allowDrag'] = $this->_allowNodesDrag() + ? ($node->getLevel()==1 && $rootForStores) ? false : true + : false; if ((int)$node->getChildrenCount()>0) { $item['children'] = array(); @@ -282,6 +281,12 @@ public function buildNodeName($node) return $result; } + protected function _allowNodesDrag() + { + return true; + } + + protected function _isParentSelectedCategory($node) { if ($node && $this->getCategory()) { @@ -293,4 +298,14 @@ protected function _isParentSelectedCategory($node) return false; } + + /** + * Check if page loaded by outside link to category edit + * + * @return boolean + */ + public function isClearEdit() + { + return (bool) $this->getRequest()->getParam('clear'); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/DateFieldsOrder.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/DateFieldsOrder.php new file mode 100644 index 0000000000..68912b36a7 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/DateFieldsOrder.php @@ -0,0 +1,61 @@ + + */ +class Mage_Adminhtml_Block_Catalog_Form_Renderer_Config_DateFieldsOrder extends Mage_Adminhtml_Block_System_Config_Form_Field +{ + + protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) + { + $_options = array( + 'd' => Mage::helper('adminhtml')->__('Day'), + 'm' => Mage::helper('adminhtml')->__('Month'), + 'y' => Mage::helper('adminhtml')->__('Year') + ); + + $element->setValues($_options) + ->setStyle('width:70px;') + ->setName($element->getName() . '[]'); + if ($element->getValue()) { + $values = explode(',', $element->getValue()); + } else { + $values = array(); + } + + $_parts = array(); + $_parts[] = $element->setValue(isset($values[0]) ? $values[0] : null)->getElementHtml(); + $_parts[] = $element->setValue(isset($values[1]) ? $values[1] : null)->getElementHtml(); + $_parts[] = $element->setValue(isset($values[2]) ? $values[2] : null)->getElementHtml(); + + return implode(' / ', $_parts); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/YearRange.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/YearRange.php new file mode 100644 index 0000000000..dd366bd289 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Config/YearRange.php @@ -0,0 +1,54 @@ + + */ +class Mage_Adminhtml_Block_Catalog_Form_Renderer_Config_YearRange extends Mage_Adminhtml_Block_System_Config_Form_Field +{ + + protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) + { + $element->setStyle('width:70px;') + ->setName($element->getName() . '[]'); + + if ($element->getValue()) { + $values = explode(',', $element->getValue()); + } else { + $values = array(); + } + + $from = $element->setValue(isset($values[0]) ? $values[0] : null)->getElementHtml(); + $to = $element->setValue(isset($values[1]) ? $values[1] : null)->getElementHtml(); + return Mage::helper('adminhtml')->__('from') . ' ' . $from + . ' ' + . Mage::helper('adminhtml')->__('to') . ' ' . $to; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product.php index 9499888834..791eaeaec4 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product.php @@ -50,23 +50,17 @@ protected function _prepareLayout() 'class' => 'add' )) ); - /** - * Display store switcher if system has more one store - */ - if (!Mage::app()->isSingleStoreMode()) { - $this->setChild('store_switcher', - $this->getLayout()->createBlock('adminhtml/store_switcher') - ->setUseConfirm(false) - ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null))) - ); - } + $this->setChild('grid', $this->getLayout()->createBlock('adminhtml/catalog_product_grid', 'product.grid')); return parent::_prepareLayout(); } public function getAddNewButtonHtml() { - return $this->getChildHtml('add_new_button'); + if( $this->_enabledAddNewButton() ) { + return $this->getChildHtml('add_new_button'); + } + return ''; } public function getGridHtml() @@ -74,10 +68,17 @@ public function getGridHtml() return $this->getChildHtml('grid'); } - public function getStoreSwitcherHtml() + public function isSingleStoreMode() { - return $this->getChildHtml('store_switcher'); + if (!Mage::app()->isSingleStoreMode()) { + return false; + } + return true; } + protected function _enabledAddNewButton() + { + return true; + } } diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php index 99cb916ca8..4b01d01117 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php @@ -330,15 +330,6 @@ protected function _prepareForm() 'class' => 'validate-digits', )); -// if ($model->getIsUserDefined() || !$model->getId()) { - $fieldset->addField('is_visible_on_front', 'select', array( - 'name' => 'is_visible_on_front', - 'label' => Mage::helper('catalog')->__('Visible on Catalog Pages on Front-end'), - 'title' => Mage::helper('catalog')->__('Visible on Catalog Pages on Front-end'), - 'values' => $yesno, - )); -// } - $htmlAllowed = $fieldset->addField('is_html_allowed_on_front', 'select', array( 'name' => 'is_html_allowed_on_front', 'label' => Mage::helper('catalog')->__('Allow HTML-tags on Front-end'), @@ -349,6 +340,27 @@ protected function _prepareForm() $htmlAllowed->setValue(1); } + $fieldset->addField('is_visible_on_front', 'select', array( + 'name' => 'is_visible_on_front', + 'label' => Mage::helper('catalog')->__('Visible on Product View Page on Front-end'), + 'title' => Mage::helper('catalog')->__('Visible on Product View Page on Front-end'), + 'values' => $yesno, + )); + + $fieldset->addField('used_in_product_listing', 'select', array( + 'name' => 'used_in_product_listing', + 'label' => Mage::helper('catalog')->__('Used in product listing'), + 'title' => Mage::helper('catalog')->__('Used in product listing'), + 'note' => Mage::helper('catalog')->__('Depends on design theme'), + 'values' => $yesno, + )); + $fieldset->addField('used_for_sort_by', 'select', array( + 'name' => 'used_for_sort_by', + 'label' => Mage::helper('catalog')->__('Used for sorting in product listing'), + 'title' => Mage::helper('catalog')->__('Used for sorting in product listing'), + 'note' => Mage::helper('catalog')->__('Depends on design theme'), + 'values' => $yesno, + )); if ($model->getId()) { $form->getElement('attribute_code')->setDisabled(1); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Created.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Created.php index 4c9bd3c33b..606f30e16d 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Created.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Created.php @@ -1,152 +1,152 @@ - - */ -class Mage_Adminhtml_Block_Catalog_Product_Created extends Mage_Adminhtml_Block_Widget -{ - protected $_configurableProduct; - protected $_product; - - public function __construct() - { - parent::__construct(); - $this->setTemplate('catalog/product/created.phtml'); - } - - - protected function _prepareLayout() - { - $this->setChild( - 'close_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Close Window'), - 'onclick' => 'addProduct(true)' - )) - ); - } - - - public function getCloseButtonHtml() - { - return $this->getChildHtml('close_button'); - } - - public function getProductId() - { - return (int) $this->getRequest()->getParam('id'); - } - - /** - * Indentifies edit mode of popup - * - * @return boolean - */ - public function isEdit() - { - return (bool) $this->getRequest()->getParam('edit'); - } - - /** - * Retrive serialized json with configurable attributes values of simple - * - * @return string - */ - public function getAttributesJson() - { - $result = array(); - foreach ($this->getAttributes() as $attribute) { - $value = $this->getProduct()->getAttributeText($attribute->getAttributeCode()); - - $result[] = array( - 'label' => $value, - 'value_index' => $this->getProduct()->getData($attribute->getAttributeCode()), - 'attribute_id' => $attribute->getId() - ); - } - - return Zend_Json::encode($result); - } - - public function getAttributes() - { - if ($this->getConfigurableProduct()->getId()) { - return $this->getConfigurableProduct()->getTypeInstance()->getUsedProductAttributes(); - } - - $attributes = array(); - - $attributesIds = $this->getRequest()->getParam('required'); - if ($attributesIds) { - $attributesIds = explode(',', $attributesIds); - foreach ($attributesIds as $attributeId) { - $attribute = $this->getProduct()->getTypeInstance()->getAttributeById($attributeId); - if (!$attribute) { - continue; - } - $attributes[] = $attribute; - } - } - - return $attributes; - } - - /** - * Retrive configurable product for created/edited simple - * - * @return Mage_Catalog_Model_Product - */ - public function getConfigurableProduct() - { - if (is_null($this->_configurableProduct)) { - $this->_configurableProduct = Mage::getModel('catalog/product') - ->setStore(0) - ->load($this->getRequest()->getParam('product')); - } - return $this->_configurableProduct; - } - - /** - * Retrive product - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - if (is_null($this->_product)) { - $this->_product = Mage::getModel('catalog/product') - ->setStore(0) - ->load($this->getRequest()->getParam('id')); - } - return $this->_product; - } + + */ +class Mage_Adminhtml_Block_Catalog_Product_Created extends Mage_Adminhtml_Block_Widget +{ + protected $_configurableProduct; + protected $_product; + + public function __construct() + { + parent::__construct(); + $this->setTemplate('catalog/product/created.phtml'); + } + + + protected function _prepareLayout() + { + $this->setChild( + 'close_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Close Window'), + 'onclick' => 'addProduct(true)' + )) + ); + } + + + public function getCloseButtonHtml() + { + return $this->getChildHtml('close_button'); + } + + public function getProductId() + { + return (int) $this->getRequest()->getParam('id'); + } + + /** + * Indentifies edit mode of popup + * + * @return boolean + */ + public function isEdit() + { + return (bool) $this->getRequest()->getParam('edit'); + } + + /** + * Retrive serialized json with configurable attributes values of simple + * + * @return string + */ + public function getAttributesJson() + { + $result = array(); + foreach ($this->getAttributes() as $attribute) { + $value = $this->getProduct()->getAttributeText($attribute->getAttributeCode()); + + $result[] = array( + 'label' => $value, + 'value_index' => $this->getProduct()->getData($attribute->getAttributeCode()), + 'attribute_id' => $attribute->getId() + ); + } + + return Zend_Json::encode($result); + } + + public function getAttributes() + { + if ($this->getConfigurableProduct()->getId()) { + return $this->getConfigurableProduct()->getTypeInstance(true)->getUsedProductAttributes($this->getConfigurableProduct()); + } + + $attributes = array(); + + $attributesIds = $this->getRequest()->getParam('required'); + if ($attributesIds) { + $attributesIds = explode(',', $attributesIds); + foreach ($attributesIds as $attributeId) { + $attribute = $this->getProduct()->getTypeInstance(true)->getAttributeById($attributeId, $this->getProduct()); + if (!$attribute) { + continue; + } + $attributes[] = $attribute; + } + } + + return $attributes; + } + + /** + * Retrive configurable product for created/edited simple + * + * @return Mage_Catalog_Model_Product + */ + public function getConfigurableProduct() + { + if (is_null($this->_configurableProduct)) { + $this->_configurableProduct = Mage::getModel('catalog/product') + ->setStore(0) + ->load($this->getRequest()->getParam('product')); + } + return $this->_configurableProduct; + } + + /** + * Retrive product + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + if (is_null($this->_product)) { + $this->_product = Mage::getModel('catalog/product') + ->setStore(0) + ->load($this->getRequest()->getParam('id')); + } + return $this->_product; + } } // Class Mage_Adminhtml_Block_Catalog_Product_Created End \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php index fe614c56b1..5f6d643b5e 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit.php @@ -1,242 +1,242 @@ - - */ -class Mage_Adminhtml_Block_Catalog_Product_Edit extends Mage_Adminhtml_Block_Widget -{ - public function __construct() - { - parent::__construct(); - $this->setTemplate('catalog/product/edit.phtml'); - $this->setId('product_edit'); - } - - /** - * Retrieve currently edited product object - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - return Mage::registry('current_product'); - } - - protected function _prepareLayout() - { - if (!$this->getRequest()->getParam('popup')) { - $this->setChild('back_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Back'), - 'onclick' => 'setLocation(\''.$this->getUrl('*/*/', array('store'=>$this->getRequest()->getParam('store', 0))).'\')', - 'class' => 'back' - )) - ); - } else { - $this->setChild('back_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Close Window'), - 'onclick' => 'window.close()', - 'class' => 'cancel' - )) - ); - } - - $this->setChild('reset_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Reset'), - 'onclick' => 'setLocation(\''.$this->getUrl('*/*/*', array('_current'=>true)).'\')' - )) - ); - - $this->setChild('save_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Save'), - 'onclick' => 'productForm.submit()', - 'class' => 'save' - )) - ); - - if (!$this->getRequest()->getParam('popup')) { - $this->setChild('save_and_edit_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Save And Continue Edit'), - 'onclick' => 'saveAndContinueEdit(\''.$this->getSaveAndContinueUrl().'\')', - 'class' => 'save' - )) - ); - $this->setChild('delete_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Delete'), - 'onclick' => 'confirmSetLocation(\''.Mage::helper('catalog')->__('Are you sure?').'\', \''.$this->getDeleteUrl().'\')', - 'class' => 'delete' - )) - ); - $this->setChild('duplicate_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Duplicate'), - 'onclick' => 'setLocation(\''.$this->getDuplicateUrl().'\')', - 'class' => 'add' - )) - ); - } - - - - - return parent::_prepareLayout(); - } - - public function getBackButtonHtml() - { - return $this->getChildHtml('back_button'); - } - - public function getCancelButtonHtml() - { - return $this->getChildHtml('reset_button'); - } - - public function getSaveButtonHtml() - { - return $this->getChildHtml('save_button'); - } - - public function getSaveAndEditButtonHtml() - { - return $this->getChildHtml('save_and_edit_button'); - } - - public function getDeleteButtonHtml() - { - return $this->getChildHtml('delete_button'); - } - - public function getDuplicateButtonHtml() - { - return $this->getChildHtml('duplicate_button'); - } - - public function getValidationUrl() - { - return $this->getUrl('*/*/validate', array('_current'=>true)); - } - - public function getSaveUrl() - { - return $this->getUrl('*/*/save', array('_current'=>true, 'back'=>null)); - } - - public function getSaveAndContinueUrl() - { - return $this->getUrl('*/*/save', array( - '_current' => true, - 'back' => 'edit', - 'tab' => '{{tab_id}}' - )); - } - - public function getProductId() - { - return $this->getProduct()->getId(); - } - - public function getProductSetId() - { - $setId = false; - if (!($setId = $this->getProduct()->getAttributeSetId()) && $this->getRequest()) { - $setId = $this->getRequest()->getParam('set', null); - } - return $setId; - } - - public function getIsGrouped() - { - return $this->getProduct()->isGrouped(); - } - - public function getDeleteUrl() - { - return $this->getUrl('*/*/delete', array('_current'=>true)); - } - - public function getDuplicateUrl() - { - return $this->getUrl('*/*/duplicate', array('_current'=>true)); - } - - public function getHeader() - { - $header = ''; - if ($this->getProduct()->getId()) { - $header = $this->htmlEscape($this->getProduct()->getName()); - } - else { - $header = Mage::helper('catalog')->__('New Product'); - } - if ($setName = $this->getAttributeSetName()) { - $header.= ' (' . $setName . ')'; - } - return $header; - } - - public function getAttributeSetName() - { - if ($setId = $this->getProduct()->getAttributeSetId()) { - $set = Mage::getModel('eav/entity_attribute_set') - ->load($setId); - return $set->getAttributeSetName(); - } - return ''; - } - - public function getIsConfigured() - { - if ($this->getProduct()->isConfigurable() - && !($superAttributes = $this->getProduct()->getTypeInstance()->getUsedProductAttributeIds())) { - $superAttributes = false; - } - - return !$this->getProduct()->isConfigurable() || $superAttributes !== false; - } - - public function getSelectedTabId() - { - return addslashes(htmlspecialchars($this->getRequest()->getParam('tab'))); - } -} + + */ +class Mage_Adminhtml_Block_Catalog_Product_Edit extends Mage_Adminhtml_Block_Widget +{ + public function __construct() + { + parent::__construct(); + $this->setTemplate('catalog/product/edit.phtml'); + $this->setId('product_edit'); + } + + /** + * Retrieve currently edited product object + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + return Mage::registry('current_product'); + } + + protected function _prepareLayout() + { + if (!$this->getRequest()->getParam('popup')) { + $this->setChild('back_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Back'), + 'onclick' => 'setLocation(\''.$this->getUrl('*/*/', array('store'=>$this->getRequest()->getParam('store', 0))).'\')', + 'class' => 'back' + )) + ); + } else { + $this->setChild('back_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Close Window'), + 'onclick' => 'window.close()', + 'class' => 'cancel' + )) + ); + } + + $this->setChild('reset_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Reset'), + 'onclick' => 'setLocation(\''.$this->getUrl('*/*/*', array('_current'=>true)).'\')' + )) + ); + + $this->setChild('save_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Save'), + 'onclick' => 'productForm.submit()', + 'class' => 'save' + )) + ); + + if (!$this->getRequest()->getParam('popup')) { + $this->setChild('save_and_edit_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Save And Continue Edit'), + 'onclick' => 'saveAndContinueEdit(\''.$this->getSaveAndContinueUrl().'\')', + 'class' => 'save' + )) + ); + $this->setChild('delete_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Delete'), + 'onclick' => 'confirmSetLocation(\''.Mage::helper('catalog')->__('Are you sure?').'\', \''.$this->getDeleteUrl().'\')', + 'class' => 'delete' + )) + ); + $this->setChild('duplicate_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Duplicate'), + 'onclick' => 'setLocation(\''.$this->getDuplicateUrl().'\')', + 'class' => 'add' + )) + ); + } + + + + + return parent::_prepareLayout(); + } + + public function getBackButtonHtml() + { + return $this->getChildHtml('back_button'); + } + + public function getCancelButtonHtml() + { + return $this->getChildHtml('reset_button'); + } + + public function getSaveButtonHtml() + { + return $this->getChildHtml('save_button'); + } + + public function getSaveAndEditButtonHtml() + { + return $this->getChildHtml('save_and_edit_button'); + } + + public function getDeleteButtonHtml() + { + return $this->getChildHtml('delete_button'); + } + + public function getDuplicateButtonHtml() + { + return $this->getChildHtml('duplicate_button'); + } + + public function getValidationUrl() + { + return $this->getUrl('*/*/validate', array('_current'=>true)); + } + + public function getSaveUrl() + { + return $this->getUrl('*/*/save', array('_current'=>true, 'back'=>null)); + } + + public function getSaveAndContinueUrl() + { + return $this->getUrl('*/*/save', array( + '_current' => true, + 'back' => 'edit', + 'tab' => '{{tab_id}}' + )); + } + + public function getProductId() + { + return $this->getProduct()->getId(); + } + + public function getProductSetId() + { + $setId = false; + if (!($setId = $this->getProduct()->getAttributeSetId()) && $this->getRequest()) { + $setId = $this->getRequest()->getParam('set', null); + } + return $setId; + } + + public function getIsGrouped() + { + return $this->getProduct()->isGrouped(); + } + + public function getDeleteUrl() + { + return $this->getUrl('*/*/delete', array('_current'=>true)); + } + + public function getDuplicateUrl() + { + return $this->getUrl('*/*/duplicate', array('_current'=>true)); + } + + public function getHeader() + { + $header = ''; + if ($this->getProduct()->getId()) { + $header = $this->htmlEscape($this->getProduct()->getName()); + } + else { + $header = Mage::helper('catalog')->__('New Product'); + } + if ($setName = $this->getAttributeSetName()) { + $header.= ' (' . $setName . ')'; + } + return $header; + } + + public function getAttributeSetName() + { + if ($setId = $this->getProduct()->getAttributeSetId()) { + $set = Mage::getModel('eav/entity_attribute_set') + ->load($setId); + return $set->getAttributeSetName(); + } + return ''; + } + + public function getIsConfigured() + { + if ($this->getProduct()->isConfigurable() + && !($superAttributes = $this->getProduct()->getTypeInstance(true)->getUsedProductAttributeIds($this->getProduct()))) { + $superAttributes = false; + } + + return !$this->getProduct()->isConfigurable() || $superAttributes !== false; + } + + public function getSelectedTabId() + { + return addslashes(htmlspecialchars($this->getRequest()->getParam('tab'))); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php index 6ec5631624..96e7497681 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Action/Attribute/Tab/Attributes.php @@ -92,11 +92,20 @@ protected function _getAdditionalElementTypes() */ protected function _getAdditionalElementHtml($element) { - return ' - '; + if( $this->_returnAdditionalElementHtml($element) === true ) { + return ' + '; + } else { + return ''; + } + } + + protected function _returnAdditionalElementHtml($element) + { + return true; } /** diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Options/Option.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Options/Option.php index 9772706fdb..07d78eff4b 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Options/Option.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Options/Option.php @@ -231,6 +231,8 @@ public function getOptionValues() $value['sku'] = $this->htmlEscape($option->getSku()); $value['max_characters'] = $option->getMaxCharacters(); $value['file_extension'] = $option->getFileExtension(); + $value['image_size_x'] = $option->getImageSizeX(); + $value['image_size_y'] = $option->getImageSizeY(); if ($this->getProduct()->getStoreId() != '0' && $scope == Mage_Core_Model_Store::PRICE_SCOPE_WEBSITE) { $value['checkboxScopePrice'] = $this->getCheckboxScopeHtml($option->getOptionId(), 'price', is_null($option->getStorePrice())); $value['scopePriceDisabled'] = is_null($option->getStorePrice())?'disabled':null; diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php index b7b44d5788..bfd321e185 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config.php @@ -1,212 +1,212 @@ - - */ - -class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config extends Mage_Adminhtml_Block_Widget implements Mage_Adminhtml_Block_Widget_Tab_Interface -{ - public function __construct() - { - parent::__construct(); - $this->setProductId($this->getRequest()->getParam('id')); - $this->setTemplate('catalog/product/edit/super/config.phtml'); - $this->setId('config_super_product'); - } - - public function getTabClass() - { - return 'ajax'; - } - - protected function _prepareLayout() - { - $this->setChild('grid', - $this->getLayout()->createBlock('adminhtml/catalog_product_edit_tab_super_config_grid') - ); - - - - $this->setChild('create_empty', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Create Empty'), - 'class' => 'add', - 'onclick' => 'superProduct.createEmptyProduct()' - )) - ); - - if ($this->_getProduct()->getId()) { - $this->setChild('simple', - $this->getLayout()->createBlock('adminhtml/catalog_product_edit_tab_super_config_simple') - ); - - $this->setChild('create_from_configurable', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Copy From Configurable'), - 'class' => 'add', - 'onclick' => 'superProduct.createNewProduct()' - )) - ); - } - - return parent::_prepareLayout(); - } - - /** - * Retrieve currently edited product object - * - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct() - { - return Mage::registry('current_product'); - } - - public function getAttributesJson() - { - $attributes = $this->_getProduct()->getTypeInstance()->getConfigurableAttributesAsArray(); - if(!$attributes) { - return '[]'; - } - return Zend_Json::encode($attributes); - } - - public function getLinksJson() - { - $products = $this->_getProduct()->getTypeInstance()->getUsedProducts(); - if(!$products) { - return '{}'; - } - $data = array(); - foreach ($products as $product) { - $data[$product->getId()] = $this->getConfigurableSettings($product); - } - return Zend_Json::encode($data); - } - - public function getConfigurableSettings($product) { - $data = array(); - foreach ($this->_getProduct()->getTypeInstance()->getUsedProductAttributes() as $attribute) { - $data[] = array( - 'attribute_id' => $attribute->getId(), - 'label' => $product->getAttributeText($attribute->getAttributeCode()), - 'value_index' => $product->getData($attribute->getAttributeCode()) - ); - } - - return $data; - } - - public function getGridHtml() - { - return $this->getChildHtml('grid'); - } - - public function getGridJsObject() - { - return $this->getChild('grid')->getJsObjectName(); - } - - public function getNewEmptyProductUrl() - { - return $this->getUrl( - '*/*/new', - array( - 'set' => $this->_getProduct()->getAttributeSetId(), - 'type' => Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, - 'required' => $this->_getRequiredAttributesIds(), - 'popup' => 1 - ) - ); - } - - public function getNewProductUrl() - { - return $this->getUrl( - '*/*/new', - array( - 'set' => $this->_getProduct()->getAttributeSetId(), - 'type' => Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, - 'required' => $this->_getRequiredAttributesIds(), - 'popup' => 1, - 'product' => $this->_getProduct()->getId() - ) - ); - } - - - - public function getQuickCreationUrl() - { - return $this->getUrl( - '*/*/quickCreate', - array( - 'product' => $this->_getProduct()->getId() - ) - ); - } - - - protected function _getRequiredAttributesIds() - { - $attributesIds = array(); - foreach ($this->_getProduct()->getTypeInstance()->getConfigurableAttributes() as $attribute) { - $attributesIds[] = $attribute->getProductAttribute()->getId(); - } - - return implode(',', $attributesIds); - } - - public function escapeJs($string) - { - return addcslashes($string, "'\r\n\\"); - } - - public function getTabLabel() - { - return Mage::helper('catalog')->__('Associated Products'); - } - public function getTabTitle() - { - return Mage::helper('catalog')->__('Associated Products'); - } - public function canShowTab() - { - return true; - } - public function isHidden() - { - return false; - } - + + */ + +class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config extends Mage_Adminhtml_Block_Widget implements Mage_Adminhtml_Block_Widget_Tab_Interface +{ + public function __construct() + { + parent::__construct(); + $this->setProductId($this->getRequest()->getParam('id')); + $this->setTemplate('catalog/product/edit/super/config.phtml'); + $this->setId('config_super_product'); + } + + public function getTabClass() + { + return 'ajax'; + } + + protected function _prepareLayout() + { + $this->setChild('grid', + $this->getLayout()->createBlock('adminhtml/catalog_product_edit_tab_super_config_grid') + ); + + + + $this->setChild('create_empty', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Create Empty'), + 'class' => 'add', + 'onclick' => 'superProduct.createEmptyProduct()' + )) + ); + + if ($this->_getProduct()->getId()) { + $this->setChild('simple', + $this->getLayout()->createBlock('adminhtml/catalog_product_edit_tab_super_config_simple') + ); + + $this->setChild('create_from_configurable', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Copy From Configurable'), + 'class' => 'add', + 'onclick' => 'superProduct.createNewProduct()' + )) + ); + } + + return parent::_prepareLayout(); + } + + /** + * Retrieve currently edited product object + * + * @return Mage_Catalog_Model_Product + */ + protected function _getProduct() + { + return Mage::registry('current_product'); + } + + public function getAttributesJson() + { + $attributes = $this->_getProduct()->getTypeInstance(true)->getConfigurableAttributesAsArray($this->_getProduct()); + if(!$attributes) { + return '[]'; + } + return Zend_Json::encode($attributes); + } + + public function getLinksJson() + { + $products = $this->_getProduct()->getTypeInstance(true)->getUsedProducts(null, $this->_getProduct()); + if(!$products) { + return '{}'; + } + $data = array(); + foreach ($products as $product) { + $data[$product->getId()] = $this->getConfigurableSettings($product); + } + return Zend_Json::encode($data); + } + + public function getConfigurableSettings($product) { + $data = array(); + foreach ($this->_getProduct()->getTypeInstance(true)->getUsedProductAttributes($this->_getProduct()) as $attribute) { + $data[] = array( + 'attribute_id' => $attribute->getId(), + 'label' => $product->getAttributeText($attribute->getAttributeCode()), + 'value_index' => $product->getData($attribute->getAttributeCode()) + ); + } + + return $data; + } + + public function getGridHtml() + { + return $this->getChildHtml('grid'); + } + + public function getGridJsObject() + { + return $this->getChild('grid')->getJsObjectName(); + } + + public function getNewEmptyProductUrl() + { + return $this->getUrl( + '*/*/new', + array( + 'set' => $this->_getProduct()->getAttributeSetId(), + 'type' => Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, + 'required' => $this->_getRequiredAttributesIds(), + 'popup' => 1 + ) + ); + } + + public function getNewProductUrl() + { + return $this->getUrl( + '*/*/new', + array( + 'set' => $this->_getProduct()->getAttributeSetId(), + 'type' => Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, + 'required' => $this->_getRequiredAttributesIds(), + 'popup' => 1, + 'product' => $this->_getProduct()->getId() + ) + ); + } + + + + public function getQuickCreationUrl() + { + return $this->getUrl( + '*/*/quickCreate', + array( + 'product' => $this->_getProduct()->getId() + ) + ); + } + + + protected function _getRequiredAttributesIds() + { + $attributesIds = array(); + foreach ($this->_getProduct()->getTypeInstance(true)->getConfigurableAttributes($this->_getProduct()) as $attribute) { + $attributesIds[] = $attribute->getProductAttribute()->getId(); + } + + return implode(',', $attributesIds); + } + + public function escapeJs($string) + { + return addcslashes($string, "'\r\n\\"); + } + + public function getTabLabel() + { + return Mage::helper('catalog')->__('Associated Products'); + } + public function getTabTitle() + { + return Mage::helper('catalog')->__('Associated Products'); + } + public function canShowTab() + { + return true; + } + public function isHidden() + { + return false; + } + }// Class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config END \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Grid.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Grid.php index b4ad007592..719f3b441e 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Grid.php @@ -1,275 +1,275 @@ - - */ -class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Grid extends Mage_Adminhtml_Block_Widget_Grid -{ - - public function __construct() - { - parent::__construct(); - $this->setUseAjax(true); - $this->setId('super_product_links'); - - if ($this->_getProduct()->getId()) { - $this->setDefaultFilter(array('in_products'=>1)); - } - } - - /** - * Retrieve currently edited product object - * - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct() - { - return Mage::registry('current_product'); - } - - protected function _addColumnFilterToCollection($column) - { - // Set custom filter for in product flag - if ($column->getId() == 'in_products') { - $productIds = $this->_getSelectedProducts(); - - if (empty($productIds)) { - $productIds = 0; - } - - $createdProducts = $this->_getCreatedProducts(); - - $existsProducts = $productIds; // Only for "Yes" Filter we will add created products - - if(count($createdProducts)>0) { - if(!is_array($existsProducts)) { - $existsProducts = $createdProducts; - } else { - $existsProducts = array_merge($createdProducts); - } - } - - if ($column->getFilter()->getValue()) { - $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$existsProducts)); - } - else { - if($productIds) { - $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds)); - } - } - } - else { - parent::_addColumnFilterToCollection($column); - } - return $this; - } - - protected function _getCreatedProducts() - { - $products = $this->getRequest()->getPost('new_products', null); - if (!is_array($products)) { - $products = array(); - } - - return $products; - } - - protected function _prepareCollection() - { - $allowProductTypes = array(); - foreach (Mage::getConfig()->getNode('global/catalog/product/type/configurable/allow_product_types')->children() as $type) { - $allowProductTypes[] = $type->getName(); - } - - $product = $this->_getProduct(); - $collection = $product->getCollection() - ->addAttributeToSelect('name') - ->addAttributeToSelect('sku') - ->addAttributeToSelect('attribute_set_id') - ->addAttributeToSelect('type_id') - ->addAttributeToSelect('price') - ->addFieldToFilter('attribute_set_id',$product->getAttributeSetId()) - ->addFieldToFilter('type_id', $allowProductTypes) - ->addFilterByRequiredOptions(); - - Mage::getModel('cataloginventory/stock_item')->addCatalogInventoryToProductCollection($collection); - - foreach ($product->getTypeInstance()->getUsedProductAttributes() as $attribute) { - $collection->addAttributeToSelect($attribute->getAttributeCode()); - $collection->addAttributeToFilter($attribute->getAttributeCode(), array('nin'=>array(null))); - } - - $this->setCollection($collection); - - parent::_prepareCollection(); - return $this; - } - - protected function _getSelectedProducts() - { - $products = $this->getRequest()->getPost('products', null); - if (!is_array($products)) { - $products = $this->_getProduct()->getTypeInstance()->getUsedProductIds(); - } - return $products; - } - - protected function _prepareColumns() - { - $product = $this->_getProduct(); - $attributes = $product->getTypeInstance()->getConfigurableAttributes(); - $this->addColumn('in_products', array( - 'header_css_class' => 'a-center', - 'type' => 'checkbox', - 'name' => 'in_products', - 'values' => $this->_getSelectedProducts(), - 'align' => 'center', - 'index' => 'entity_id', - 'renderer' => 'adminhtml/catalog_product_edit_tab_super_config_grid_renderer_checkbox', - 'attributes' => $attributes - )); - - $this->addColumn('entity_id', array( - 'header' => Mage::helper('catalog')->__('ID'), - 'sortable' => true, - 'width' => '60px', - 'index' => 'entity_id' - )); - $this->addColumn('name', array( - 'header' => Mage::helper('catalog')->__('Name'), - 'index' => 'name' - )); - - - $sets = Mage::getModel('eav/entity_attribute_set')->getCollection() - ->setEntityTypeFilter($this->_getProduct()->getResource()->getTypeId()) - ->load() - ->toOptionHash(); - - $this->addColumn('set_name', - array( - 'header'=> Mage::helper('catalog')->__('Attrib. Set Name'), - 'width' => '130px', - 'index' => 'attribute_set_id', - 'type' => 'options', - 'options' => $sets, - )); - - $this->addColumn('sku', array( - 'header' => Mage::helper('catalog')->__('SKU'), - 'width' => '80px', - 'index' => 'sku' - )); - - $this->addColumn('price', array( - 'header' => Mage::helper('catalog')->__('Price'), - 'type' => 'currency', - 'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE), - 'index' => 'price' - )); - - $this->addColumn('is_saleable', array( - 'header' => Mage::helper('catalog')->__('Inventory'), - 'renderer' => 'adminhtml/catalog_product_edit_tab_super_config_grid_renderer_inventory', - 'filter' => 'adminhtml/catalog_product_edit_tab_super_config_grid_filter_inventory', - 'index' => 'is_saleable' - )); - - foreach ($attributes as $attribute) { - $productAttribute = $attribute->getProductAttribute(); - $productAttribute->getSource(); - $this->addColumn($productAttribute->getAttributeCode(), array( - 'header' => $productAttribute->getFrontend()->getLabel(), - 'index' => $productAttribute->getAttributeCode(), - 'type' => $productAttribute->getSourceModel() ? 'options' : 'number', - 'options' => $productAttribute->getSourceModel() ? $this->getOptions($attribute) : '' - )); - } - - $this->addColumn('action', - array( - 'header' => Mage::helper('catalog')->__('Action'), - 'type' => 'action', - 'getter' => 'getId', - 'actions' => array( - array( - 'caption' => Mage::helper('catalog')->__('Edit'), - 'url' => $this->getEditParamsForAssociated(), - 'field' => 'id', - 'onclick' => 'superProduct.createPopup(this.href);return false;' - ) - ), - 'filter' => false, - 'sortable' => false - )); - - return parent::_prepareColumns(); - } - - public function getEditParamsForAssociated() - { - return array( - 'base' => '*/*/edit', - 'params' => array( - 'required' => $this->_getRequiredAttributesIds(), - 'popup' => 1, - 'product' => $this->_getProduct()->getId() - ) - ); - } - - protected function _getRequiredAttributesIds() - { - $attributesIds = array(); - foreach ($this->_getProduct()->getTypeInstance()->getConfigurableAttributes() as $attribute) { - $attributesIds[] = $attribute->getProductAttribute()->getId(); - } - - return implode(',', $attributesIds); - } - - public function getOptions($attribute) { - $result = array(); - foreach ($attribute->getProductAttribute()->getSource()->getAllOptions() as $option) { - if($option['value']!='') { - $result[$option['value']] = $option['label']; - } - } - - return $result; - } - - public function getGridUrl() - { - return $this->getUrl('*/*/superConfig', array('_current'=>true)); - } - + + */ +class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Grid extends Mage_Adminhtml_Block_Widget_Grid +{ + + public function __construct() + { + parent::__construct(); + $this->setUseAjax(true); + $this->setId('super_product_links'); + + if ($this->_getProduct()->getId()) { + $this->setDefaultFilter(array('in_products'=>1)); + } + } + + /** + * Retrieve currently edited product object + * + * @return Mage_Catalog_Model_Product + */ + protected function _getProduct() + { + return Mage::registry('current_product'); + } + + protected function _addColumnFilterToCollection($column) + { + // Set custom filter for in product flag + if ($column->getId() == 'in_products') { + $productIds = $this->_getSelectedProducts(); + + if (empty($productIds)) { + $productIds = 0; + } + + $createdProducts = $this->_getCreatedProducts(); + + $existsProducts = $productIds; // Only for "Yes" Filter we will add created products + + if(count($createdProducts)>0) { + if(!is_array($existsProducts)) { + $existsProducts = $createdProducts; + } else { + $existsProducts = array_merge($createdProducts); + } + } + + if ($column->getFilter()->getValue()) { + $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$existsProducts)); + } + else { + if($productIds) { + $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds)); + } + } + } + else { + parent::_addColumnFilterToCollection($column); + } + return $this; + } + + protected function _getCreatedProducts() + { + $products = $this->getRequest()->getPost('new_products', null); + if (!is_array($products)) { + $products = array(); + } + + return $products; + } + + protected function _prepareCollection() + { + $allowProductTypes = array(); + foreach (Mage::getConfig()->getNode('global/catalog/product/type/configurable/allow_product_types')->children() as $type) { + $allowProductTypes[] = $type->getName(); + } + + $product = $this->_getProduct(); + $collection = $product->getCollection() + ->addAttributeToSelect('name') + ->addAttributeToSelect('sku') + ->addAttributeToSelect('attribute_set_id') + ->addAttributeToSelect('type_id') + ->addAttributeToSelect('price') + ->addFieldToFilter('attribute_set_id',$product->getAttributeSetId()) + ->addFieldToFilter('type_id', $allowProductTypes) + ->addFilterByRequiredOptions(); + + Mage::getModel('cataloginventory/stock_item')->addCatalogInventoryToProductCollection($collection); + + foreach ($product->getTypeInstance(true)->getUsedProductAttributes($product) as $attribute) { + $collection->addAttributeToSelect($attribute->getAttributeCode()); + $collection->addAttributeToFilter($attribute->getAttributeCode(), array('nin'=>array(null))); + } + + $this->setCollection($collection); + + parent::_prepareCollection(); + return $this; + } + + protected function _getSelectedProducts() + { + $products = $this->getRequest()->getPost('products', null); + if (!is_array($products)) { + $products = $this->_getProduct()->getTypeInstance(true)->getUsedProductIds($this->_getProduct()); + } + return $products; + } + + protected function _prepareColumns() + { + $product = $this->_getProduct(); + $attributes = $product->getTypeInstance(true)->getConfigurableAttributes($product); + $this->addColumn('in_products', array( + 'header_css_class' => 'a-center', + 'type' => 'checkbox', + 'name' => 'in_products', + 'values' => $this->_getSelectedProducts(), + 'align' => 'center', + 'index' => 'entity_id', + 'renderer' => 'adminhtml/catalog_product_edit_tab_super_config_grid_renderer_checkbox', + 'attributes' => $attributes + )); + + $this->addColumn('entity_id', array( + 'header' => Mage::helper('catalog')->__('ID'), + 'sortable' => true, + 'width' => '60px', + 'index' => 'entity_id' + )); + $this->addColumn('name', array( + 'header' => Mage::helper('catalog')->__('Name'), + 'index' => 'name' + )); + + + $sets = Mage::getModel('eav/entity_attribute_set')->getCollection() + ->setEntityTypeFilter($this->_getProduct()->getResource()->getTypeId()) + ->load() + ->toOptionHash(); + + $this->addColumn('set_name', + array( + 'header'=> Mage::helper('catalog')->__('Attrib. Set Name'), + 'width' => '130px', + 'index' => 'attribute_set_id', + 'type' => 'options', + 'options' => $sets, + )); + + $this->addColumn('sku', array( + 'header' => Mage::helper('catalog')->__('SKU'), + 'width' => '80px', + 'index' => 'sku' + )); + + $this->addColumn('price', array( + 'header' => Mage::helper('catalog')->__('Price'), + 'type' => 'currency', + 'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE), + 'index' => 'price' + )); + + $this->addColumn('is_saleable', array( + 'header' => Mage::helper('catalog')->__('Inventory'), + 'renderer' => 'adminhtml/catalog_product_edit_tab_super_config_grid_renderer_inventory', + 'filter' => 'adminhtml/catalog_product_edit_tab_super_config_grid_filter_inventory', + 'index' => 'is_saleable' + )); + + foreach ($attributes as $attribute) { + $productAttribute = $attribute->getProductAttribute(); + $productAttribute->getSource(); + $this->addColumn($productAttribute->getAttributeCode(), array( + 'header' => $productAttribute->getFrontend()->getLabel(), + 'index' => $productAttribute->getAttributeCode(), + 'type' => $productAttribute->getSourceModel() ? 'options' : 'number', + 'options' => $productAttribute->getSourceModel() ? $this->getOptions($attribute) : '' + )); + } + + $this->addColumn('action', + array( + 'header' => Mage::helper('catalog')->__('Action'), + 'type' => 'action', + 'getter' => 'getId', + 'actions' => array( + array( + 'caption' => Mage::helper('catalog')->__('Edit'), + 'url' => $this->getEditParamsForAssociated(), + 'field' => 'id', + 'onclick' => 'superProduct.createPopup(this.href);return false;' + ) + ), + 'filter' => false, + 'sortable' => false + )); + + return parent::_prepareColumns(); + } + + public function getEditParamsForAssociated() + { + return array( + 'base' => '*/*/edit', + 'params' => array( + 'required' => $this->_getRequiredAttributesIds(), + 'popup' => 1, + 'product' => $this->_getProduct()->getId() + ) + ); + } + + protected function _getRequiredAttributesIds() + { + $attributesIds = array(); + foreach ($this->_getProduct()->getTypeInstance(true)->getConfigurableAttributes($this->_getProduct()) as $attribute) { + $attributesIds[] = $attribute->getProductAttribute()->getId(); + } + + return implode(',', $attributesIds); + } + + public function getOptions($attribute) { + $result = array(); + foreach ($attribute->getProductAttribute()->getSource()->getAllOptions() as $option) { + if($option['value']!='') { + $result[$option['value']] = $option['label']; + } + } + + return $result; + } + + public function getGridUrl() + { + return $this->getUrl('*/*/superConfig', array('_current'=>true)); + } + } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Simple.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Simple.php index 23b4ff2d14..0e47059657 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Simple.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Config/Simple.php @@ -1,184 +1,184 @@ - - */ -class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Simple extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes -{ - protected function _prepareForm() - { - $form = new Varien_Data_Form(); - - $form->setFieldNameSuffix('simple_product'); - - $fieldset = $form->addFieldset('simple_product', array( - 'legend' => Mage::helper('catalog')->__('Quick simple product creation') - )); - $this->_addElementTypes($fieldset); - $attributesConfig = array( - 'autogenerate' => array('name', 'sku'), - 'additional' => array('name', 'sku', 'visibility', 'status') - ); - - $availableTypes = array('text', 'select', 'multiselect', 'textarea', 'price'); - - $attributes = Mage::getModel('catalog/product') - ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) - ->setAttributeSetId($this->_getProduct()->getAttributeSetId()) - ->getAttributes(); - - /* Standart attributes */ - foreach ($attributes as $attribute) { - if (($attribute->getIsRequired() - && $attribute->getApplyTo() - // If not applied to configurable - && !in_array(Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE, $attribute->getApplyTo()) - // If not used in configurable - && !in_array($attribute->getId(),$this->_getProduct()->getTypeInstance()->getUsedProductAttributeIds())) - // Or in additional - || in_array($attribute->getAttributeCode(), $attributesConfig['additional'])) { - - $inputType = $attribute->getFrontend()->getInputType(); - if (!in_array($inputType, $availableTypes)) { - continue; - } - $attributeCode = $attribute->getAttributeCode(); - $element = $fieldset->addField( - 'simple_product_' . $attributeCode, - $inputType, - array( - 'label' => $attribute->getFrontend()->getLabel(), - 'name' => $attributeCode, - 'required' => $attribute->getIsRequired(), - ) - )->setEntityAttribute($attribute); - - if (in_array($attributeCode, $attributesConfig['autogenerate'])) { - $element->setDisabled('true'); - $element->setValue($this->_getProduct()->getData($attributeCode)); - $element->setAfterElementHtml( - ' ' - . '' - ); - } - - - if ($inputType == 'select' || $inputType == 'multiselect') { - $element->setValues($attribute->getFrontend()->getSelectOptions()); - } - } - - } - - /* Configurable attributes */ - foreach ($this->_getProduct()->getTypeInstance()->getUsedProductAttributes() as $attribute) { - $attributeCode = $attribute->getAttributeCode(); - $fieldset->addField( 'simple_product_' . $attributeCode, 'select', array( - 'label' => $attribute->getFrontend()->getLabel(), - 'name' => $attributeCode, - 'values' => $attribute->getSource()->getAllOptions(true, true), - 'required' => true, - 'class' => 'validate-configurable', - 'onchange' => 'superProduct.showPricing(this, \'' . $attributeCode . '\')' - )); - - $fieldset->addField('simple_product_' . $attributeCode . '_pricing_value', 'hidden', array( - 'name' => 'pricing[' . $attributeCode . '][value]' - )); - - $fieldset->addField('simple_product_' . $attributeCode . '_pricing_type', 'hidden', array( - 'name' => 'pricing[' . $attributeCode . '][is_percent]' - )); - } - - /* Inventory Data */ - $fieldset->addField('simple_product_inventory_qty', 'text', array( - 'label' => Mage::helper('catalog')->__('Qty'), - 'name' => 'stock_data[qty]', - 'class' => 'validate-number', - 'required' => true, - 'value' => 0 - )); - - $fieldset->addField('simple_product_inventory_is_in_stock', 'select', array( - 'label' => Mage::helper('catalog')->__('Stock Availability'), - 'name' => 'stock_data[is_in_stock]', - 'values' => array( - array('value'=>1, 'label'=> Mage::helper('catalog')->__('In Stock')), - array('value'=>0, 'label'=> Mage::helper('catalog')->__('Out of Stock')) - ), - 'value' => 1 - )); - - $stockHiddenFields = array( - 'use_config_min_qty' => 1, - 'use_config_min_sale_qty' => 1, - 'use_config_max_sale_qty' => 1, - 'use_config_backorders' => 1, - 'use_config_notify_stock_qty' => 1, - 'is_qty_decimal' => 0 - ); - - foreach ($stockHiddenFields as $fieldName=>$fieldValue) { - $fieldset->addField('simple_product_inventory_' . $fieldName, 'hidden', array( - 'name' => 'stock_data[' . $fieldName .']', - 'value' => $fieldValue - )); - } - - - $fieldset->addField('create_button', 'note', array( - 'text' => $this->getButtonHtml( - Mage::helper('catalog')->__('Quick Create'), - 'superProduct.quickCreateNewProduct()', - 'save' - ) - )); - - - - $this->setForm($form); - } - - /** - * Retrieve currently edited product object - * - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct() - { - return Mage::registry('current_product'); - } + + */ +class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Simple extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes +{ + protected function _prepareForm() + { + $form = new Varien_Data_Form(); + + $form->setFieldNameSuffix('simple_product'); + + $fieldset = $form->addFieldset('simple_product', array( + 'legend' => Mage::helper('catalog')->__('Quick simple product creation') + )); + $this->_addElementTypes($fieldset); + $attributesConfig = array( + 'autogenerate' => array('name', 'sku'), + 'additional' => array('name', 'sku', 'visibility', 'status') + ); + + $availableTypes = array('text', 'select', 'multiselect', 'textarea', 'price'); + + $attributes = Mage::getModel('catalog/product') + ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) + ->setAttributeSetId($this->_getProduct()->getAttributeSetId()) + ->getAttributes(); + + /* Standart attributes */ + foreach ($attributes as $attribute) { + if (($attribute->getIsRequired() + && $attribute->getApplyTo() + // If not applied to configurable + && !in_array(Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE, $attribute->getApplyTo()) + // If not used in configurable + && !in_array($attribute->getId(),$this->_getProduct()->getTypeInstance(true)->getUsedProductAttributeIds($this->_getProduct()))) + // Or in additional + || in_array($attribute->getAttributeCode(), $attributesConfig['additional'])) { + + $inputType = $attribute->getFrontend()->getInputType(); + if (!in_array($inputType, $availableTypes)) { + continue; + } + $attributeCode = $attribute->getAttributeCode(); + $element = $fieldset->addField( + 'simple_product_' . $attributeCode, + $inputType, + array( + 'label' => $attribute->getFrontend()->getLabel(), + 'name' => $attributeCode, + 'required' => $attribute->getIsRequired(), + ) + )->setEntityAttribute($attribute); + + if (in_array($attributeCode, $attributesConfig['autogenerate'])) { + $element->setDisabled('true'); + $element->setValue($this->_getProduct()->getData($attributeCode)); + $element->setAfterElementHtml( + ' ' + . '' + ); + } + + + if ($inputType == 'select' || $inputType == 'multiselect') { + $element->setValues($attribute->getFrontend()->getSelectOptions()); + } + } + + } + + /* Configurable attributes */ + foreach ($this->_getProduct()->getTypeInstance(true)->getUsedProductAttributes($this->_getProduct()) as $attribute) { + $attributeCode = $attribute->getAttributeCode(); + $fieldset->addField( 'simple_product_' . $attributeCode, 'select', array( + 'label' => $attribute->getFrontend()->getLabel(), + 'name' => $attributeCode, + 'values' => $attribute->getSource()->getAllOptions(true, true), + 'required' => true, + 'class' => 'validate-configurable', + 'onchange' => 'superProduct.showPricing(this, \'' . $attributeCode . '\')' + )); + + $fieldset->addField('simple_product_' . $attributeCode . '_pricing_value', 'hidden', array( + 'name' => 'pricing[' . $attributeCode . '][value]' + )); + + $fieldset->addField('simple_product_' . $attributeCode . '_pricing_type', 'hidden', array( + 'name' => 'pricing[' . $attributeCode . '][is_percent]' + )); + } + + /* Inventory Data */ + $fieldset->addField('simple_product_inventory_qty', 'text', array( + 'label' => Mage::helper('catalog')->__('Qty'), + 'name' => 'stock_data[qty]', + 'class' => 'validate-number', + 'required' => true, + 'value' => 0 + )); + + $fieldset->addField('simple_product_inventory_is_in_stock', 'select', array( + 'label' => Mage::helper('catalog')->__('Stock Availability'), + 'name' => 'stock_data[is_in_stock]', + 'values' => array( + array('value'=>1, 'label'=> Mage::helper('catalog')->__('In Stock')), + array('value'=>0, 'label'=> Mage::helper('catalog')->__('Out of Stock')) + ), + 'value' => 1 + )); + + $stockHiddenFields = array( + 'use_config_min_qty' => 1, + 'use_config_min_sale_qty' => 1, + 'use_config_max_sale_qty' => 1, + 'use_config_backorders' => 1, + 'use_config_notify_stock_qty' => 1, + 'is_qty_decimal' => 0 + ); + + foreach ($stockHiddenFields as $fieldName=>$fieldValue) { + $fieldset->addField('simple_product_inventory_' . $fieldName, 'hidden', array( + 'name' => 'stock_data[' . $fieldName .']', + 'value' => $fieldValue + )); + } + + + $fieldset->addField('create_button', 'note', array( + 'text' => $this->getButtonHtml( + Mage::helper('catalog')->__('Quick Create'), + 'superProduct.quickCreateNewProduct()', + 'save' + ) + )); + + + + $this->setForm($form); + } + + /** + * Retrieve currently edited product object + * + * @return Mage_Catalog_Model_Product + */ + protected function _getProduct() + { + return Mage::registry('current_product'); + } } // Class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Simple End \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Group.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Group.php index 49bb027ac7..551b07c022 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Group.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Group.php @@ -144,7 +144,7 @@ protected function _prepareColumns() 'type' => 'number', 'validate_class' => 'validate-number', 'index' => 'qty', - 'width' => '60px', + 'width' => '1', 'editable' => true )); @@ -154,7 +154,7 @@ protected function _prepareColumns() 'type' => 'number', 'validate_class' => 'validate-number', 'index' => 'position', - 'width' => '60px', + 'width' => '1', 'editable' => true, 'edit_only' => !$this->_getProduct()->getId() )); @@ -171,7 +171,7 @@ protected function _getSelectedProducts() { $products = $this->getRequest()->getPost('products', null); if (!is_array($products)) { - $products = $this->_getProduct()->getTypeInstance()->getAssociatedProductIds(); + $products = $this->_getProduct()->getTypeInstance(true)->getAssociatedProductIds($this->_getProduct()); } return $products; } diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php index 4cd301013e..6009ea31c8 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Super/Settings.php @@ -1,135 +1,135 @@ - - */ -class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings extends Mage_Adminhtml_Block_Widget_Form -{ - protected function _prepareLayout() - { - $onclick = "setSuperSettings('".$this->getContinueUrl()."','attribute-checkbox', 'attributes')"; - $this->setChild('continue_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Continue'), - 'onclick' => $onclick, - 'class' => 'save' - )) - ); - - $backButton = $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Back'), - 'onclick' => "setLocation('".$this->getBackUrl()."')", - 'class' => 'back' - )); - - $this->setChild('back_button', $backButton); - return parent::_prepareLayout(); - } - - /** - * Retrieve currently edited product object - * - * @return Mage_Catalog_Model_Product - */ - protected function _getProduct() - { - return Mage::registry('current_product'); - } - - protected function _prepareForm() - { - $form = new Varien_Data_Form(); - $fieldset = $form->addFieldset('settings', array( - 'legend'=>Mage::helper('catalog')->__('Select Configurable Attributes ') - )); - - $product = $this->_getProduct(); - $attributes = $product->getTypeInstance()->getSetAttributes(); - - $fieldset->addField('req_text', 'note', array( - 'text' => '' - )); - - $hasAttributes = false; - foreach($attributes as $attribute) { - if($product->getTypeInstance()->canUseAttribute($attribute)) { - $hasAttributes = true; - $fieldset->addField('attribute_'.$attribute->getAttributeId(), 'checkbox', array( - 'label' => $attribute->getFrontend()->getLabel(), - 'title' => $attribute->getFrontend()->getLabel(), - 'name' => 'attribute', - 'class' => 'attribute-checkbox', - 'value' => $attribute->getAttributeId() - )); - } - } - - if ($hasAttributes) { - $fieldset->addField('attributes', 'hidden', array( - 'name' => 'attribute_validate', - 'value' => '', - 'class' => 'validate-super-product-attributes' - )); - - $fieldset->addField('continue_button', 'note', array( - 'text' => $this->getChildHtml('continue_button'), - )); - } - else { - $fieldset->addField('note_text', 'note', array( - 'text' => $this->__('This attribute set don\'t have attributes which we can use for configurable product') - )); - $fieldset->addField('back_button', 'note', array( - 'text' => $this->getChildHtml('back_button'), - )); - } - - - $this->setForm($form); - } - - public function getContinueUrl() - { - return $this->getUrl('*/*/new', array( - '_current' => true, - 'attributes' => '{{attributes}}' - )); - } - - public function getBackUrl() - { - return $this->getUrl('*/*/new', array('set'=>null, 'type'=>null)); - } -} + + */ +class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Settings extends Mage_Adminhtml_Block_Widget_Form +{ + protected function _prepareLayout() + { + $onclick = "setSuperSettings('".$this->getContinueUrl()."','attribute-checkbox', 'attributes')"; + $this->setChild('continue_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Continue'), + 'onclick' => $onclick, + 'class' => 'save' + )) + ); + + $backButton = $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Back'), + 'onclick' => "setLocation('".$this->getBackUrl()."')", + 'class' => 'back' + )); + + $this->setChild('back_button', $backButton); + return parent::_prepareLayout(); + } + + /** + * Retrieve currently edited product object + * + * @return Mage_Catalog_Model_Product + */ + protected function _getProduct() + { + return Mage::registry('current_product'); + } + + protected function _prepareForm() + { + $form = new Varien_Data_Form(); + $fieldset = $form->addFieldset('settings', array( + 'legend'=>Mage::helper('catalog')->__('Select Configurable Attributes ') + )); + + $product = $this->_getProduct(); + $attributes = $product->getTypeInstance(true)->getSetAttributes($product); + + $fieldset->addField('req_text', 'note', array( + 'text' => '' + )); + + $hasAttributes = false; + foreach($attributes as $attribute) { + if($product->getTypeInstance(true)->canUseAttribute($attribute, $product)) { + $hasAttributes = true; + $fieldset->addField('attribute_'.$attribute->getAttributeId(), 'checkbox', array( + 'label' => $attribute->getFrontend()->getLabel(), + 'title' => $attribute->getFrontend()->getLabel(), + 'name' => 'attribute', + 'class' => 'attribute-checkbox', + 'value' => $attribute->getAttributeId() + )); + } + } + + if ($hasAttributes) { + $fieldset->addField('attributes', 'hidden', array( + 'name' => 'attribute_validate', + 'value' => '', + 'class' => 'validate-super-product-attributes' + )); + + $fieldset->addField('continue_button', 'note', array( + 'text' => $this->getChildHtml('continue_button'), + )); + } + else { + $fieldset->addField('note_text', 'note', array( + 'text' => $this->__('This attribute set don\'t have attributes which we can use for configurable product') + )); + $fieldset->addField('back_button', 'note', array( + 'text' => $this->getChildHtml('back_button'), + )); + } + + + $this->setForm($form); + } + + public function getContinueUrl() + { + return $this->getUrl('*/*/new', array( + '_current' => true, + 'attributes' => '{{attributes}}' + )); + } + + public function getBackUrl() + { + return $this->getUrl('*/*/new', array('set'=>null, 'type'=>null)); + } +} diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php index 621d258500..a9321055e4 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php @@ -88,7 +88,7 @@ protected function _prepareLayout() /** * Don't display website tab for single mode */ - if (!Mage::app()->isSingleStoreMode()) { + if (!Mage::app()->isSingleStoreMode() && $this->_enabledWebsites()) { $this->addTab('websites', array( 'label' => Mage::helper('catalog')->__('Websites'), 'content' => $this->getLayout()->createBlock('adminhtml/catalog_product_edit_tab_websites')->toHtml(), @@ -209,4 +209,9 @@ public function setAttributeTabBlock($attributeTabBlock) $this->_attributeTabBlock = $attributeTabBlock; return $this; } + + protected function _enabledWebsites() + { + return true; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Edit.php b/app/code/core/Mage/Adminhtml/Block/Customer/Edit.php index 8bb1ff2dec..eb4e25fad0 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Edit.php @@ -43,7 +43,7 @@ public function __construct() 'label' => Mage::helper('customer')->__('Create Order'), 'onclick' => 'setLocation(\'' . $this->getCreateOrderUrl() . '\')', 'class' => 'add', - ), -1); + ), 0); } parent::__construct(); @@ -77,4 +77,24 @@ public function getValidationUrl() { return $this->getUrl('*/*/validate', array('_current'=>true)); } + + protected function _prepareLayout() + { + $this->_addButton('save_and_continue', array( + 'label' => Mage::helper('customer')->__('Save And Continue Edit'), + 'onclick' => 'saveAndContinueEdit(\''.$this->_getSaveAndContinueUrl().'\')', + 'class' => 'save' + ), 10); + + return parent::_prepareLayout(); + } + + protected function _getSaveAndContinueUrl() + { + return $this->getUrl('*/*/save', array( + '_current' => true, + 'back' => 'edit', + 'tab' => '{{tab_id}}' + )); + } } diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Renderer/Region.php b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Renderer/Region.php index 0cb24e3f9a..bdffd13d39 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Renderer/Region.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Renderer/Region.php @@ -54,7 +54,9 @@ public function render(Varien_Data_Form_Element_Abstract $element) $html.= ''; $html.= ''; $html.= ''; $html.= ''."\n"; return $html; diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tab/View.php b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tab/View.php index 95b5fc8f67..78d9089f0e 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tab/View.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tab/View.php @@ -130,24 +130,30 @@ public function getCustomerLog() public function getCreateDate() { - return $this->formatDate($this->getCustomer()->getCreatedAt(), Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); + $date = Mage::app()->getLocale()->date($this->getCustomer()->getCreatedAtTimestamp()); + return $this->formatDate($date, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); } public function getStoreCreateDate() { - $date = Mage::app()->getLocale()->storeDate($this->getCustomer()->getStoreId(), $this->getCustomer()->getCreatedAt(), true); + $date = Mage::app()->getLocale()->storeDate( + $this->getCustomer()->getStoreId(), + $this->getCustomer()->getCreatedAtTimestamp(), + true + ); return $this->formatDate($date, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); } public function getStoreCreateDateTimezone() { - $date = Mage::app()->getLocale()->storeDate($this->getCustomer()->getStoreId(), $this->getCustomer()->getCreatedAt(), true); - return $date->getTimezone(); + return Mage::app()->getStore($this->getCustomer()->getStoreId()) + ->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE); } public function getLastLoginDate() { - if ($date = $this->getCustomerLog()->getLoginAt()) { + if ($date = $this->getCustomerLog()->getLoginAtTimestamp()) { + $date = Mage::app()->getLocale()->date($date); return $this->formatDate($date, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); } return Mage::helper('customer')->__('Never'); @@ -155,14 +161,21 @@ public function getLastLoginDate() public function getStoreLastLoginDate() { - $date = Mage::app()->getLocale()->storeDate($this->getCustomer()->getStoreId(), $this->getCustomer()->getLoginAt(), true); - return $this->formatDate($date, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); + if ($date = $this->getCustomerLog()->getLoginAtTimestamp()) { + $date = Mage::app()->getLocale()->storeDate( + $this->getCustomer()->getStoreId(), + $date, + true + ); + return $this->formatDate($date, Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM, true); + } + return Mage::helper('customer')->__('Never'); } public function getStoreLastLoginDateTimezone() { - $date = Mage::app()->getLocale()->storeDate($this->getCustomer()->getStoreId(), $this->getCustomer()->getLoginAt(), true); - return $date->getTimezone(); + return Mage::app()->getStore($this->getCustomer()->getStoreId()) + ->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE); } public function getCurrentStatus() diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php index 142de13698..deea5eb545 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Edit/Tabs.php @@ -102,8 +102,20 @@ protected function _beforeToHtml() 'url' => $this->getUrl('*/*/productTags', array('_current' => true)), )); } + + $this->_updateActiveTab(); Varien_Profiler::stop('customer/tabs'); return parent::_beforeToHtml(); } -} + protected function _updateActiveTab() + { + $tabId = $this->getRequest()->getParam('tab'); + if( $tabId ) { + $tabId = preg_replace("#{$this->getId()}_#", '', $tabId); + if($tabId) { + $this->setActiveTab($tabId); + } + } + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Grid.php b/app/code/core/Mage/Adminhtml/Block/Customer/Grid.php index 8f87f1ba05..6c0e0fcb0a 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Grid.php @@ -133,10 +133,7 @@ protected function _prepareColumns() )); if (!Mage::app()->isSingleStoreMode()) { - $websites = Mage::getModel('core/website')->getCollection() - ->setLoadDefault(true) - ->load() - ->toOptionHash(true); + $websites = Mage::getSingleton('adminhtml/system_store')->getWebsiteValuesForGridFilter(true, true); $this->addColumn('website_id', array( 'header' => Mage::helper('customer')->__('Website'), diff --git a/app/code/core/Mage/Adminhtml/Block/Dashboard.php b/app/code/core/Mage/Adminhtml/Block/Dashboard.php index 3851b87bb7..efa5f51e81 100644 --- a/app/code/core/Mage/Adminhtml/Block/Dashboard.php +++ b/app/code/core/Mage/Adminhtml/Block/Dashboard.php @@ -37,13 +37,6 @@ public function __construct() protected function _prepareLayout() { - $this->setChild('store_switcher', - $this->getLayout()->createBlock('adminhtml/store_switcher') - ->setUseConfirm(false) - ->setSwitchUrl($this->getUrl('*/*/*', array('store'=>null))) - ->setTemplate('dashboard/store/switcher.phtml') - ); - $this->setChild('lastOrders', $this->getLayout()->createBlock('adminhtml/dashboard_orders_grid') ); @@ -75,11 +68,6 @@ protected function _prepareLayout() parent::_prepareLayout(); } - public function getStoreSwitcherHtml() - { - return $this->getChildHtml('store_switcher'); - } - public function getSwitchUrl() { if ($url = $this->getData('switch_url')) { diff --git a/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Ordered.php b/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Ordered.php index 5b1d07faa5..df0bc7a287 100644 --- a/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Ordered.php +++ b/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Ordered.php @@ -55,7 +55,7 @@ protected function _prepareCollection() $collection = Mage::getResourceModel('reports/product_collection') ->addOrderedQty() - ->addAttributeToSelect('*') + ->addAttributeToSelect(array('name', 'price')) ->setStoreId($storeId) ->addStoreFilter($storeId) ->setOrder('ordered_qty', 'desc'); diff --git a/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Viewed.php b/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Viewed.php index 15d9a84e9c..2d538c528c 100644 --- a/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Viewed.php +++ b/app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products/Viewed.php @@ -52,12 +52,11 @@ protected function _prepareCollection() } else { $storeId = (int)$this->getParam('store'); } - $collection = Mage::getResourceModel('reports/product_collection') ->addAttributeToSelect('*') + ->addViewsCount() ->setStoreId($storeId) - ->addStoreFilter($storeId) - ->addViewsCount(); + ->addStoreFilter($storeId); $this->setCollection($collection); diff --git a/app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php b/app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php index d22e19f278..9a5a5896e0 100644 --- a/app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php @@ -164,11 +164,7 @@ protected function _getOptions($optionsArray) */ protected function _getWebsiteOptions() { - $options = array(); - foreach (Mage::app()->getWebsites() as $website) { - $options[$website->getId()] = $website->getName(); - } - return $options; + return Mage::getModel('adminhtml/system_store')->getWebsiteValuesForGridFilter(); } /** @@ -178,15 +174,7 @@ protected function _getWebsiteOptions() */ protected function _getStoreGroupOptions() { - $options = array(); - foreach (Mage::app()->getWebsites() as $website) { - /* @var $website Mage_Core_Model_Website */ - foreach ($website->getGroups() as $group) { - /* @var $group Mage_Core_Model_Store_Group */ - $options[$group->getId()] = $group->getName(); - } - } - return $options; + return Mage::getModel('adminhtml/system_store')->getStoreGroupValuesForGridFilter(); } /** @@ -196,12 +184,7 @@ protected function _getStoreGroupOptions() */ protected function _getStoreOptions() { - $options = array(); - foreach (Mage::app()->getStores() as $store) { - /* @var $store Mage_Core_Model_Store */ - $options[$store->getId()] = $store->getName(); - } - return $options; + return Mage::getModel('adminhtml/system_store')->getStoreValuesForGridFilter(); } protected function _prepareMassaction() diff --git a/app/code/core/Mage/Adminhtml/Block/Notification/Window.php b/app/code/core/Mage/Adminhtml/Block/Notification/Window.php index a0e549aac7..830bdc985f 100644 --- a/app/code/core/Mage/Adminhtml/Block/Notification/Window.php +++ b/app/code/core/Mage/Adminhtml/Block/Notification/Window.php @@ -28,8 +28,8 @@ class Mage_Adminhtml_Block_Notification_Window extends Mage_Adminhtml_Block_Noti { protected $_available = null; - protected $_httpsObjectUrl = 'https://widgets.magentocommerce.com/messagePopupWindow'; - protected $_httpObjectUrl = 'http://widgets.magentocommerce.com/messagePopupWindow'; + protected $_httpsObjectUrl = 'https://widgets.magentocommerce.com/notificationPopup'; + protected $_httpObjectUrl = 'http://widgets.magentocommerce.com/notificationPopup'; protected $_aclResourcePath = 'admin/system/adminnotification/show_toolbar'; @@ -124,4 +124,4 @@ protected function _isAllowed() return true; } } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Adminhtml/Block/Page/Menu.php b/app/code/core/Mage/Adminhtml/Block/Page/Menu.php index 1f9d052db0..e74b930f4c 100644 --- a/app/code/core/Mage/Adminhtml/Block/Page/Menu.php +++ b/app/code/core/Mage/Adminhtml/Block/Page/Menu.php @@ -53,8 +53,7 @@ public function getCacheKey() { // getting roles for current user, for now one role per user $roles = implode('', Mage::getSingleton('admin/session')->getUser()->getRoles()); - $a = explode('/', $this->getActive()); - return 'admin_top_nav_'.$a[0].'_'.$roles.'_'.Mage::app()->getLocale()->getLocaleCode(); + return 'admin_top_nav_'.$this->getActive().'_'.$roles.'_'.Mage::app()->getLocale()->getLocaleCode(); } public function getMenuArray() diff --git a/app/code/core/Mage/Adminhtml/Block/Permissions/Editroles.php b/app/code/core/Mage/Adminhtml/Block/Permissions/Editroles.php index 109f685330..558bfbece0 100644 --- a/app/code/core/Mage/Adminhtml/Block/Permissions/Editroles.php +++ b/app/code/core/Mage/Adminhtml/Block/Permissions/Editroles.php @@ -24,7 +24,8 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_Adminhtml_Block_Permissions_Editroles extends Mage_Adminhtml_Block_Widget_Tabs { +class Mage_Adminhtml_Block_Permissions_Editroles extends Mage_Adminhtml_Block_Widget_Tabs +{ public function __construct() { parent::__construct(); @@ -33,32 +34,23 @@ public function __construct() $this->setTitle(Mage::helper('adminhtml')->__('Role Information')); } - protected function _beforeToHtml() + protected function _prepareLayout() { $roleId = $this->getRequest()->getParam('rid', false); $role = Mage::getModel("admin/roles") ->load($roleId); - $this->addTab('info', array( - 'label' => Mage::helper('adminhtml')->__('Role Info'), - 'title' => Mage::helper('adminhtml')->__('Role Info'), - 'content' => $this->getLayout()->createBlock('adminhtml/permissions_tab_roleinfo')->setRole($role)->toHtml(), - 'active' => true - )); + $this->addTab('info', $this->getLayout()->createBlock('adminhtml/permissions_tab_roleinfo')->setRole($role)->setActive(true)); + $this->addTab('account', $this->getLayout()->createBlock('adminhtml/permissions_tab_rolesedit', 'adminhtml.permissions.tab.rolesedit')); - $this->addTab('account', array( - 'label' => Mage::helper('adminhtml')->__('Role Resources'), - 'title' => Mage::helper('adminhtml')->__('Role Resources'), - 'content' => $this->getLayout()->createBlock('adminhtml/permissions_tab_rolesedit')->toHtml(), - )); - - if( intval($roleId) > 0 ) { + if (intval($roleId) > 0) { $this->addTab('roles', array( 'label' => Mage::helper('adminhtml')->__('Role Users'), 'title' => Mage::helper('adminhtml')->__('Role Users'), 'content' => $this->getLayout()->createBlock('adminhtml/permissions_tab_rolesusers', 'role.users.grid')->toHtml(), )); } - return parent::_beforeToHtml(); + + return parent::_prepareLayout(); } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Adminhtml/Block/Permissions/Roles.php b/app/code/core/Mage/Adminhtml/Block/Permissions/Roles.php index 65a04dab3b..01c9f6d503 100644 --- a/app/code/core/Mage/Adminhtml/Block/Permissions/Roles.php +++ b/app/code/core/Mage/Adminhtml/Block/Permissions/Roles.php @@ -33,19 +33,23 @@ */ class Mage_Adminhtml_Block_Permissions_Roles extends Mage_Adminhtml_Block_Template { - public function __construct() - { - parent::__construct(); - $this->setTemplate('permissions/roles.phtml'); - } - + /** + * Get URL of adding new record + * + * @return string + */ public function getAddNewUrl() { return $this->getUrl('*/*/editrole'); } + /** + * Get grid HTML + * + * @return unknown + */ public function getGridHtml() { - return $this->getLayout()->createBlock('adminhtml/permissions_grid_role')->toHtml(); + return $this->getChild('grid')->toHtml(); } } diff --git a/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Roleinfo.php b/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Roleinfo.php index 058e7bceb7..af3ac2bf0d 100644 --- a/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Roleinfo.php +++ b/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Roleinfo.php @@ -28,17 +28,32 @@ * implementing now * */ -class Mage_Adminhtml_Block_Permissions_Tab_Roleinfo extends Mage_Adminhtml_Block_Widget_Form +class Mage_Adminhtml_Block_Permissions_Tab_Roleinfo extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface { - public function __construct() + public function getTabLabel() { - parent::__construct(); + return Mage::helper('adminhtml')->__('Role Info'); + } + + public function getTabTitle() + { + return $this->getTabLabel(); + } + + public function canShowTab() + { + return true; + } + + public function isHidden() + { + return false; } public function _beforeToHtml() { - $this->_initForm(); + $this->_initForm(); - return parent::_beforeToHtml(); + return parent::_beforeToHtml(); } protected function _initForm() diff --git a/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Rolesedit.php b/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Rolesedit.php index d7921ed0f6..ba2ec2cc51 100644 --- a/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Rolesedit.php +++ b/app/code/core/Mage/Adminhtml/Block/Permissions/Tab/Rolesedit.php @@ -24,9 +24,50 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -class Mage_Adminhtml_Block_Permissions_Tab_Rolesedit extends Mage_Adminhtml_Block_Widget_Form { +class Mage_Adminhtml_Block_Permissions_Tab_Rolesedit extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface +{ + /** + * Get tab label + * + * @return string + */ + public function getTabLabel() + { + return Mage::helper('adminhtml')->__('Role Resources'); + } + + /** + * Get tab title + * + * @return string + */ + public function getTabTitle() + { + return $this->getTabLabel(); + } + + /** + * Whether tab is available + * + * @return bool + */ + public function canShowTab() + { + return true; + } + + /** + * Whether tab is visible + * + * @return bool + */ + public function isHidden() + { + return false; + } - public function __construct() { + public function __construct() + { parent::__construct(); $rid = Mage::app()->getRequest()->getParam('rid', false); diff --git a/app/code/core/Mage/Adminhtml/Block/Report/Grid.php b/app/code/core/Mage/Adminhtml/Block/Report/Grid.php index f3021ddc53..2b9ba3f398 100644 --- a/app/code/core/Mage/Adminhtml/Block/Report/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Report/Grid.php @@ -168,6 +168,10 @@ protected function _prepareCollection() $collection->setPageSize($this->getSubReportSize()); $this->setCollection($collection); + + Mage::dispatchEvent('adminhtml_widget_grid_filter_collection', + array('collection' => $this->getCollection(), 'filter_values' => $this->_filterValues) + ); } protected function _setFilterValues($data) diff --git a/app/code/core/Mage/Adminhtml/Block/Report/Product/Downloads/Grid.php b/app/code/core/Mage/Adminhtml/Block/Report/Product/Downloads/Grid.php index a5fc3890bf..dc94b6cfda 100644 --- a/app/code/core/Mage/Adminhtml/Block/Report/Product/Downloads/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Report/Product/Downloads/Grid.php @@ -57,10 +57,13 @@ protected function _prepareCollection() $collection = Mage::getResourceModel('reports/product_downloads_collection') ->addAttributeToSelect('*') ->setStoreId($storeId) - ->addStoreFilter($storeId) ->addAttributeToFilter('type_id', array(Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE)) ->addSummary(); + if( $storeId ) { + $collection->addStoreFilter($storeId); + } + $this->setCollection($collection); return parent::_prepareCollection(); } diff --git a/app/code/core/Mage/Adminhtml/Block/Report/Product/Lowstock/Grid.php b/app/code/core/Mage/Adminhtml/Block/Report/Product/Lowstock/Grid.php index 7740e87d69..fd3671fdce 100644 --- a/app/code/core/Mage/Adminhtml/Block/Report/Product/Lowstock/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Report/Product/Lowstock/Grid.php @@ -59,7 +59,6 @@ protected function _prepareCollection() $collection = Mage::getModel('catalog/product')->getCollection() ->addAttributeToSelect('*') ->setStoreId($storeId) - ->addStoreFilter($storeId) ->addAttributeToFilter('type_id', array( Mage_Catalog_Model_Product_Type::TYPE_SIMPLE, Mage_Catalog_Model_Product_Type::TYPE_VIRTUAL @@ -72,6 +71,10 @@ protected function _prepareCollection() 'left') ->setOrder('qty', 'asc'); + if( $storeId ) { + $collection->addStoreFilter($storeId); + } + $this->setCollection($collection); return parent::_prepareCollection(); } diff --git a/app/code/core/Mage/Adminhtml/Block/Report/Shopcart/Product/Grid.php b/app/code/core/Mage/Adminhtml/Block/Report/Shopcart/Product/Grid.php index 1faeb5dfc2..fee94f3108 100644 --- a/app/code/core/Mage/Adminhtml/Block/Report/Shopcart/Product/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Report/Shopcart/Product/Grid.php @@ -46,7 +46,6 @@ protected function _prepareCollection() ->addAttributeToSelect('name') ->addAttributeToSelect('price') ->setStoreId('') - ->addStoreFilter('') ->addCartsCount() ->addOrdersCount() ->setSelectCountSqlType(Mage_Reports_Model_Mysql4_Product_Collection::SELECT_COUNT_SQL_TYPE_CART); diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage.php index bc0710d30b..3e4dc70cf2 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage.php @@ -18,23 +18,26 @@ * 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_Adminhmtml - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Adminhtml + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Adminhtml order create gift message block * - * @category Mage - * @package Mage_Adminhmtml + * @category Mage + * @package Mage_Adminhtml * @author Magento Core Team */ class Mage_Adminhtml_Block_Sales_Order_Create_Giftmessage extends Mage_Adminhtml_Block_Sales_Order_Create_Abstract { + /** + * Constructor + */ public function __construct() { parent::__construct(); diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Items/Grid.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Items/Grid.php index 61759af21f..18c86a0c14 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Items/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Items/Grid.php @@ -120,7 +120,6 @@ public function isAllowedForGiftMessage($item) public function getSubtotal() { -// return '66'; $totals = $this->getQuote()->getTotals(); if (isset($totals['subtotal'])) { return $totals['subtotal']->getValue(); @@ -130,7 +129,6 @@ public function getSubtotal() public function getSubtotalWithDiscount() { -// return '55'; return $this->getQuote()->getShippingAddress()->getSubtotalWithDiscount(); } @@ -188,35 +186,19 @@ public function getCustomOptions(Mage_Sales_Model_Quote_Item $item) foreach (explode(',', $optionIds->getValue()) as $optionId) { if ($option = $item->getProduct()->getOptionById($optionId)) { $optionValue = $item->getOptionByCode('option_' . $option->getId())->getValue(); + $optionStr .= $option->getTitle() . ':'; - if ($option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - foreach (explode(',', $optionValue) as $_value) { - $optionStr .= $option->getValueById($_value)->getTitle() . ', '; - } - $optionStr = Mage::helper('core/string')->substr($optionStr, 0, -2); - } elseif ($option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $optionStr .= $option->getValueById($optionValue)->getTitle(); - } else { - $optionStr .= $optionValue; - } + + $quoteItemOption = $item->getOptionByCode('option_' . $option->getId()); + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setQuoteItemOption($quoteItemOption); + + $optionStr .= $group->getEditableOptionValue($quoteItemOption->getValue()); $optionStr .= "\n"; } } } - foreach ($item->getProduct()->getOptions() as $option) { - if ($option->getIsRequire() && !$item->getOptionByCode('option_'.$option->getId())) { - $optionStr .= $option->getTitle() . ':' . "\n"; - } - } - if ($additionalOptions = $item->getOptionByCode('additional_options')) { - $this->_moveToCustomerStorage = false; - foreach (unserialize($additionalOptions->getValue()) as $additionalOption) { - $optionStr .= $additionalOption['label'] . ':' . $additionalOption['value'] . "\n"; - } - } - $optionStr = $this->helper('core/string')->substr($optionStr, 0, -1); - return $optionStr; } @@ -259,4 +241,9 @@ public function getInclExclTaxMessage() return Mage::helper('sales')->__('* - Enter custom price excluding tax'); } } + + public function getStore() + { + return $this->getQuote()->getStore(); + } } diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Compared.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Compared.php index b6ae085250..8e42948d13 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Compared.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Compared.php @@ -59,6 +59,7 @@ public function getItemCollection() if ($collection = $this->getCreateOrderModel()->getCustomerCompareList()) { $collection = $collection->getItemCollection() ->useProductItem(true) + ->setStoreId($this->getQuote()->getStoreId()) ->setStoreId($this->getStoreId()) ->setCustomerId($this->getCustomerId()) ->addAttributeToSelect('name') diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Pviewed.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Pviewed.php index 7bc2a299fe..a8903feccf 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Pviewed.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Sidebar/Pviewed.php @@ -74,6 +74,7 @@ public function getItemCollection() if ($productIds) { $productCollection = Mage::getModel('catalog/product') ->getCollection() + ->setStoreId($this->getQuote()->getStoreId()) ->addAttributeToSelect('name') ->addAttributeToSelect('price') ->addAttributeToSelect('small_image') diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Item.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Item.php new file mode 100644 index 0000000000..87876eacec --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Item.php @@ -0,0 +1,36 @@ +setCanDisplayTotalPaid($this->getParentBlock()->getCanDisplayTotalPaid()); + $this->setCanDisplayTotalRefunded($this->getParentBlock()->getCanDisplayTotalRefunded()); + $this->setCanDisplayTotalDue($this->getParentBlock()->getCanDisplayTotalDue()); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php index 7db8e059be..985dac33c6 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php @@ -31,7 +31,7 @@ * @package Mage_Adminhtml * @author Magento Core Team */ -class Mage_Adminhtml_Block_Sales_Order_Totals_Tax extends Mage_Adminhtml_Block_Sales_Order_Abstract +class Mage_Adminhtml_Block_Sales_Order_Totals_Tax extends Mage_Adminhtml_Block_Sales_Order_Totals { /** * Retrieve required options from parent diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php index 9bf627035f..cf75fcb5e1 100644 --- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php +++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php @@ -62,7 +62,8 @@ public function __construct() if ($nonEditableTypes) { $this->_updateButton('order_edit', 'onclick', 'if (!confirm(\'' . Mage::helper('sales')->__( - 'This order contains items (%s) that cannot be added to order from admin interface and will not be put to new order.', + 'This order contains (%s) items and therefore cannot be edited through the admin interface at this time, if you wish to continue editing the (%s) items will be removed, the order will be cancelled and a new order will be placed', + implode(', ', $nonEditableTypes), implode(', ', $nonEditableTypes) ) . '\')) return false;' . $onclickJs ); diff --git a/app/code/core/Mage/Adminhtml/Block/Store/Switcher.php b/app/code/core/Mage/Adminhtml/Block/Store/Switcher.php index 460051dcbc..a849dcd179 100644 --- a/app/code/core/Mage/Adminhtml/Block/Store/Switcher.php +++ b/app/code/core/Mage/Adminhtml/Block/Store/Switcher.php @@ -70,8 +70,9 @@ public function getStoreCollection($group) $group = Mage::getModel('core/store_group')->load($group); } $stores = $group->getStoreCollection(); - if (!empty($this->_storeIds)) { - $stores->addIdFilter($this->_storeIds); + $_storeIds = $this->getStoreIds(); + if (!empty($_storeIds)) { + $stores->addIdFilter($_storeIds); } return $stores; } @@ -95,6 +96,11 @@ public function setStoreIds($storeIds) return $this; } + public function getStoreIds() + { + return $this->_storeIds; + } + public function isShow() { return !Mage::app()->isSingleStoreMode(); diff --git a/app/code/core/Mage/Adminhtml/Block/System/Cache/Edit.php b/app/code/core/Mage/Adminhtml/Block/System/Cache/Edit.php index e428fd6879..89333db0ed 100644 --- a/app/code/core/Mage/Adminhtml/Block/System/Cache/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/System/Cache/Edit.php @@ -1,158 +1,176 @@ - - */ -class Mage_Adminhtml_Block_System_Cache_Edit extends Mage_Adminhtml_Block_Widget -{ - public function __construct() - { - parent::__construct(); - $this->setTemplate('system/cache/edit.phtml'); - $this->setTitle('Cache Management'); - } - - protected function _prepareLayout() - { - $this->setChild('save_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('adminhtml')->__('Save cache settings'), - 'onclick' => 'configForm.submit()', - 'class' => 'save', - )) - ); - return parent::_prepareLayout(); - } - - public function getSaveButtonHtml() - { - return $this->getChildHtml('save_button'); - } - - public function getSaveUrl() - { - return $this->getUrl('*/*/save', array('_current'=>true)); - } - - public function initForm() - { - $this->setChild('form', - $this->getLayout()->createBlock('adminhtml/system_cache_form') - ->initForm() - ); - return $this; - } - - /** - * Retrieve Catalog Tools Data - * - * @return array - */ - public function getCatalogData() - { - $layeredIsDisabled = false; - $warning = ''; - - $flag = Mage::getModel('catalogindex/catalog_index_flag')->loadSelf(); - switch ($flag->getState()) { - case Mage_CatalogIndex_Model_Catalog_Index_Flag::STATE_QUEUED: - $layeredAction = Mage::helper('adminhtml')->__('Queued... Cancel'); - //$layeredIsDisabled = true; - break; - case Mage_CatalogIndex_Model_Catalog_Index_Flag::STATE_RUNNING: - $layeredAction = Mage::helper('adminhtml')->__('Running... Kill'); - $warning = Mage::helper('adminhtml')->__('Do you really want to KILL parallel process and start new indexing process?'); - //$layeredIsDisabled = true; - //$nowIsDisabled = true; - break; - default: - $layeredAction = Mage::helper('adminhtml')->__('Queue Refresh'); - //$layeredIsDisabled = false; - break; - } - - return array( - 'refresh_catalog_rewrites' => array( - 'label' => Mage::helper('adminhtml')->__('Catalog Rewrites'), - 'buttons' => array( - array( - 'name' => 'refresh_catalog_rewrites', - 'action' => Mage::helper('adminhtml')->__('Refresh'), - ) - ), - ), - 'clear_images_cache' => array( - 'label' => Mage::helper('adminhtml')->__('Images Cache'), - 'buttons' => array( - array( - 'name' => 'clear_images_cache', - 'action' => Mage::helper('adminhtml')->__('Clear'), - ) - ), - ), - 'refresh_layered_navigation' => array( - 'label' => Mage::helper('adminhtml')->__('Layered Navigation Indices'), - 'buttons' => array( - array( - 'name' => 'refresh_layered_navigation', - 'action' => $layeredAction, - 'disabled' => $layeredIsDisabled, - ), - array( - 'name' => 'refresh_layered_navigation_now', - 'action' => Mage::helper('adminhtml')->__('Refresh Now*'), - 'comment' => Mage::helper('adminhtml')->__('* - If indexing is in progress, it will be killed and new indexing process will start'), - 'warning' => $warning, - ) - ), - ), - 'rebuild_search_index' => array( - 'label' => Mage::helper('adminhtml')->__('Search Index'), - 'buttons' => array( - array( - 'name' => 'rebuild_search_index', - 'action' => Mage::helper('adminhtml')->__('Rebuild'), - ) - ), - ), - 'rebuild_inventory_stock_status' => array( - 'label' => Mage::helper('adminhtml')->__('Inventory Stock Status'), - 'buttons' => array( - array( - 'name' => 'rebuild_inventory_stock_status', - 'action' => Mage::helper('adminhtml')->__('Refresh'), - ) - ), - ), - ); - } + + */ +class Mage_Adminhtml_Block_System_Cache_Edit extends Mage_Adminhtml_Block_Widget +{ + public function __construct() + { + parent::__construct(); + $this->setTemplate('system/cache/edit.phtml'); + $this->setTitle('Cache Management'); + } + + protected function _prepareLayout() + { + $this->setChild('save_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('adminhtml')->__('Save cache settings'), + 'onclick' => 'configForm.submit()', + 'class' => 'save', + )) + ); + return parent::_prepareLayout(); + } + + public function getSaveButtonHtml() + { + return $this->getChildHtml('save_button'); + } + + public function getSaveUrl() + { + return $this->getUrl('*/*/save', array('_current'=>true)); + } + + public function initForm() + { + $this->setChild('form', + $this->getLayout()->createBlock('adminhtml/system_cache_form') + ->initForm() + ); + return $this; + } + + /** + * Retrieve Catalog Tools Data + * + * @return array + */ + public function getCatalogData() + { + $layeredIsDisabled = false; + $warning = ''; + + $flag = Mage::getModel('catalogindex/catalog_index_flag')->loadSelf(); + switch ($flag->getState()) { + case Mage_CatalogIndex_Model_Catalog_Index_Flag::STATE_QUEUED: + $layeredAction = Mage::helper('adminhtml')->__('Queued... Cancel'); + //$layeredIsDisabled = true; + break; + case Mage_CatalogIndex_Model_Catalog_Index_Flag::STATE_RUNNING: + $layeredAction = Mage::helper('adminhtml')->__('Running... Kill'); + $warning = Mage::helper('adminhtml')->__('Do you really want to KILL parallel process and start new indexing process?'); + //$layeredIsDisabled = true; + //$nowIsDisabled = true; + break; + default: + $layeredAction = Mage::helper('adminhtml')->__('Queue Refresh'); + //$layeredIsDisabled = false; + break; + } + + return array( + 'refresh_catalog_rewrites' => array( + 'label' => Mage::helper('adminhtml')->__('Catalog Rewrites'), + 'buttons' => array( + array( + 'name' => 'refresh_catalog_rewrites', + 'action' => Mage::helper('adminhtml')->__('Refresh'), + ) + ), + ), + 'clear_images_cache' => array( + 'label' => Mage::helper('adminhtml')->__('Images Cache'), + 'buttons' => array( + array( + 'name' => 'clear_images_cache', + 'action' => Mage::helper('adminhtml')->__('Clear'), + ) + ), + ), + 'refresh_layered_navigation' => array( + 'label' => Mage::helper('adminhtml')->__('Layered Navigation Indices'), + 'buttons' => array( + array( + 'name' => 'refresh_layered_navigation', + 'action' => $layeredAction, + 'disabled' => $layeredIsDisabled, + ), + array( + 'name' => 'refresh_layered_navigation_now', + 'action' => Mage::helper('adminhtml')->__('Refresh Now*'), + 'comment' => Mage::helper('adminhtml')->__('* - If indexing is in progress, it will be killed and new indexing process will start'), + 'warning' => $warning, + ) + ), + ), + 'rebuild_search_index' => array( + 'label' => Mage::helper('adminhtml')->__('Search Index'), + 'buttons' => array( + array( + 'name' => 'rebuild_search_index', + 'action' => Mage::helper('adminhtml')->__('Rebuild'), + ) + ), + ), + 'rebuild_inventory_stock_status' => array( + 'label' => Mage::helper('adminhtml')->__('Inventory Stock Status'), + 'buttons' => array( + array( + 'name' => 'rebuild_inventory_stock_status', + 'action' => Mage::helper('adminhtml')->__('Refresh'), + ) + ), + ), + 'rebuild_flat_catalog_category' => array( + 'label' => Mage::helper('adminhtml')->__('Rebuild Flat Catalog Category'), + 'buttons' => array( + array( + 'name' => 'rebuild_flat_catalog_category', + 'action' => Mage::helper('adminhtml')->__('Rebuild'), + ) + ), + ), + 'rebuild_flat_catalog_product' => array( + 'label' => Mage::helper('adminhtml')->__('Rebuild Flat Catalog Product'), + 'buttons' => array( + array( + 'name' => 'rebuild_flat_catalog_product', + 'action' => Mage::helper('adminhtml')->__('Rebuild'), + ) + ), + ), + ); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatcatalog.php b/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatcatalog.php new file mode 100644 index 0000000000..c91c4d5abf --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatcatalog.php @@ -0,0 +1,46 @@ + + */ +class Mage_Adminhtml_Block_System_Config_Form_Field_Select_Flatcatalog extends Mage_Adminhtml_Block_System_Config_Form_Field +{ + protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) + { + if (!Mage::helper('catalog/category_flat')->isRebuilt()) { + $element->setDisabled('disabled') + ->setValue(0); + } + return parent::_getElementHtml($element); + } + +} diff --git a/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatproduct.php b/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatproduct.php new file mode 100644 index 0000000000..37a4f09fcd --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Select/Flatproduct.php @@ -0,0 +1,52 @@ + + */ +class Mage_Adminhtml_Block_System_Config_Form_Field_Select_Flatproduct + extends Mage_Adminhtml_Block_System_Config_Form_Field +{ + /** + * Retrieve Element HTML + * + * @param Varien_Data_Form_Element_Abstract $element + * @return string + */ + protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) { + if (!Mage::helper('catalog/product_flat')->isBuilt()) { + $element->setDisabled(true) + ->setValue(0); + } + return parent::_getElementHtml($element); + } + +} diff --git a/app/code/core/Mage/Adminhtml/Block/System/Config/Switcher.php b/app/code/core/Mage/Adminhtml/Block/System/Config/Switcher.php new file mode 100644 index 0000000000..dd09e14949 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Block/System/Config/Switcher.php @@ -0,0 +1,109 @@ +setTemplate('system/config/switcher.phtml'); + return parent::_prepareLayout(); + } + + /** + * Enter description here... + * + * @return array + */ + public function getStoreSelectOptions() + { + $section = $this->getRequest()->getParam('section'); + + $curWebsite = $this->getRequest()->getParam('website'); + $curStore = $this->getRequest()->getParam('store'); + + $storeModel = Mage::getSingleton('adminhtml/system_store'); + /* @var $storeModel Mage_Adminhtml_Model_System_Store */ + + $url = Mage::getModel('adminhtml/url'); + + $options = array(); + $options['default'] = array( + 'label' => Mage::helper('adminhtml')->__('Default Config'), + 'url' => $url->getUrl('*/*/*', array('section'=>$section)), + 'selected' => !$curWebsite && !$curStore, + 'style' => 'background:#ccc; font-weight:bold;', + ); + + foreach ($storeModel->getWebsiteCollection() as $website) { + $websiteShow = false; + foreach ($storeModel->getGroupCollection() as $group) { + if ($group->getWebsiteId() != $website->getId()) { + continue; + } + $groupShow = false; + foreach ($storeModel->getStoreCollection() as $store) { + if ($store->getGroupId() != $group->getId()) { + continue; + } + if (!$websiteShow) { + $websiteShow = true; + $options['website_' . $website->getCode()] = array( + 'label' => $website->getName(), + 'url' => $url->getUrl('*/*/*', array('section'=>$section, 'website'=>$website->getCode())), + 'selected' => !$curStore && $curWebsite == $website->getCode(), + 'style' => 'padding-left:16px; background:#DDD; font-weight:bold;', + ); + } + if (!$groupShow) { + $groupShow = true; + $options['group_' . $group->getId() . '_open'] = array( + 'is_group' => true, + 'is_close' => false, + 'label' => $group->getName(), + 'style' => 'padding-left:32px;' + ); + } + $options['store_' . $store->getCode()] = array( + 'label' => $store->getName(), + 'url' => $url->getUrl('*/*/*', array('section'=>$section, 'website'=>$website->getCode(), 'store'=>$store->getCode())), + 'selected' => $curStore == $store->getCode(), + 'style' => '', + ); + } + if ($groupShow) { + $options['group_' . $group->getId() . '_close'] = array( + 'is_group' => true, + 'is_close' => true, + ); + } + } + } + + return $options; + } + +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Category/Tree.php b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Category/Tree.php index 3aa248b257..b6548bb19a 100644 --- a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Category/Tree.php +++ b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Category/Tree.php @@ -127,6 +127,6 @@ protected function _getNodesArray($node) */ public function getLoadTreeUrl() { - return Mage::getUrl('*/*/categoriesJson'); + return Mage::helper('adminhtml')->getUrl('*/*/categoriesJson'); } } diff --git a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit.php b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit.php index 81924a4375..141b7e0e84 100644 --- a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit.php @@ -58,7 +58,7 @@ protected function _prepareLayout() $this->setTemplate('urlrewrite/edit.phtml'); $this->_addButton('back', array( 'label' => Mage::helper('adminhtml')->__('Back'), - 'onclick' => 'setLocation(\'' . Mage::getUrl('*/*/') . '\')', + 'onclick' => 'setLocation(\'' . Mage::helper('adminhtml')->getUrl('*/*/') . '\')', 'class' => 'back', 'level' => -1 )); @@ -67,16 +67,16 @@ protected function _prepareLayout() if ($this->getProductId()) { $this->setChild('product_link', $this->getLayout()->createBlock('adminhtml/urlrewrite_link') ->setData(array( - 'item_url' => Mage::getUrl('*/*/*') . 'product', + 'item_url' => Mage::helper('adminhtml')->getUrl('*/*/*') . 'product', 'item' => Mage::registry('current_product'), 'label' => Mage::helper('adminhtml')->__('Product:') )) ); } if ($this->getCategoryId()) { - $itemUrl = Mage::getUrl('*/*/*') . 'category'; + $itemUrl = Mage::helper('adminhtml')->getUrl('*/*/*') . 'category'; if ($this->getProductId()) { - $itemUrl = Mage::getUrl('*/*/*', array('product' => $this->getProductId())) . 'category'; + $itemUrl = Mage::helper('adminhtml')->getUrl('*/*/*', array('product' => $this->getProductId())) . 'category'; } $this->setChild('category_link', $this->getLayout()->createBlock('adminhtml/urlrewrite_link') ->setData(array( @@ -107,14 +107,14 @@ protected function _prepareLayout() $this->setChild('skip_categories', $this->getLayout()->createBlock('adminhtml/widget_button')->setData(array( 'label' => Mage::helper('adminhtml')->__('Skip category selection'), - 'onclick' => 'window.location = \'' . Mage::getUrl('*/*/*', array( + 'onclick' => 'window.location = \'' . Mage::helper('adminhtml')->getUrl('*/*/*', array( 'product' => $this->getProductId() )) . '\'', 'class' => 'save', 'level' => -1 )) ); - $this->_updateButton('back', 'onclick', 'setLocation(\'' . Mage::getUrl('*/*/edit') . 'product\')'); + $this->_updateButton('back', 'onclick', 'setLocation(\'' . Mage::helper('adminhtml')->getUrl('*/*/edit') . 'product\')'); } } // edit form for category @@ -161,7 +161,7 @@ protected function _setFormChild() $this->_addButton('delete', array( 'label' => Mage::helper('adminhtml')->__('Delete'), 'onclick' => 'deleteConfirm(\'' . Mage::helper('adminhtml')->__('Are you sure you want to do this?') - . '\', \'' . Mage::getUrl('*/*/delete', array('id' => $this->getUrlrewriteId())) . '\')', + . '\', \'' . Mage::helper('adminhtml')->getUrl('*/*/delete', array('id' => $this->getUrlrewriteId())) . '\')', 'class' => 'scalable delete', 'level' => -1 )); @@ -187,7 +187,7 @@ protected function _setFormChild() $suffix = 'category'; } } - $this->_updateButton('back', 'onclick', 'setLocation(\'' . Mage::getUrl('*/*/' . $action, $params) . $suffix . '\')'); + $this->_updateButton('back', 'onclick', 'setLocation(\'' . Mage::helper('adminhtml')->getUrl('*/*/' . $action, $params) . $suffix . '\')'); return $this; } diff --git a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit/Form.php b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit/Form.php index 672f31abd2..fe982f7daa 100644 --- a/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit/Form.php +++ b/app/code/core/Mage/Adminhtml/Block/Urlrewrite/Edit/Form.php @@ -192,7 +192,7 @@ protected function _prepareForm() )); $form->setUseContainer(true); - $form->setAction(Mage::getUrl('*/*/save', array( + $form->setAction(Mage::helper('adminhtml')->getUrl('*/*/save', array( 'id' => $model->getId(), 'product' => $product->getId(), 'category' => $category->getId(), diff --git a/app/code/core/Mage/Adminhtml/Block/Widget.php b/app/code/core/Mage/Adminhtml/Block/Widget.php index 537ef3a6f3..a5e8ce1f39 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget.php @@ -1,86 +1,85 @@ - - */ -class Mage_Adminhtml_Block_Widget extends Mage_Adminhtml_Block_Template -{ - public function getId() - { - if ($this->getData('id')===null) { - $this->setData('id', 'id_'.md5(microtime())); - } - return $this->getData('id'); - } - - public function getHtmlId() - { - return $this->getId(); - } - - public function getCurrentUrl($params=array()) - { - return $this->getUrl('*/*/*', array('_current'=>true)); - } - - protected function _addBreadcrumb($label, $title=null, $link=null) - { - $this->getLayout()->getBlock('breadcrumbs')->addLink($label, $title, $link); - } - - /** - * Create buttonn and return its html - * - * @param string $label - * @param string $onclick - * @param string $class - * @param string $id - * @return string - */ - public function getButtonHtml($label, $onclick, $class='', $id=null) { - return $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => $label, - 'onclick' => $onclick, - 'class' => $class, - 'type' => 'button', - 'id' => $id, - )) - ->toHtml(); - } - - public function getGlobalIcon() - { - return ''.$this->__('Global Attribute').''; - } - -} - + + */ +class Mage_Adminhtml_Block_Widget extends Mage_Adminhtml_Block_Template +{ + public function getId() + { + if ($this->getData('id')===null) { + $this->setData('id', 'id_'.md5(microtime())); + } + return $this->getData('id'); + } + + public function getHtmlId() + { + return $this->getId(); + } + + public function getCurrentUrl($params=array()) + { + return $this->getUrl('*/*/*', array('_current'=>true)); + } + + protected function _addBreadcrumb($label, $title=null, $link=null) + { + $this->getLayout()->getBlock('breadcrumbs')->addLink($label, $title, $link); + } + + /** + * Create buttonn and return its html + * + * @param string $label + * @param string $onclick + * @param string $class + * @param string $id + * @return string + */ + public function getButtonHtml($label, $onclick, $class='', $id=null) { + return $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => $label, + 'onclick' => $onclick, + 'class' => $class, + 'type' => 'button', + 'id' => $id, + )) + ->toHtml(); + } + + public function getGlobalIcon() + { + return ''.$this->__('Global Attribute').''; + } +} + diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Form.php b/app/code/core/Mage/Adminhtml/Block/Widget/Form.php index cdd8a2702d..59572f141d 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Form.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Form.php @@ -1,218 +1,242 @@ - - */ -class Mage_Adminhtml_Block_Widget_Form extends Mage_Adminhtml_Block_Widget -{ - - /** - * Form Object - * - * @var Varien_Data_Form - */ - protected $_form; - - /** - * Class constructor - * - */ - public function __construct() - { - parent::__construct(); - $this->setTemplate('widget/form.phtml'); - $this->setDestElementId('edit_form'); - $this->setShowGlobalIcon(false); - } - - /** - * Prepare block children and data - * - */ - protected function _prepareLayout() - { - Varien_Data_Form::setElementRenderer( - $this->getLayout()->createBlock('adminhtml/widget_form_renderer_element') - ); - Varien_Data_Form::setFieldsetRenderer( - $this->getLayout()->createBlock('adminhtml/widget_form_renderer_fieldset') - ); - Varien_Data_Form::setFieldsetElementRenderer( - $this->getLayout()->createBlock('adminhtml/widget_form_renderer_fieldset_element') - ); - } - - /** - * Get form object - * - * @return Varien_Data_Form - */ - public function getForm() - { - return $this->_form; - } - - /** - * Get form object - * - * @deprecated deprecated since version 1.2 - * @see getForm() - * @return Varien_Data_Form - */ - public function getFormObject() - { - return $this->getForm(); - } - - /** - * Get form HTML - * - * @return string - */ - public function getFormHtml() - { - if (is_object($this->getForm())) { - return $this->getForm()->getHtml(); - } - return ''; - } - - /** - * Set form object - * - * @param Varien_Data_Form $form - * @return Mage_Adminhtml_Block_Widget_Form - */ - public function setForm(Varien_Data_Form $form) - { - $this->_form = $form; - $this->_form->setParent($this); - $this->_form->setBaseUrl(Mage::getBaseUrl()); - return $this; - } - - /** - * Prepare form before rendering HTML - * - * @return Mage_Adminhtml_Block_Widget_Form - */ - protected function _prepareForm() - { - return $this; - } - - /** - * This method is called before rendering HTML - * - * @return Mage_Adminhtml_Block_Widget_Form - */ - protected function _beforeToHtml() - { - $this->_prepareForm(); - return parent::_beforeToHtml(); - } - - /** - * Enter description here... - * - * @param array $attributes attributes that are to be added - * @param Varien_Data_Form_Element_Fieldset $fieldset - * @param array $exclude attributes that should be skipped - */ - protected function _setFieldset($attributes, $fieldset, $exclude=array()) - { - $this->_addElementTypes($fieldset); - foreach ($attributes as $attribute) { - if (!$attribute || !$attribute->getIsVisible()) { - continue; - } - if ( ($inputType = $attribute->getFrontend()->getInputType()) - && !in_array($attribute->getAttributeCode(), $exclude) - && ('media_image' != $inputType) - ) { - $element = $fieldset->addField($attribute->getAttributeCode(), $inputType, - array( - 'name' => $attribute->getAttributeCode(), - 'label' => __($attribute->getFrontend()->getLabel()), - 'class' => $attribute->getFrontend()->getClass(), - 'required' => $attribute->getIsRequired(), - 'note' => $attribute->getNote(), - ) - ) - ->setEntityAttribute($attribute); - - $element->setAfterElementHtml($this->_getAdditionalElementHtml($element)); - - if ($inputType == 'select' || $inputType == 'multiselect') { - $element->setValues($attribute->getSource()->getAllOptions(true, true)); - } elseif ($inputType == 'date') { - $element->setImage($this->getSkinUrl('images/grid-cal.gif')); - $element->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT)); - } - } - } - } - - /** - * Enter description here... - * - * @param Varien_Data_Form_Abstract $baseElement - */ - protected function _addElementTypes(Varien_Data_Form_Abstract $baseElement) - { - $types = $this->_getAdditionalElementTypes(); - foreach ($types as $code => $className) { - $baseElement->addType($code, $className); - } - } - - /** - * Enter description here... - * - * @return array - */ - protected function _getAdditionalElementTypes() - { - return array(); - } - - /** - * Enter description here... - * - * @param Varien_Data_Form_Element_Abstract $element - * @return string - */ - protected function _getAdditionalElementHtml($element) - { - return ''; - } - -} + + */ +class Mage_Adminhtml_Block_Widget_Form extends Mage_Adminhtml_Block_Widget +{ + + /** + * Form Object + * + * @var Varien_Data_Form + */ + protected $_form; + + /** + * Class constructor + * + */ + public function __construct() + { + parent::__construct(); + $this->setTemplate('widget/form.phtml'); + $this->setDestElementId('edit_form'); + $this->setShowGlobalIcon(false); + } + + /** + * Prepare block children and data + * + */ + protected function _prepareLayout() + { + Varien_Data_Form::setElementRenderer( + $this->getLayout()->createBlock('adminhtml/widget_form_renderer_element') + ); + Varien_Data_Form::setFieldsetRenderer( + $this->getLayout()->createBlock('adminhtml/widget_form_renderer_fieldset') + ); + Varien_Data_Form::setFieldsetElementRenderer( + $this->getLayout()->createBlock('adminhtml/widget_form_renderer_fieldset_element') + ); + } + + /** + * Get form object + * + * @return Varien_Data_Form + */ + public function getForm() + { + return $this->_form; + } + + /** + * Get form object + * + * @deprecated deprecated since version 1.2 + * @see getForm() + * @return Varien_Data_Form + */ + public function getFormObject() + { + return $this->getForm(); + } + + /** + * Get form HTML + * + * @return string + */ + public function getFormHtml() + { + if (is_object($this->getForm())) { + return $this->getForm()->getHtml(); + } + return ''; + } + + /** + * Set form object + * + * @param Varien_Data_Form $form + * @return Mage_Adminhtml_Block_Widget_Form + */ + public function setForm(Varien_Data_Form $form) + { + $this->_form = $form; + $this->_form->setParent($this); + $this->_form->setBaseUrl(Mage::getBaseUrl()); + return $this; + } + + /** + * Prepare form before rendering HTML + * + * @return Mage_Adminhtml_Block_Widget_Form + */ + protected function _prepareForm() + { + return $this; + } + + /** + * This method is called before rendering HTML + * + * @return Mage_Adminhtml_Block_Widget_Form + */ + protected function _beforeToHtml() + { + $this->_prepareForm(); + $this->_initFormValues(); + Mage::dispatchEvent('adminhtml_widget_form_before_tohtml', + array('form' => $this->getForm(), 'layout' => $this->getLayout()) + ); + return parent::_beforeToHtml(); + } + + /** + * Initialize form fileds values + * Method will be called after prepareForm and can be used for field values initialization + * + * @return Mage_Adminhtml_Block_Widget_Form + */ + protected function _initFormValues() + { + return $this; + } + + /** + * Set Fieldset to Form + * + * @param array $attributes attributes that are to be added + * @param Varien_Data_Form_Element_Fieldset $fieldset + * @param array $exclude attributes that should be skipped + */ + protected function _setFieldset($attributes, $fieldset, $exclude=array()) + { + $this->_addElementTypes($fieldset); + foreach ($attributes as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if (!$attribute || !$attribute->getIsVisible()) { + continue; + } + if ( ($inputType = $attribute->getFrontend()->getInputType()) + && !in_array($attribute->getAttributeCode(), $exclude) + && ('media_image' != $inputType) + ) { + + $fieldType = $inputType; + $rendererClass = $attribute->getFrontend()->getInputRendererClass(); + if (!empty($rendererClass)) { + $fieldType = $inputType . '_' . $attribute->getAttributeCode(); + $fieldset->addType($fieldType, $rendererClass); + } + + $element = $fieldset->addField($attribute->getAttributeCode(), $fieldType, + array( + 'name' => $attribute->getAttributeCode(), + 'label' => __($attribute->getFrontend()->getLabel()), + 'class' => $attribute->getFrontend()->getClass(), + 'required' => $attribute->getIsRequired(), + 'note' => $attribute->getNote(), + ) + ) + ->setEntityAttribute($attribute); + + $element->setAfterElementHtml($this->_getAdditionalElementHtml($element)); + + if ($inputType == 'select' || $inputType == 'multiselect') { + $element->setValues($attribute->getSource()->getAllOptions(true, true)); + } elseif ($inputType == 'date') { + $element->setImage($this->getSkinUrl('images/grid-cal.gif')); + $element->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT)); + } + } + } + } + + /** + * Add new element type + * + * @param Varien_Data_Form_Abstract $baseElement + */ + protected function _addElementTypes(Varien_Data_Form_Abstract $baseElement) + { + $types = $this->_getAdditionalElementTypes(); + foreach ($types as $code => $className) { + $baseElement->addType($code, $className); + } + } + + /** + * Retrieve predefined additional element types + * + * @return array + */ + protected function _getAdditionalElementTypes() + { + return array(); + } + + /** + * Enter description here... + * + * @param Varien_Data_Form_Element_Abstract $element + * @return string + */ + protected function _getAdditionalElementHtml($element) + { + return ''; + } + +} diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Form/Container.php b/app/code/core/Mage/Adminhtml/Block/Widget/Form/Container.php index 7eeb1cc592..a77e2a7c9c 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Form/Container.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Form/Container.php @@ -1,172 +1,176 @@ - - */ - -class Mage_Adminhtml_Block_Widget_Form_Container extends Mage_Adminhtml_Block_Widget_Container -{ - protected $_objectId = 'id'; - protected $_formScripts = array(); - protected $_formInitScripts = array(); - protected $_mode = 'edit'; - protected $_blockGroup = 'adminhtml'; - - public function __construct() - { - parent::__construct(); - - $this->setTemplate('widget/form/container.phtml'); - - $this->_addButton('back', array( - 'label' => Mage::helper('adminhtml')->__('Back'), - 'onclick' => 'setLocation(\'' . $this->getBackUrl() . '\')', - 'class' => 'back', - ), -1); - $this->_addButton('reset', array( - 'label' => Mage::helper('adminhtml')->__('Reset'), - 'onclick' => 'setLocation(window.location.href)', - ), -1); - - $objId = $this->getRequest()->getParam($this->_objectId); - - if (! empty($objId)) { - $this->_addButton('delete', array( - 'label' => Mage::helper('adminhtml')->__('Delete'), - 'class' => 'delete', - 'onclick' => 'deleteConfirm(\''. Mage::helper('adminhtml')->__('Are you sure you want to do this?') - .'\', \'' . $this->getDeleteUrl() . '\')', - )); - } - - $this->_addButton('save', array( - 'label' => Mage::helper('adminhtml')->__('Save'), - 'onclick' => 'editForm.submit();', - 'class' => 'save', - ), 1); - } - - protected function _prepareLayout() - { - $this->setChild('form', $this->getLayout()->createBlock($this->_blockGroup . '/' . $this->_controller . '_' . $this->_mode . '_form')); - return parent::_prepareLayout(); - } - - /** - * Get URL for back (reset) button - * - * @return string - */ - public function getBackUrl() - { - return $this->getUrl('*/*/'); - } - - public function getDeleteUrl() - { - return $this->getUrl('*/*/delete', array($this->_objectId => $this->getRequest()->getParam($this->_objectId))); - } - - /** - * Get form save URL - * - * @deprecated - * @see getFormActionUrl() - * @return string - */ - public function getSaveUrl() - { - return $this->getFormActionUrl(); - } - - /** - * Get form action URL - * - * @return string - */ - public function getFormActionUrl() - { - if ($this->hasFormActionUrl()) { - return $this->getData('form_action_url'); - } - return $this->getUrl('*/' . $this->_controller . '/save'); - } - - public function getFormHtml() - { - $this->getChild('form')->setData('action', $this->getSaveUrl()); - return $this->getChildHtml('form'); - } - - public function getFormInitScripts() - { - if ( !empty($this->_formInitScripts) && is_array($this->_formInitScripts) ) { - return ''; - } - return ''; - } - - public function getFormScripts() - { - if ( !empty($this->_formScripts) && is_array($this->_formScripts) ) { - return ''; - } - return ''; - } - - public function getHeaderWidth() - { - return ''; - } - - public function getHeaderCssClass() - { - return 'icon-head head-' . strtr($this->_controller, '_', '-'); - } - - public function getHeaderHtml() - { - return '

' . $this->getHeaderText() . '

'; - } - - /** - * Set data object and pass it to form - * - * @param Varien_Object $object - * @return Mage_Adminhtml_Block_Widget_Form_Container - */ - public function setDataObject($object) - { - $this->getChild('form')->setDataObject($object); - return $this->setData('data_object', $object); - } - -} + + */ + +class Mage_Adminhtml_Block_Widget_Form_Container extends Mage_Adminhtml_Block_Widget_Container +{ + protected $_objectId = 'id'; + protected $_formScripts = array(); + protected $_formInitScripts = array(); + protected $_mode = 'edit'; + protected $_blockGroup = 'adminhtml'; + + public function __construct() + { + parent::__construct(); + + if (!$this->hasData('template')) { + $this->setTemplate('widget/form/container.phtml'); + } + + $this->_addButton('back', array( + 'label' => Mage::helper('adminhtml')->__('Back'), + 'onclick' => 'setLocation(\'' . $this->getBackUrl() . '\')', + 'class' => 'back', + ), -1); + $this->_addButton('reset', array( + 'label' => Mage::helper('adminhtml')->__('Reset'), + 'onclick' => 'setLocation(window.location.href)', + ), -1); + + $objId = $this->getRequest()->getParam($this->_objectId); + + if (! empty($objId)) { + $this->_addButton('delete', array( + 'label' => Mage::helper('adminhtml')->__('Delete'), + 'class' => 'delete', + 'onclick' => 'deleteConfirm(\''. Mage::helper('adminhtml')->__('Are you sure you want to do this?') + .'\', \'' . $this->getDeleteUrl() . '\')', + )); + } + + $this->_addButton('save', array( + 'label' => Mage::helper('adminhtml')->__('Save'), + 'onclick' => 'editForm.submit();', + 'class' => 'save', + ), 1); + } + + protected function _prepareLayout() + { + if ($this->_blockGroup && $this->_controller && $this->_mode) { + $this->setChild('form', $this->getLayout()->createBlock($this->_blockGroup . '/' . $this->_controller . '_' . $this->_mode . '_form')); + } + return parent::_prepareLayout(); + } + + /** + * Get URL for back (reset) button + * + * @return string + */ + public function getBackUrl() + { + return $this->getUrl('*/*/'); + } + + public function getDeleteUrl() + { + return $this->getUrl('*/*/delete', array($this->_objectId => $this->getRequest()->getParam($this->_objectId))); + } + + /** + * Get form save URL + * + * @deprecated + * @see getFormActionUrl() + * @return string + */ + public function getSaveUrl() + { + return $this->getFormActionUrl(); + } + + /** + * Get form action URL + * + * @return string + */ + public function getFormActionUrl() + { + if ($this->hasFormActionUrl()) { + return $this->getData('form_action_url'); + } + return $this->getUrl('*/' . $this->_controller . '/save'); + } + + public function getFormHtml() + { + $this->getChild('form')->setData('action', $this->getSaveUrl()); + return $this->getChildHtml('form'); + } + + public function getFormInitScripts() + { + if ( !empty($this->_formInitScripts) && is_array($this->_formInitScripts) ) { + return ''; + } + return ''; + } + + public function getFormScripts() + { + if ( !empty($this->_formScripts) && is_array($this->_formScripts) ) { + return ''; + } + return ''; + } + + public function getHeaderWidth() + { + return ''; + } + + public function getHeaderCssClass() + { + return 'icon-head head-' . strtr($this->_controller, '_', '-'); + } + + public function getHeaderHtml() + { + return '

' . $this->getHeaderText() . '

'; + } + + /** + * Set data object and pass it to form + * + * @param Varien_Object $object + * @return Mage_Adminhtml_Block_Widget_Form_Container + */ + public function setDataObject($object) + { + $this->getChild('form')->setDataObject($object); + return $this->setData('data_object', $object); + } + +} diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php b/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php index f49a4cfed6..1a8890cf09 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php @@ -117,6 +117,8 @@ class Mage_Adminhtml_Block_Widget_Grid extends Mage_Adminhtml_Block_Widget */ protected $_filterVisibility = true; + protected $_filterValues = false; + /** * Massage block visibility * @@ -310,6 +312,7 @@ public function getColumns() protected function _setFilterValues($data) { + $this->_filterValues = $data; foreach ($this->getColumns() as $columnId => $column) { if (isset($data[$columnId]) && (!empty($data[$columnId]) || strlen($data[$columnId]) > 0) && $column->getFilter()) { $column->getFilter()->setValue($data[$columnId]); @@ -365,6 +368,10 @@ protected function _prepareCollection() $this->_setFilterValues($this->_defaultFilter); } + Mage::dispatchEvent('adminhtml_widget_grid_filter_collection', + array('collection' => $this->getCollection(), 'filter_values' => $this->_filterValues) + ); + if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) { $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc'; $this->_columns[$columnId]->setDir($dir); diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column.php b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column.php index f28fcbee1d..bbcf9a3b10 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column.php @@ -147,7 +147,14 @@ public function setRenderer($renderer) protected function _getRendererByType() { - switch (strtolower($this->getType())) { + $type = strtolower($this->getType()); + $renderers = $this->getGrid()->getColumnRenderers(); + + if (is_array($renderers) && isset($renderers[$type])) { + return $renderers[$type]; + } + + switch ($type) { case 'date': $rendererClass = 'adminhtml/widget_grid_column_renderer_date'; break; @@ -230,7 +237,13 @@ public function setFilter($column) protected function _getFilterByType() { - switch (strtolower($this->getType())) { + $type = strtolower($this->getType()); + $filters = $this->getGrid()->getColumnFilters(); + if (is_array($filters) && isset($filters[$type])) { + return $filters[$type]; + } + + switch ($type) { case 'datetime': $filterClass = 'adminhtml/widget_grid_column_filter_datetime'; break; diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Datetime.php b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Datetime.php index 9bf826146d..c955fb2ff6 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Datetime.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Datetime.php @@ -49,7 +49,7 @@ public function getValue($index=null) if (is_array($value)) { $value['datetime'] = true; } - if (!empty($value['to'])) { + if (!empty($value['to']) && !$this->getColumn()->getFilterTime()) { $datetimeTo = $value['to']; //set end of the day $datetimeTo->addSecond(self::END_OF_DAY_IN_SECONDS); @@ -57,4 +57,105 @@ public function getValue($index=null) return $value; } + /* + * Convert given date to default (UTC) timezone + * + * @param string $date + * @param string $locale + * @return Zend_Date + */ + protected function _convertDate($date, $locale) + { + if ($this->getColumn()->getFilterTime()) { + try { + $dateObj = $this->getLocale()->date(null, null, $locale, false); + + //set default timezone for store (admin) + $dateObj->setTimezone(Mage::app()->getStore()->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE)); + + //set date with applying timezone of store + $dateObj->set( + $date, + $this->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT), + $locale + ); + + //convert store date to default date in UTC timezone without DST + $dateObj->setTimezone(Mage_Core_Model_Locale::DEFAULT_TIMEZONE); + + return $dateObj; + } + catch (Exception $e) { + return null; + } + } + + return parent::_convertDate($date, $locale); + } + + /** + * Render filter html + * + * @return string + */ + public function getHtml() + { + $htmlId = $this->_getHtmlId() . microtime(true); + $format = $this->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); + + if ($this->getColumn()->getFilterTime()) { + $format .= ' ' . $this->getLocale()->getTimeStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); + } + + $html = '
+ ' . Mage::helper('adminhtml')->__('From').': + + +
'; + $html.= '
+ ' . Mage::helper('adminhtml')->__('To').' : + + +
'; + $html.= ''; + $html.= ''; + return $html; + } + + /** + * Return escaped value for calendar + * + * @param string $index + * @return string + */ + public function getEscapedValue($index=null) + { + if ($this->getColumn()->getFilterTime()) { + $value = $this->getValue($index); + if ($value instanceof Zend_Date) { + return $value->toString($this->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT)); + } + return $value; + } + + return parent::getEscapedValue($index); + } + } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php index 62376d5a33..6981bfa1ec 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php @@ -45,11 +45,13 @@ public function __construct() $this->setTemplate('widget/grid/container.phtml'); - $this->_addButton('add', array( - 'label' => $this->getAddButtonLabel(), - 'onclick' => 'setLocation(\'' . $this->getCreateUrl() .'\')', - 'class' => 'add', - )); + if( $this->_enabledAddNewButton() === true ) { + $this->_addButton('add', array( + 'label' => $this->getAddButtonLabel(), + 'onclick' => 'setLocation(\'' . $this->getCreateUrl() .'\')', + 'class' => 'add', + )); + } } protected function _prepareLayout() @@ -99,4 +101,8 @@ public function getHeaderWidth() return 'width:50%;'; } + protected function _enabledAddNewButton() + { + return true; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php index e42c694aa5..38044813b2 100644 --- a/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php +++ b/app/code/core/Mage/Adminhtml/Block/Widget/Tabs.php @@ -88,7 +88,10 @@ public function addTab($tabId, $tab) $this->_tabs[$tabId] = new Varien_Object($tab); } elseif ($tab instanceof Varien_Object) { - $this->_tabs[$tabId] = $tab; + $this->_tabs[$tabId] = $tab; + if (!$this->_tabs[$tabId]->hasTabId()) { + $this->_tabs[$tabId]->setTabId($tabId); + } } elseif (is_string($tab)) { if (strpos($tab, '/')) { @@ -178,6 +181,24 @@ protected function _beforeToHtml() } elseif ($activeTabId = Mage::getSingleton('admin/session')->getActiveTabId()) { $this->_setActiveTab($activeTabId); } + + $_new = array(); + foreach( $this->_tabs as $key => $tab ) { + foreach( $this->_tabs as $k => $t ) { + if( $t->getAfter() == $key ) { + $_new[$key] = $tab; + $_new[$k] = $t; + } else { + if( !$tab->getAfter() || !in_array($tab->getAfter(), array_keys($this->_tabs)) ) { + $_new[$key] = $tab; + } + } + } + } + + $this->_tabs = $_new; + unset($_new); + $this->assign('tabs', $this->_tabs); return parent::_beforeToHtml(); } diff --git a/app/code/core/Mage/Adminhtml/Controller/Action.php b/app/code/core/Mage/Adminhtml/Controller/Action.php index 52a859f543..b0f8a468ac 100644 --- a/app/code/core/Mage/Adminhtml/Controller/Action.php +++ b/app/code/core/Mage/Adminhtml/Controller/Action.php @@ -120,7 +120,6 @@ public function hasAction($action) public function preDispatch() { Mage::getDesign()->setArea('adminhtml') - // [bug] this value will be overriden by defaults, how can it be set in adminhtml/etc/config.xml? ->setPackageName((string)Mage::getConfig()->getNode('stores/admin/design/package/name')) ->setTheme((string)Mage::getConfig()->getNode('stores/admin/design/theme/default')); @@ -130,19 +129,28 @@ public function preDispatch() parent::preDispatch(); - if ($this->getRequest()->isPost() - && !$this->_validateFormKey() - && Mage::getSingleton('admin/session')->isLoggedIn()) { - + $_isValidFormKey = true; + $_isValidSecretKey = true; + $_keyErrorMsg = ''; + if (Mage::getSingleton('admin/session')->isLoggedIn()) { + if ($this->getRequest()->isPost()) { + $_isValidFormKey = $this->_validateFormKey(); + $_keyErrorMsg = 'Invalid Form Key'; + } elseif (Mage::getSingleton('adminhtml/url')->useSecretKey()) { + $_isValidSecretKey = $this->_validateSecretKey(); + $_keyErrorMsg = 'Invalid Secret Key'; + } + } + if (!$_isValidFormKey || !$_isValidSecretKey) { $this->setFlag('', self::FLAG_NO_DISPATCH, true); $this->setFlag('', self::FLAG_NO_POST_DISPATCH, true); if ($this->getRequest()->getQuery('isAjax', false) || $this->getRequest()->getQuery('ajax', false)) { $this->getResponse()->setBody(Zend_Json::encode(array( 'error' => true, - 'error_msg' => Mage::helper('adminhtml')->__('Invalid Form Key') + 'error_msg' => Mage::helper('adminhtml')->__($_keyErrorMsg) ))); } else { - $this->_redirectReferer(); + $this->_redirect('*/index/index'); } return $this; } @@ -337,6 +345,16 @@ protected function _redirect($path, $arguments=array()) protected function _forward($action, $controller = null, $module = null, array $params = null) { $this->_getSession()->setIsUrlNotice($this->getFlag('', self::FLAG_IS_URLS_CHECKED)); + + // Save original values for controller and action included in secret key Urls + $_urlModel = Mage::getSingleton('adminhtml/url'); + if (!$_urlModel->getOriginalControllerName()) { + $_urlModel->setOriginalControllerName($this->getRequest()->getControllerName()); + } + if (!$_urlModel->getOriginalActionName()) { + $_urlModel->setOriginalActionName($this->getRequest()->getActionName()); + } + return parent::_forward($action, $controller, $module, $params); } @@ -351,4 +369,21 @@ public function getUrl($route='', $params=array()) { return Mage::helper('adminhtml')->getUrl($route, $params); } + + + /** + * Validate Secret Key + * + * @return bool + */ + protected function _validateSecretKey() + { + $url = Mage::getSingleton('adminhtml/url'); + + if (!($secretKey = $this->getRequest()->getParam(Mage_Adminhtml_Model_Url::SECRET_KEY_PARAM_NAME, null)) + || $secretKey != $url->getSecretKey($url->getOriginalControllerName(), $url->getOriginalActionName())) { + return false; + } + return true; + } } diff --git a/app/code/core/Mage/Adminhtml/Helper/Catalog.php b/app/code/core/Mage/Adminhtml/Helper/Catalog.php index e8b0b3ec80..5043b98839 100644 --- a/app/code/core/Mage/Adminhtml/Helper/Catalog.php +++ b/app/code/core/Mage/Adminhtml/Helper/Catalog.php @@ -33,17 +33,61 @@ */ class Mage_Adminhtml_Helper_Catalog extends Mage_Core_Helper_Abstract { - + /** + * Attribute Tab block name for product edit + * + * @var string + */ protected $_attributeTabBlock = null; + /** + * Attribute Tab block name for category edit + * + * @var string + */ + protected $_categoryAttributeTabBlock; + + /** + * Retrieve Attribute Tab Block Name for Product Edit + * + * @return string + */ public function getAttributeTabBlock() { return $this->_attributeTabBlock; } + /** + * Set Custom Attribute Tab Block Name for Product Edit + * + * @param string $attributeTabBlock + * @return Mage_Adminhtml_Helper_Catalog + */ public function setAttributeTabBlock($attributeTabBlock) { $this->_attributeTabBlock = $attributeTabBlock; return $this; } + + /** + * Retrieve Attribute Tab Block Name for Category Edit + * + * @return string + */ + public function getCategoryAttributeTabBlock() + { + return $this->_categoryAttributeTabBlock; + } + + /** + * Set Custom Attribute Tab Block Name for Category Edit + * + * @param string $attributeTabBlock + * @return Mage_Adminhtml_Helper_Catalog + */ + public function setCategoryAttributeTabBlock($attributeTabBlock) + { + $this->_categoryAttributeTabBlock = $attributeTabBlock; + return $this; + } } diff --git a/app/code/core/Mage/Adminhtml/Helper/Data.php b/app/code/core/Mage/Adminhtml/Helper/Data.php index 90a42200e0..354fe4812b 100644 --- a/app/code/core/Mage/Adminhtml/Helper/Data.php +++ b/app/code/core/Mage/Adminhtml/Helper/Data.php @@ -51,9 +51,14 @@ public function setPageHelpUrl($url=null) $frontName = $request->getModuleName(); $router = Mage::app()->getFrontController()->getRouterByFrontName($frontName); + + $frontModule = $router->getModuleByFrontName($frontName); + if (is_array($frontModule)) { + $frontModule = $frontModule[0]; + } $url = 'http://www.magentocommerce.com/gethelp/'; $url.= Mage::app()->getLocale()->getLocaleCode().'/'; - $url.= $router->getModuleByFrontName($frontName).'/'; + $url.= $frontModule.'/'; $url.= $request->getControllerName().'/'; $url.= $request->getActionName().'/'; diff --git a/app/code/core/Mage/Adminhtml/Model/Extension.php b/app/code/core/Mage/Adminhtml/Model/Extension.php index 1a0979cdc7..ce663c42a5 100644 --- a/app/code/core/Mage/Adminhtml/Model/Extension.php +++ b/app/code/core/Mage/Adminhtml/Model/Extension.php @@ -288,6 +288,7 @@ public function savePackage() $this->unsPackageXml(); $this->unsRoles(); $xml = Mage::helper('core')->assocToXml($this->getData()); + $xml = new Varien_Simplexml_Element($xml->asXML()); // prepare dir to save $parts = explode(DS, $fileName); @@ -299,7 +300,7 @@ public function savePackage() } } - if (!@file_put_contents($dir . DS . $fileName . '.xml', $xml->asXML())) { + if (!@file_put_contents($dir . DS . $fileName . '.xml', $xml->asNiceXml())) { return false; } diff --git a/app/code/core/Mage/Adminhtml/Model/Observer.php b/app/code/core/Mage/Adminhtml/Model/Observer.php index 10a41f9dd2..df4a9b41e8 100644 --- a/app/code/core/Mage/Adminhtml/Model/Observer.php +++ b/app/code/core/Mage/Adminhtml/Model/Observer.php @@ -39,7 +39,7 @@ public function bindLocale($observer) { if ($locale=$observer->getEvent()->getLocale()) { if ($choosedLocale = Mage::getSingleton('adminhtml/session')->getLocale()) { - $locale->setDefaultLocale($choosedLocale); + $locale->setLocaleCode($choosedLocale); } } return $this; diff --git a/app/code/core/Mage/Adminhtml/Model/Sales/Order/Create.php b/app/code/core/Mage/Adminhtml/Model/Sales/Order/Create.php index 648de3dcb3..279f6eb48e 100644 --- a/app/code/core/Mage/Adminhtml/Model/Sales/Order/Create.php +++ b/app/code/core/Mage/Adminhtml/Model/Sales/Order/Create.php @@ -49,8 +49,6 @@ class Mage_Adminhtml_Model_Sales_Order_Create extends Varien_Object protected $_needCollect; - protected $_productOptions = array(); - /** * @var Mage_Customer_Model_Customer */ @@ -573,9 +571,6 @@ public function addProduct($product, $qty=1) $product->setSkipCheckRequiredOption(true); $item = $this->getQuote()->addProduct($product, $qty); $product->unsSkipCheckRequiredOption(); - if (is_string($item)) { - Mage::throwException($item); - } $item->checkData(); } @@ -673,78 +668,39 @@ public function updateQuoteItems($data) */ protected function _parseOptions(Mage_Sales_Model_Quote_Item $item, $additionalOptions) { - if (!isset($this->_productOptions[$item->getProduct()->getId()])) { - foreach ($item->getProduct()->getOptions() as $_option) { - /* @var $option Mage_Catalog_Model_Product_Option */ - $this->_productOptions[$item->getProduct()->getId()][$_option->getTitle()] = array('option_id' => $_option->getId()); - if ($_option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $optionValues = array(); - foreach ($_option->getValues() as $_value) { - /* @var $value Mage_Catalog_Model_Product_Option_Value */ - $optionValues[$_value->getTitle()] = $_value->getId(); - } - $this->_productOptions[$item->getProduct()->getId()][$_option->getTitle()]['values'] = $optionValues; - } else { - $this->_productOptions[$item->getProduct()->getId()][$_option->getTitle()]['values'] = array(); - } - } - } + $productOptions = Mage::getSingleton('catalog/product_option_type_default') + ->setProduct($item->getProduct()) + ->getProductOptions(); $newOptions = array(); $newAdditionalOptions = array(); + foreach (explode("\n", $additionalOptions) as $_additionalOption) { if (strlen(trim($_additionalOption))) { try { - list($label,$value) = explode(':', $_additionalOption); + list($label,$value) = explode(':', $_additionalOption, 2); } catch (Exception $e) { Mage::throwException(Mage::helper('adminhtml')->__('One of options row has error')); } $label = trim($label); $value = trim($value); if (empty($value)) { + die($label); continue; } - if (isset($this->_productOptions[$item->getProduct()->getId()])) { - if (array_key_exists($label, $this->_productOptions[$item->getProduct()->getId()])) { - $optionId = $this->_productOptions[$item->getProduct()->getId()][$label]['option_id']; - $group = $item->getProduct() - ->getOptionById($optionId) - ->getGroupByType(); - $type = $item->getProduct() - ->getOptionById($optionId) - ->getType(); - if (($type == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $type == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE)) { - $_values = array(); - foreach (explode(',', $value) as $_value) { - $_value = trim($_value); - if (array_key_exists($_value, $this->_productOptions[$item->getProduct()->getId()][$label]['values'])) { - $_values[] = $this->_productOptions[$item->getProduct()->getId()][$label]['values'][$_value]; - } else { - $_values = array(); - $newAdditionalOptions[] = array( - 'label' => $label, - 'value' => $value - ); - break; - } - } - if (count($_values)) { - $newOptions[$optionId] = implode(',',$_values); - } - } elseif ($group == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - if (array_key_exists($value, $this->_productOptions[$item->getProduct()->getId()][$label]['values'])) { - $newOptions[$optionId] = $this->_productOptions[$item->getProduct()->getId()][$label]['values'][$value]; - } else { - $newAdditionalOptions[] = array( - 'label' => $label, - 'value' => $value - ); - } - } else { - $newOptions[$optionId] = $value; - } + if (array_key_exists($label, $productOptions)) { + $optionId = $productOptions[$label]['option_id']; + $option = $item->getProduct()->getOptionById($optionId); + + $group = Mage::getSingleton('catalog/product_option')->groupFactory($option->getType()) + ->setOption($option) + ->setProduct($item->getProduct()); + + $parsedValue = $group->parseOptionValue($value, $productOptions[$label]['values']); + + if ($parsedValue !== null) { + $newOptions[$optionId] = $parsedValue; } else { $newAdditionalOptions[] = array( 'label' => $label, @@ -827,13 +783,14 @@ protected function _prepareOptionsForRequest($item) $newInfoOptions = array(); if ($optionIds = $item->getOptionByCode('option_ids')) { foreach (explode(',', $optionIds->getValue()) as $optionId) { - $optionType = $item->getProduct()->getOptionById($optionId)->getType(); + $option = $item->getProduct()->getOptionById($optionId); $optionValue = $item->getOptionByCode('option_'.$optionId)->getValue(); - if ($optionType == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $optionType == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - $optionValue = explode(',', $optionValue); - } - $newInfoOptions[$optionId] = $optionValue; + + $group = Mage::getSingleton('catalog/product_option')->groupFactory($option->getType()) + ->setOption($option) + ->setQuoteItem($item); + + $newInfoOptions[$optionId] = $group->prepareOptionValueForRequest($optionValue); } } return $newInfoOptions; @@ -1069,7 +1026,7 @@ public function createOrder() /* @var $item Mage_Sales_Model_Quote_Item */ $orderItem = $quoteConvert->itemToOrderItem($item); $options = array(); - if ($productOptions = $item->getProduct()->getTypeInstance()->getOrderOptions()) { + if ($productOptions = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct())) { $productOptions['info_buyRequest']['options'] = $this->_prepareOptionsForRequest($item); $options = $productOptions; } @@ -1092,7 +1049,7 @@ public function createOrder() /* @var $item Mage_Sales_Model_Quote_Item */ $orderItem = $quoteConvert->itemToOrderItem($item); $options = array(); - if ($productOptions = $item->getProduct()->getTypeInstance()->getOrderOptions()) { + if ($productOptions = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct())) { $productOptions['info_buyRequest']['options'] = $this->_prepareOptionsForRequest($item); $options = $productOptions; } diff --git a/app/code/core/Mage/Adminhtml/Model/Search/Order.php b/app/code/core/Mage/Adminhtml/Model/Search/Order.php index 8b038b0399..2ba1cb5b9a 100644 --- a/app/code/core/Mage/Adminhtml/Model/Search/Order.php +++ b/app/code/core/Mage/Adminhtml/Model/Search/Order.php @@ -50,6 +50,7 @@ public function load() ->joinAttribute('shipping_postcode', 'order_address/postcode', 'shipping_address_id') ->addAttributeToFilter(array( + array('attribute'=>'increment_id', 'like'=>$this->getQuery().'%'), array('attribute'=>'billing_firstname', 'like'=>$this->getQuery().'%'), array('attribute'=>'billing_lastname', 'like'=>$this->getQuery().'%'), array('attribute'=>'billing_telephone', 'like'=>$this->getQuery().'%'), diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usesecretkey.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usesecretkey.php new file mode 100644 index 0000000000..e1b7c6e4fa --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usesecretkey.php @@ -0,0 +1,42 @@ + + */ +class Mage_Adminhtml_Model_System_Config_Backend_Admin_Usesecretkey extends Mage_Core_Model_Config_Data +{ + protected function _afterSave() + { + Mage::getSingleton('adminhtml/url')->renewSecretUrls(); + return $this; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Encrypted.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Encrypted.php index 5f48190739..9381443f7a 100644 --- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Encrypted.php +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Encrypted.php @@ -35,7 +35,7 @@ class Mage_Adminhtml_Model_System_Config_Backend_Encrypted extends Mage_Core_Mod { /** - * Enter description here... + * Decrypt value after loading * */ protected function _afterLoad() @@ -47,15 +47,28 @@ protected function _afterLoad() } /** - * Enter description here... + * Encrypt value before saving * */ protected function _beforeSave() { $value = (string)$this->getValue(); + // don't change value, if an obscured value came + if (preg_match('/^\*+$/', $this->getValue())) { + $value = $this->getOldValue(); + } if (!empty($value) && ($encrypted = Mage::helper('core')->encrypt($value))) { $this->setValue($encrypted); } } + /** + * Get & decrypt old value from configuration + * + * @return string + */ + public function getOldValue() + { + return Mage::helper('core')->decrypt(parent::getOldValue()); + } } diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/ListSort.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/ListSort.php new file mode 100644 index 0000000000..f554199c14 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/ListSort.php @@ -0,0 +1,66 @@ + + */ +class Mage_Adminhtml_Model_System_Config_Source_Catalog_ListSort +{ + /** + * Retrieve option values array + * + * @return array + */ + public function toOptionArray() + { + $options = array(); + $options[] = array( + 'label' => Mage::helper('catalog')->__('Best Value'), + 'value' => 'position' + ); + foreach ($this->_getCatalogConfig()->getAttributesUsedForSortBy() as $attribute) { + $options[] = array( + 'label' => Mage::helper('catalog')->__($attribute['frontend_label']), + 'value' => $attribute['attribute_code'] + ); + } + return $options; + } + + /** + * Retrieve Catalog Config Singleton + * + * @return Mage_Catalog_Model_Config + */ + protected function _getCatalogConfig() { + return Mage::getSingleton('catalog/config'); + } +} diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/TimeFormat.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/TimeFormat.php new file mode 100644 index 0000000000..2b2c41bf82 --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Catalog/TimeFormat.php @@ -0,0 +1,36 @@ + '12h', 'label' => Mage::helper('adminhtml')->__('12h AM/PM')), + array('value' => '24h', 'label' => Mage::helper('adminhtml')->__('24h')), + ); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Website.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Website.php index 3fb303fad2..1ba3b4f9ee 100644 --- a/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Website.php +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Website.php @@ -41,6 +41,11 @@ public function toOptionArray() } } } - return $this->_options; + return $this->_cleanupOptions($this->_options); + } + + protected function _cleanupOptions($options) + { + return $options; } } \ No newline at end of file diff --git a/app/code/core/Mage/Adminhtml/Model/System/Store.php b/app/code/core/Mage/Adminhtml/Model/System/Store.php index 74ae32e0a9..85b7be37c7 100644 --- a/app/code/core/Mage/Adminhtml/Model/System/Store.php +++ b/app/code/core/Mage/Adminhtml/Model/System/Store.php @@ -81,6 +81,7 @@ protected function _loadWebsiteCollection() foreach (Mage::getModel('core/website')->getCollection() as $website) { $this->_websiteCollection[$website->getId()] = $website; } + $this->_cleanupCollection(); return $this; } @@ -95,6 +96,7 @@ protected function _loadGroupCollection() foreach (Mage::getModel('core/store_group')->getCollection() as $group) { $this->_groupCollection[$group->getId()] = $group; } + $this->_cleanupCollection(); return $this; } @@ -109,10 +111,16 @@ protected function _loadStoreCollection() foreach (Mage::getModel('core/store')->getCollection() as $store) { $this->_storeCollection[$store->getId()] = $store; } + $this->_cleanupCollection(); return $this; } - public function getStoreValuesForForm($empty = false, $all = false) + protected function _cleanupCollection() + { + return $this; + } + + protected function _getDefaultStoreOptions($empty=false, $all=false) { $options = array(); if ($empty) { @@ -128,6 +136,18 @@ public function getStoreValuesForForm($empty = false, $all = false) ); } + return $options; + } + + protected function _forceDisableWebsitesAll() + { + return false; + } + + public function getStoreValuesForForm($empty = false, $all = false) + { + $options = $this->_getDefaultStoreOptions($empty, $all); + foreach ($this->_websiteCollection as $website) { $websiteShow = false; foreach ($this->_groupCollection as $group) { @@ -175,7 +195,7 @@ public function getWebsiteValuesForForm($empty = false, $all = false) 'value' => '' ); } - if ($all) { + if ($all && !$this->_forceDisableWebsitesAll()) { $options[] = array( 'label' => Mage::helper('adminhtml')->__('Admin'), 'value' => 0 @@ -191,6 +211,32 @@ public function getWebsiteValuesForForm($empty = false, $all = false) return $options; } + public function getWebsiteValuesForGridFilter() + { + $options = array(); + foreach ($this->_websiteCollection as $website) { + $options[$website->getId()] = $website->getName(); + } + return $options; + } + + public function getStoreValuesForGridFilter() + { + $options = array(); + foreach ($this->_storeCollection as $store) { + $options[$store->getId()] = $store->getName(); + } + return $options; + } + + public function getStoreGroupValuesForGridFilter() + { + foreach ($this->_groupCollection as $group) { + $options[$group->getId()] = $group->getName(); + } + return $options; + } + /** * Retrieve Website name by Id * diff --git a/app/code/core/Mage/Adminhtml/Model/Url.php b/app/code/core/Mage/Adminhtml/Model/Url.php index 57a768c976..97124f5578 100644 --- a/app/code/core/Mage/Adminhtml/Model/Url.php +++ b/app/code/core/Mage/Adminhtml/Model/Url.php @@ -25,6 +25,11 @@ */ class Mage_Adminhtml_Model_Url extends Mage_Core_Model_Url { + /** + * Secret key query param name + */ + const SECRET_KEY_PARAM_NAME = 'key'; + /** * Retrieve is secure mode for ULR logic * @@ -38,4 +43,89 @@ public function getSecure() return Mage::getStoreConfigFlag('web/secure/use_in_adminhtml'); } + /** + * Force strip secret key param if _nosecret param specified + * + * @return Mage_Core_Model_Url + */ + public function setRouteParams(array $data, $unsetOldParams=true) + { + if (isset($data['_nosecret'])) { + $this->setNoSecret(true); + unset($data['_nosecret']); + } + + return parent::setRouteParams($data, $unsetOldParams); + } + + /** + * Custom logic to retrieve Urls + * + * @param string $routePath + * @param array $routeParams + * @return string + */ + public function getUrl($routePath=null, $routeParams=null) + { + $result = parent::getUrl($routePath, $routeParams); + + if (!$this->useSecretKey() || $this->getNoSecret()) { + return $result; + } + + $_route = $this->getRouteName() ? $this->getRouteName() : '*'; + $_controller = $this->getControllerName() ? $this->getControllerName() : $this->getDefaultControllerName(); + $_action = $this->getActionName() ? $this->getActionName() : $this->getDefaultActionName(); + $secret = array(self::SECRET_KEY_PARAM_NAME => $this->getSecretKey($_controller, $_action)); + if (is_array($routeParams)) { + $routeParams = array_merge($secret, $routeParams); + } else { + $routeParams = $secret; + } + if (is_array($this->getRouteParams())) { + $routeParams = array_merge($this->getRouteParams(), $routeParams); + } + return parent::getUrl("{$_route}/{$_controller}/{$_action}", $routeParams); + } + + /** + * Generate secret key for controller and action based on form key + * + * @param string $controller Controller name + * @param string $action Action name + * @return string + */ + public function getSecretKey($controller = null, $action = null) + { + $salt = Mage::getSingleton('core/session')->getFormKey(); + if (!$controller) { + $controller = $this->getRequest()->getControllerName(); + } + if (!$action) { + $action = $this->getRequest()->getActionName(); + } + + $secret = $controller . $action . $salt; + return Mage::helper('core')->getHash($secret); + } + + /** + * Return secret key settings flag + * + * @return boolean + */ + public function useSecretKey() + { + return Mage::getStoreConfigFlag('admin/security/use_form_key'); + } + + /** + * Refresh admin menu cache etc. + * + * @return Mage_Adminhtml_Model_Url + */ + public function renewSecretUrls() + { + Mage::app()->cleanCache(array(Mage_Adminhtml_Block_Page_Menu::CACHE_TAGS)); + } } diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php index 14a3f66ccf..dda56170bc 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php @@ -111,7 +111,9 @@ public function editAction() ->getLastEditedCategory(true); - if ($_prevCategoryId && !$this->getRequest()->getQuery('isAjax')) { + if ($_prevCategoryId + && !$this->getRequest()->getQuery('isAjax') + && !$this->getRequest()->getParam('clear')) { // $params['id'] = $_prevCategoryId; $this->getRequest()->setParam('id',$_prevCategoryId); //$redirect = true; @@ -131,7 +133,6 @@ public function editAction() if (!($category = $this->_initCategory(true))) { return; } - /** * Check if we have data in session (if duering category save was exceprion) */ @@ -166,11 +167,12 @@ public function editAction() ->setLastViewedStore($this->getRequest()->getParam('store')); Mage::getSingleton('admin/session') ->setLastEditedCategory($category->getId()); - $this->_initLayoutMessages('adminhtml/session'); +// $this->_initLayoutMessages('adminhtml/session'); + $this->loadLayout(); $this->getResponse()->setBody( $this->getLayout()->getMessagesBlock()->getGroupedHtml() - . $this->getLayout()->createBlock('adminhtml/catalog_category_edit_form')->toHtml() - . $this->getLayout()->getBlockSingleton('adminhtml/catalog_category_tree') + . $this->getLayout()->getBlock('category.edit')->getFormHtml() + . $this->getLayout()->getBlock('category.tree') ->getBreadcrumbsJavascript($breadcrumbsPath, 'editingCategoryBreadcrumbs') ); return; @@ -184,13 +186,6 @@ public function editAction() $this->_addBreadcrumb(Mage::helper('catalog')->__('Manage Catalog Categories'), Mage::helper('catalog')->__('Manage Categories') ); - - $this->_addLeft( - $this->getLayout()->createBlock('adminhtml/catalog_category_tree', 'category.tree') - ); - $this->_addContent( - $this->getLayout()->createBlock('adminhtml/catalog_category_edit') - ); $this->renderLayout(); } @@ -229,7 +224,6 @@ public function saveAction() $storeId = $this->getRequest()->getParam('store'); if ($data = $this->getRequest()->getPost()) { $category->addData($data['general']); - if (!$category->getId()) { $parentId = $this->getRequest()->getParam('parent'); if (!$parentId) { diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php index 668b39ec90..92d264b331 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php @@ -101,7 +101,7 @@ public function saveAction() } try { - $modelSet->validate($this->getRequest()->getParam('attribute_set_name')); + $modelSet->validate($modelSet->getAttributeSetName()); $modelSet->save(); if( $this->getRequest()->getParam('gotoEdit') == 1 ) { $modelSet->initFromSkeleton($this->getRequest()->getParam('skeleton_set')) diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php index 46562a5f68..9318dfd41c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php @@ -154,11 +154,6 @@ public function indexAction() { $this->loadLayout(); $this->_setActiveMenu('catalog/products'); - - $this->_addContent( - $this->getLayout()->createBlock('adminhtml/catalog_product') - ); - $this->renderLayout(); } @@ -198,7 +193,6 @@ public function newAction() public function editAction() { $product = $this->_initProduct(); - Mage::dispatchEvent('catalog_product_edit_action', array('product' => $product)); $_additionalLayoutPart = ''; @@ -621,10 +615,9 @@ public function deleteAction() { if ($id = $this->getRequest()->getParam('id')) { $product = Mage::getModel('catalog/product') - ->setId($id); - + ->load($id); + $sku = $product->getSku(); try { - Mage::dispatchEvent('catalog_controller_product_delete', array('product'=>$product)); $product->delete(); $this->_getSession()->addSuccess($this->__('Product deleted')); } diff --git a/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php b/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php index 0463e3a619..b208e76c90 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php @@ -153,10 +153,12 @@ public function deleteAction() { // check if we know what should be deleted if ($id = $this->getRequest()->getParam('block_id')) { + $title = ""; try { // init model and delete $model = Mage::getModel('cms/block'); - $model->setId($id); + $model->load($id); + $title = $model->getTitle(); $model->delete(); // display success message Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('cms')->__('Block was successfully deleted')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Cms/PageController.php b/app/code/core/Mage/Adminhtml/controllers/Cms/PageController.php index 7ada91ae66..d09e2730bb 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Cms/PageController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Cms/PageController.php @@ -108,7 +108,6 @@ public function editAction() && Mage::helper('googleoptimizer')->isOptimizerActive()) { $this->_addJs($this->getLayout()->createBlock('googleoptimizer/js')->setTemplate('googleoptimizer/js.phtml')); } - $this->renderLayout(); } @@ -145,7 +144,6 @@ public function saveAction() Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('cms')->__('Page was successfully saved')); // clear previously saved data from session Mage::getSingleton('adminhtml/session')->setFormData(false); - // check if 'Save and Continue' if ($this->getRequest()->getParam('back')) { $this->_redirect('*/*/edit', array('page_id' => $model->getId())); @@ -175,18 +173,22 @@ public function deleteAction() { // check if we know what should be deleted if ($id = $this->getRequest()->getParam('page_id')) { + $title = ""; try { // init model and delete $model = Mage::getModel('cms/page'); - $model->setId($id); + $model->load($id); + $title = $model->getTitle(); $model->delete(); // display success message Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('cms')->__('Page was successfully deleted')); // go to grid + Mage::dispatchEvent('adminhtml_cmspage_on_delete', array('title' => $title, 'status' => 'success')); $this->_redirect('*/*/'); return; } catch (Exception $e) { + Mage::dispatchEvent('adminhtml_cmspage_on_delete', array('title' => $title, 'status' => 'fail')); // display error message Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); // go back to edit form diff --git a/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php b/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php index aea965dcd8..ce37e2ac2d 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php @@ -105,7 +105,6 @@ public function saveAction() $customerGroup->setCode($this->getRequest()->getParam('code')) ->setTaxClassId($taxClass) ->save(); - Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('customer')->__('Customer Group was successfully saved')); $this->getResponse()->setRedirect($this->getUrl('*/customer_group')); return; @@ -131,7 +130,6 @@ public function deleteAction() try { $customerGroup->load($id); $customerGroup->delete(); - Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('customer')->__('Customer Group was successfully deleted')); $this->getResponse()->setRedirect($this->getUrl('*/customer_group')); return; diff --git a/app/code/core/Mage/Adminhtml/controllers/CustomerController.php b/app/code/core/Mage/Adminhtml/controllers/CustomerController.php index d3d95de834..08c5bd104c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/CustomerController.php +++ b/app/code/core/Mage/Adminhtml/controllers/CustomerController.php @@ -1,572 +1,572 @@ - - */ -class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action -{ - - protected function _initCustomer($idFieldName = 'id') - { - $customerId = (int) $this->getRequest()->getParam($idFieldName); - $customer = Mage::getModel('customer/customer'); - - if ($customerId) { - $customer->load($customerId); - } - - Mage::register('current_customer', $customer); - return $this; - } - - /** - * Customers list action - */ - public function indexAction() - { - if ($this->getRequest()->getQuery('ajax')) { - $this->_forward('grid'); - return; - } - $this->loadLayout(); - - /** - * Set active menu item - */ - $this->_setActiveMenu('customer/manage'); - - /** - * Append customers block to content - */ - $this->_addContent( - $this->getLayout()->createBlock('adminhtml/customer', 'customer') - ); - - /** - * Add breadcrumb item - */ - $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Customers'), Mage::helper('adminhtml')->__('Customers')); - $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Manage Customers'), Mage::helper('adminhtml')->__('Manage Customers')); - - $this->renderLayout(); - } - - public function gridAction() - { - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_grid')->toHtml()); - } - - /** - * Customer edit action - */ - public function editAction() - { - $this->_initCustomer(); - $this->loadLayout(); - - $customer = Mage::registry('current_customer'); - - // set entered data if was error when we do save - $data = Mage::getSingleton('adminhtml/session')->getCustomerData(true); - - if (isset($data['account'])) { - $customer->addData($data['account']); - } - if (isset($data['address']) && is_array($data['address'])) { - foreach ($data['address'] as $addressId => $address) { - $addressModel = Mage::getModel('customer/address')->setData($address) - ->setId($addressId); - $customer->addAddress($addressModel); - } - } - - /** - * Set active menu item - */ - $this->_setActiveMenu('customer/new'); - - /** - * Append customer edit block to content - */ - $this->_addContent( - $this->getLayout()->createBlock('adminhtml/customer_edit') - ); - - /** - * Append customer edit tabs to left block - */ - $this->_addLeft($this->getLayout()->createBlock('adminhtml/customer_edit_tabs')); - - $this->renderLayout(); - } - - /** - * Create new customer action - */ - public function newAction() - { - $this->_forward('edit'); - } - - /** - * Delete customer action - */ - public function deleteAction() - { - $this->_initCustomer(); - $customer = Mage::registry('current_customer'); - if ($customer->getId()) { - try { - $customer->delete(); - Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Customer was deleted')); - } - catch (Exception $e){ - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - $this->_redirect('*/customer'); - } - - /** - * Save customer action - */ - public function saveAction() - { - if ($data = $this->getRequest()->getPost()) { - $this->_initCustomer('customer_id'); - $customer = Mage::registry('current_customer'); - - // Prepare customer saving data - if (isset($data['account'])) { - $customer->addData($data['account']); - } - - if (isset($data['address'])) { - // unset template data - if (isset($data['address']['_template_'])) { - unset($data['address']['_template_']); - } - - foreach ($data['address'] as $index => $addressData) { - $address = Mage::getModel('customer/address'); - $address->setData($addressData); - - if ($addressId = (int) $index) { - $address->setId($addressId); - } - /** - * We need set post_index for detect default addresses - */ - $address->setPostIndex($index); - $customer->addAddress($address); - } - } - - if(isset($data['subscription'])) { - $customer->setIsSubscribed(true); - } else { - $customer->setIsSubscribed(false); - } - - $isNewCustomer = !$customer->getId(); - try { - if ($customer->getPassword() == 'auto') { - $customer->setPassword($customer->generatePassword()); - } - - // force new customer active - if ($isNewCustomer) { - $customer->setForceConfirmed(true); - } - - $customer->save(); - - // send welcome email - if ($customer->getWebsiteId() && $customer->hasData('sendemail')) { - if ($isNewCustomer) { - $customer->sendNewAccountEmail(); - } - // confirm not confirmed customer - elseif ((!$customer->getConfirmation())) { - $customer->sendNewAccountEmail('confirmed'); - } - } - - // TODO? Send confirmation link, if deactivating account - - if ($newPassword = $customer->getNewPassword()) { - if ($newPassword == 'auto') { - $newPassword = $customer->generatePassword(); - } - $customer->changePassword($newPassword); - $customer->sendPasswordReminderEmail(); - } - - Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Customer was successfully saved')); - } - catch (Exception $e){ - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - Mage::getSingleton('adminhtml/session')->setCustomerData($data); - $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array('id'=>$customer->getId()))); - return; - } - } - $this->getResponse()->setRedirect($this->getUrl('*/customer')); - } - - /** - * Export customer grid to CSV format - */ - public function exportCsvAction() - { - $fileName = 'customers.csv'; - $content = $this->getLayout()->createBlock('adminhtml/customer_grid') - ->getCsv(); - - $this->_prepareDownloadResponse($fileName, $content); - } - - /** - * Export customer grid to XML format - */ - public function exportXmlAction() - { - $fileName = 'customers.xml'; - $content = $this->getLayout()->createBlock('adminhtml/customer_grid') - ->getXml(); - - $this->_prepareDownloadResponse($fileName, $content); - } - - /** - * Prepare file download response - * - * @todo remove in 1.3 - * @deprecated please use $this->_prepareDownloadResponse() - * @see Mage_Adminhtml_Controller_Action::_prepareDownloadResponse() - * @param string $fileName - * @param string $content - * @param string $contentType - */ - protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream') - { - $this->_prepareDownloadResponse($fileName, $content, $contentType); - } - - /** - * Customer orders grid - * - */ - public function ordersAction() { - $this->_initCustomer(); - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_orders')->toHtml()); - } - - /** - * Customer last orders grid for ajax - * - */ - public function lastOrdersAction() { - $this->_initCustomer(); - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_orders')->toHtml()); - } - - /** - * Customer newsletter grid - * - */ - public function newsletterAction() - { - $this->_initCustomer(); - $subscriber = Mage::getModel('newsletter/subscriber') - ->loadByCustomer(Mage::registry('current_customer')); - - Mage::register('subscriber', $subscriber); - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_newsletter_grid')->toHtml()); - } - - public function wishlistAction() - { - $this->_initCustomer(); - $customer = Mage::registry('current_customer'); - if ($customer->getId()) { - if($itemId = (int) $this->getRequest()->getParam('delete')) { - try { - Mage::getModel('wishlist/item')->load($itemId) - ->delete(); - } - catch (Exception $e) { - // - } - } - } - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_wishlist')->toHtml()); - } - - /** - * Customer last view wishlist for ajax - * - */ - public function viewWishlistAction() - { - $this->_initCustomer(); - $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_wishlist')->toHtml()); - } - - /** - * [Handle and then] get a cart grid contents - * - * @return string - */ - public function cartAction() - { - $this->_initCustomer(); - $websiteId = $this->getRequest()->getParam('website_id'); - - // delete an item from cart - if ($deleteItemId = $this->getRequest()->getPost('delete')) { - $quote = Mage::getModel('sales/quote') - ->setWebsite(Mage::app()->getWebsite($websiteId)) - ->loadByCustomer(Mage::registry('current_customer')); - $item = $quote->getItemById($deleteItemId); - $quote->removeItem($deleteItemId); - $quote->save(); - } - - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/customer_edit_tab_cart', '', array('website_id'=>$websiteId)) - ->toHtml() - ); - } - - /** - * Get shopping cart to view only - * - */ - public function viewCartAction() - { - $this->_initCustomer(); - - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_cart') - ->setWebsiteId($this->getRequest()->getParam('website_id')) - ->toHtml() - ); - } - - /** - * Get shopping carts from all websites for specified client - * - * @return string - */ - public function cartsAction() - { - $this->_initCustomer(); - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/customer_edit_tab_carts')->toHtml() - ); - } - - public function productReviewsAction() - { - $this->_initCustomer(); - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/review_grid', 'admin.customer.reviews') - ->setCustomerId(Mage::registry('current_customer')->getId()) - ->setUseAjax(true) - ->toHtml() - ); - } - - public function productTagsAction() - { - $this->_initCustomer(); - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/customer_edit_tab_tag', 'admin.customer.tags') - ->setCustomerId(Mage::registry('current_customer')->getId()) - ->setUseAjax(true) - ->toHtml() - ); - } - - public function tagGridAction() - { - $this->_initCustomer(); - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/customer_edit_tab_tag', 'admin.customer.tags') - ->setCustomerId(Mage::registry('current_customer')) - ->toHtml() - ); - } - - public function validateAction() - { - $response = new Varien_Object(); - $response->setError(0); - $websiteId = Mage::app()->getStore()->getWebsiteId(); - $accountData = $this->getRequest()->getPost('account'); - - - $customer = Mage::getModel('customer/customer'); - if ($id = $this->getRequest()->getParam('id')) { - $customer->load($id); - $websiteId = $customer->getWebsiteId(); - } - if (isset($accountData['website_id'])) { - $websiteId = $accountData['website_id']; - } - - # Checking if we received email. If not - ERROR - if( !($accountData['email']) ) { - $response->setError(1); - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__("Please fill in 'email' field.")); - $this->_initLayoutMessages('adminhtml/session'); - $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); - } else { - # Trying to load customer with the same email and return error message - # if customer with the same email address exisits - $checkCustomer = Mage::getModel('customer/customer') - ->setWebsiteId($websiteId); - $checkCustomer->loadByEmail($accountData['email']); - if( $checkCustomer->getId() && ($checkCustomer->getId() != $customer->getId()) ) { - $response->setError(1); - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Customer with the same email already exists.')); - $this->_initLayoutMessages('adminhtml/session'); - $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); - } - } - $this->getResponse()->setBody($response->toJson()); - } - - public function massSubscribeAction() - { - $customersIds = $this->getRequest()->getParam('customer'); - if(!is_array($customersIds)) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); - - } else { - try { - foreach ($customersIds as $customerId) { - $customer = Mage::getModel('customer/customer')->load($customerId); - $customer->setIsSubscribed(true); - $customer->save(); - } - Mage::getSingleton('adminhtml/session')->addSuccess( - Mage::helper('adminhtml')->__( - 'Total of %d record(s) were successfully updated', count($customersIds) - ) - ); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - $this->_redirect('*/*/index'); - } - - public function massUnsubscribeAction() - { - $customersIds = $this->getRequest()->getParam('customer'); - if(!is_array($customersIds)) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); - } else { - try { - foreach ($customersIds as $customerId) { - $customer = Mage::getModel('customer/customer')->load($customerId); - $customer->setIsSubscribed(false); - $customer->save(); - } - Mage::getSingleton('adminhtml/session')->addSuccess( - Mage::helper('adminhtml')->__( - 'Total of %d record(s) were successfully updated', count($customersIds) - ) - ); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - - $this->_redirect('*/*/index'); - } - - public function massDeleteAction() - { - $customersIds = $this->getRequest()->getParam('customer'); - if(!is_array($customersIds)) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); - } else { - try { - foreach ($customersIds as $customerId) { - $customer = Mage::getModel('customer/customer')->load($customerId); - $customer->delete(); - } - Mage::getSingleton('adminhtml/session')->addSuccess( - Mage::helper('adminhtml')->__( - 'Total of %d record(s) were successfully deleted', count($customersIds) - ) - ); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - - $this->_redirect('*/*/index'); - } - - public function massAssignGroupAction() - { - $customersIds = $this->getRequest()->getParam('customer'); - if(!is_array($customersIds)) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); - } else { - try { - foreach ($customersIds as $customerId) { - $customer = Mage::getModel('customer/customer')->load($customerId); - $customer->setGroupId($this->getRequest()->getParam('group')); - $customer->save(); - } - Mage::getSingleton('adminhtml/session')->addSuccess( - Mage::helper('adminhtml')->__( - 'Total of %d record(s) were successfully updated', count($customersIds) - ) - ); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - - $this->_redirect('*/*/index'); - } - - protected function _isAllowed() - { - return Mage::getSingleton('admin/session')->isAllowed('customer/manage'); - } -} + + */ +class Mage_Adminhtml_CustomerController extends Mage_Adminhtml_Controller_Action +{ + + protected function _initCustomer($idFieldName = 'id') + { + $customerId = (int) $this->getRequest()->getParam($idFieldName); + $customer = Mage::getModel('customer/customer'); + + if ($customerId) { + $customer->load($customerId); + } + + Mage::register('current_customer', $customer); + return $this; + } + + /** + * Customers list action + */ + public function indexAction() + { + if ($this->getRequest()->getQuery('ajax')) { + $this->_forward('grid'); + return; + } + $this->loadLayout(); + + /** + * Set active menu item + */ + $this->_setActiveMenu('customer/manage'); + + /** + * Append customers block to content + */ + $this->_addContent( + $this->getLayout()->createBlock('adminhtml/customer', 'customer') + ); + + /** + * Add breadcrumb item + */ + $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Customers'), Mage::helper('adminhtml')->__('Customers')); + $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Manage Customers'), Mage::helper('adminhtml')->__('Manage Customers')); + + $this->renderLayout(); + } + + public function gridAction() + { + $this->loadLayout(); + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_grid')->toHtml()); + } + + /** + * Customer edit action + */ + public function editAction() + { + $this->_initCustomer(); + $this->loadLayout(); + + $customer = Mage::registry('current_customer'); + + // set entered data if was error when we do save + $data = Mage::getSingleton('adminhtml/session')->getCustomerData(true); + + if (isset($data['account'])) { + $customer->addData($data['account']); + } + if (isset($data['address']) && is_array($data['address'])) { + foreach ($data['address'] as $addressId => $address) { + $addressModel = Mage::getModel('customer/address')->setData($address) + ->setId($addressId); + $customer->addAddress($addressModel); + } + } + + /** + * Set active menu item + */ + $this->_setActiveMenu('customer/new'); + + $this->renderLayout(); + } + + /** + * Create new customer action + */ + public function newAction() + { + $this->_forward('edit'); + } + + /** + * Delete customer action + */ + public function deleteAction() + { + $this->_initCustomer(); + $customer = Mage::registry('current_customer'); + if ($customer->getId()) { + try { + $customer->load($customer->getId()); + $customer->delete(); + Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Customer was deleted')); + } + catch (Exception $e){ + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + $this->_redirect('*/customer'); + } + + /** + * Save customer action + */ + public function saveAction() + { + if ($data = $this->getRequest()->getPost()) { + $redirectBack = $this->getRequest()->getParam('back', false); + $this->_initCustomer('customer_id'); + $customer = Mage::registry('current_customer'); + + // Prepare customer saving data + if (isset($data['account'])) { + $customer->addData($data['account']); + } + + if (isset($data['address'])) { + // unset template data + if (isset($data['address']['_template_'])) { + unset($data['address']['_template_']); + } + + foreach ($data['address'] as $index => $addressData) { + $address = Mage::getModel('customer/address'); + $address->setData($addressData); + + if ($addressId = (int) $index) { + $address->setId($addressId); + } + /** + * We need set post_index for detect default addresses + */ + $address->setPostIndex($index); + $customer->addAddress($address); + } + } + + if(isset($data['subscription'])) { + $customer->setIsSubscribed(true); + } else { + $customer->setIsSubscribed(false); + } + + $isNewCustomer = !$customer->getId(); + try { + if ($customer->getPassword() == 'auto') { + $customer->setPassword($customer->generatePassword()); + } + + // force new customer active + if ($isNewCustomer) { + $customer->setForceConfirmed(true); + } + + $customer->save(); + + // send welcome email + if ($customer->getWebsiteId() && $customer->hasData('sendemail')) { + if ($isNewCustomer) { + $customer->sendNewAccountEmail(); + } + // confirm not confirmed customer + elseif ((!$customer->getConfirmation())) { + $customer->sendNewAccountEmail('confirmed'); + } + } + + // TODO? Send confirmation link, if deactivating account + + if ($newPassword = $customer->getNewPassword()) { + if ($newPassword == 'auto') { + $newPassword = $customer->generatePassword(); + } + $customer->changePassword($newPassword); + $customer->sendPasswordReminderEmail(); + } + + Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Customer was successfully saved')); + Mage::dispatchEvent('adminhtml_customer_save_after', array('customer' => $customer)); + + if ($redirectBack) { + $this->_redirect('*/*/edit', array( + 'id' => $customer->getId(), + '_current'=>true + )); + return; + } + } + catch (Exception $e){ + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + Mage::getSingleton('adminhtml/session')->setCustomerData($data); + $this->getResponse()->setRedirect($this->getUrl('*/customer/edit', array('id'=>$customer->getId()))); + return; + } + } + $this->getResponse()->setRedirect($this->getUrl('*/customer')); + } + + /** + * Export customer grid to CSV format + */ + public function exportCsvAction() + { + $fileName = 'customers.csv'; + $content = $this->getLayout()->createBlock('adminhtml/customer_grid') + ->getCsv(); + + $this->_prepareDownloadResponse($fileName, $content); + } + + /** + * Export customer grid to XML format + */ + public function exportXmlAction() + { + $fileName = 'customers.xml'; + $content = $this->getLayout()->createBlock('adminhtml/customer_grid') + ->getXml(); + + $this->_prepareDownloadResponse($fileName, $content); + } + + /** + * Prepare file download response + * + * @todo remove in 1.3 + * @deprecated please use $this->_prepareDownloadResponse() + * @see Mage_Adminhtml_Controller_Action::_prepareDownloadResponse() + * @param string $fileName + * @param string $content + * @param string $contentType + */ + protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream') + { + $this->_prepareDownloadResponse($fileName, $content, $contentType); + } + + /** + * Customer orders grid + * + */ + public function ordersAction() { + $this->_initCustomer(); + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_orders')->toHtml()); + } + + /** + * Customer last orders grid for ajax + * + */ + public function lastOrdersAction() { + $this->_initCustomer(); + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_orders')->toHtml()); + } + + /** + * Customer newsletter grid + * + */ + public function newsletterAction() + { + $this->_initCustomer(); + $subscriber = Mage::getModel('newsletter/subscriber') + ->loadByCustomer(Mage::registry('current_customer')); + + Mage::register('subscriber', $subscriber); + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_newsletter_grid')->toHtml()); + } + + public function wishlistAction() + { + $this->_initCustomer(); + $customer = Mage::registry('current_customer'); + if ($customer->getId()) { + if($itemId = (int) $this->getRequest()->getParam('delete')) { + try { + Mage::getModel('wishlist/item')->load($itemId) + ->delete(); + } + catch (Exception $e) { + // + } + } + } + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_wishlist')->toHtml()); + } + + /** + * Customer last view wishlist for ajax + * + */ + public function viewWishlistAction() + { + $this->_initCustomer(); + $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_wishlist')->toHtml()); + } + + /** + * [Handle and then] get a cart grid contents + * + * @return string + */ + public function cartAction() + { + $this->_initCustomer(); + $websiteId = $this->getRequest()->getParam('website_id'); + + // delete an item from cart + if ($deleteItemId = $this->getRequest()->getPost('delete')) { + $quote = Mage::getModel('sales/quote') + ->setWebsite(Mage::app()->getWebsite($websiteId)) + ->loadByCustomer(Mage::registry('current_customer')); + $item = $quote->getItemById($deleteItemId); + $quote->removeItem($deleteItemId); + $quote->save(); + } + + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/customer_edit_tab_cart', '', array('website_id'=>$websiteId)) + ->toHtml() + ); + } + + /** + * Get shopping cart to view only + * + */ + public function viewCartAction() + { + $this->_initCustomer(); + + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/customer_edit_tab_view_cart') + ->setWebsiteId($this->getRequest()->getParam('website_id')) + ->toHtml() + ); + } + + /** + * Get shopping carts from all websites for specified client + * + * @return string + */ + public function cartsAction() + { + $this->_initCustomer(); + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/customer_edit_tab_carts')->toHtml() + ); + } + + public function productReviewsAction() + { + $this->_initCustomer(); + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/review_grid', 'admin.customer.reviews') + ->setCustomerId(Mage::registry('current_customer')->getId()) + ->setUseAjax(true) + ->toHtml() + ); + } + + public function productTagsAction() + { + $this->_initCustomer(); + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/customer_edit_tab_tag', 'admin.customer.tags') + ->setCustomerId(Mage::registry('current_customer')->getId()) + ->setUseAjax(true) + ->toHtml() + ); + } + + public function tagGridAction() + { + $this->_initCustomer(); + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/customer_edit_tab_tag', 'admin.customer.tags') + ->setCustomerId(Mage::registry('current_customer')) + ->toHtml() + ); + } + + public function validateAction() + { + $response = new Varien_Object(); + $response->setError(0); + $websiteId = Mage::app()->getStore()->getWebsiteId(); + $accountData = $this->getRequest()->getPost('account'); + + + $customer = Mage::getModel('customer/customer'); + if ($id = $this->getRequest()->getParam('id')) { + $customer->load($id); + $websiteId = $customer->getWebsiteId(); + } + if (isset($accountData['website_id'])) { + $websiteId = $accountData['website_id']; + } + + # Checking if we received email. If not - ERROR + if( !($accountData['email']) ) { + $response->setError(1); + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__("Please fill in 'email' field.")); + $this->_initLayoutMessages('adminhtml/session'); + $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); + } else { + # Trying to load customer with the same email and return error message + # if customer with the same email address exisits + $checkCustomer = Mage::getModel('customer/customer') + ->setWebsiteId($websiteId); + $checkCustomer->loadByEmail($accountData['email']); + if( $checkCustomer->getId() && ($checkCustomer->getId() != $customer->getId()) ) { + $response->setError(1); + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Customer with the same email already exists.')); + $this->_initLayoutMessages('adminhtml/session'); + $response->setMessage($this->getLayout()->getMessagesBlock()->getGroupedHtml()); + } + } + $this->getResponse()->setBody($response->toJson()); + } + + public function massSubscribeAction() + { + $customersIds = $this->getRequest()->getParam('customer'); + if(!is_array($customersIds)) { + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); + + } else { + try { + foreach ($customersIds as $customerId) { + $customer = Mage::getModel('customer/customer')->load($customerId); + $customer->setIsSubscribed(true); + $customer->save(); + } + Mage::getSingleton('adminhtml/session')->addSuccess( + Mage::helper('adminhtml')->__( + 'Total of %d record(s) were successfully updated', count($customersIds) + ) + ); + } catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + $this->_redirect('*/*/index'); + } + + public function massUnsubscribeAction() + { + $customersIds = $this->getRequest()->getParam('customer'); + if(!is_array($customersIds)) { + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); + } else { + try { + foreach ($customersIds as $customerId) { + $customer = Mage::getModel('customer/customer')->load($customerId); + $customer->setIsSubscribed(false); + $customer->save(); + } + Mage::getSingleton('adminhtml/session')->addSuccess( + Mage::helper('adminhtml')->__( + 'Total of %d record(s) were successfully updated', count($customersIds) + ) + ); + } catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + + $this->_redirect('*/*/index'); + } + + public function massDeleteAction() + { + $customersIds = $this->getRequest()->getParam('customer'); + if(!is_array($customersIds)) { + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); + } else { + try { + foreach ($customersIds as $customerId) { + $customer = Mage::getModel('customer/customer')->load($customerId); + $customer->delete(); + } + Mage::getSingleton('adminhtml/session')->addSuccess( + Mage::helper('adminhtml')->__( + 'Total of %d record(s) were successfully deleted', count($customersIds) + ) + ); + } catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + + $this->_redirect('*/*/index'); + } + + public function massAssignGroupAction() + { + $customersIds = $this->getRequest()->getParam('customer'); + if(!is_array($customersIds)) { + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select customer(s)')); + } else { + try { + foreach ($customersIds as $customerId) { + $customer = Mage::getModel('customer/customer')->load($customerId); + $customer->setGroupId($this->getRequest()->getParam('group')); + $customer->save(); + } + Mage::getSingleton('adminhtml/session')->addSuccess( + Mage::helper('adminhtml')->__( + 'Total of %d record(s) were successfully updated', count($customersIds) + ) + ); + } catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + + $this->_redirect('*/*/index'); + } + + protected function _isAllowed() + { + return Mage::getSingleton('admin/session')->isAllowed('customer/manage'); + } +} diff --git a/app/code/core/Mage/Adminhtml/controllers/DashboardController.php b/app/code/core/Mage/Adminhtml/controllers/DashboardController.php index 9d3b5e9fd4..d69a610ef3 100644 --- a/app/code/core/Mage/Adminhtml/controllers/DashboardController.php +++ b/app/code/core/Mage/Adminhtml/controllers/DashboardController.php @@ -38,7 +38,6 @@ public function indexAction() $this->loadLayout(); $this->_setActiveMenu('dashboard'); $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Dashboard'), Mage::helper('adminhtml')->__('Dashboard')); - $this->_addContent($this->getLayout()->createBlock('adminhtml/dashboard', 'dashboard')); $this->renderLayout(); } diff --git a/app/code/core/Mage/Adminhtml/controllers/IndexController.php b/app/code/core/Mage/Adminhtml/controllers/IndexController.php index a95c29ca2b..eb33ff2faf 100644 --- a/app/code/core/Mage/Adminhtml/controllers/IndexController.php +++ b/app/code/core/Mage/Adminhtml/controllers/IndexController.php @@ -154,6 +154,16 @@ protected function _getDeniedJson() ); } + public function deniedIframeAction() + { + $this->getResponse()->setBody($this->_getDeniedIframe()); + } + + protected function _getDeniedIframe() + { + return ''; + } + public function forgotpasswordAction () { $email = $this->getRequest()->getParam('email'); @@ -189,7 +199,6 @@ public function forgotpasswordAction () $data = array( 'email' => $email ); - $this->_outTemplate('forgotpassword', $data); } diff --git a/app/code/core/Mage/Adminhtml/controllers/Newsletter/SubscriberController.php b/app/code/core/Mage/Adminhtml/controllers/Newsletter/SubscriberController.php index 7a9ef2e831..f92b55bca0 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Newsletter/SubscriberController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Newsletter/SubscriberController.php @@ -1,134 +1,134 @@ - - */ -class Mage_Adminhtml_Newsletter_SubscriberController extends Mage_Adminhtml_Controller_Action -{ - - public function indexAction() - { - if ($this->getRequest()->getParam('ajax')) { - $this->_forward('grid'); - return; - } - - $this->loadLayout(); - - $this->_setActiveMenu('newsletter/subscriber'); - - $this->_addBreadcrumb(Mage::helper('newsletter')->__('Newsletter'), Mage::helper('newsletter')->__('Newsletter')); - $this->_addBreadcrumb(Mage::helper('newsletter')->__('Subscribers'), Mage::helper('newsletter')->__('Subscribers')); - - $this->_addContent( - $this->getLayout()->createBlock('adminhtml/newsletter_subscriber','subscriber') - ); - - $this->renderLayout(); - } - - public function gridAction() - { - $this->getResponse()->setBody( - $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid')->toHtml() - ); - } - - /** - * Export subscribers grid to CSV format - */ - public function exportCsvAction() - { - $fileName = 'subscribers.csv'; - $content = $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid') - ->getCsv(); - - $this->_prepareDownloadResponse($fileName, $content); - } - - /** - * Export subscribers grid to XML format - */ - public function exportXmlAction() - { - $fileName = 'subscribers.xml'; - $content = $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid') - ->getXml(); - - $this->_prepareDownloadResponse($fileName, $content); - } - - /** - * Prepare file download response - * - * @todo remove in 1.3 - * @deprecated please use $this->_prepareDownloadResponse() - * @see Mage_Adminhtml_Controller_Action::_prepareDownloadResponse() - * @param string $fileName - * @param string $content - * @param string $contentType - */ - protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream') - { - $this->_prepareDownloadResponse($fileName, $content, $contentType); - } - - public function massUnsubscribeAction() - { - $subscribersIds = $this->getRequest()->getParam('subscriber'); - if (!is_array($subscribersIds)) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('newsletter')->__('Please select subscriber(s)')); - } - else { - try { - foreach ($subscribersIds as $subscriberId) { - $subscriber = Mage::getModel('newsletter/subscriber')->load($subscriberId); - $subscriber->unsubscribe(); - } - Mage::getSingleton('adminhtml/session')->addSuccess( - Mage::helper('adminhtml')->__( - 'Total of %d record(s) were successfully updated', count($subscribersIds) - ) - ); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); - } - } - - $this->_redirect('*/*/index'); - } - - protected function _isAllowed() - { - return Mage::getSingleton('admin/session')->isAllowed('newsletter/subscriber'); - } - -} + + */ +class Mage_Adminhtml_Newsletter_SubscriberController extends Mage_Adminhtml_Controller_Action +{ + + public function indexAction() + { + if ($this->getRequest()->getParam('ajax')) { + $this->_forward('grid'); + return; + } + + $this->loadLayout(); + + $this->_setActiveMenu('newsletter/subscriber'); + + $this->_addBreadcrumb(Mage::helper('newsletter')->__('Newsletter'), Mage::helper('newsletter')->__('Newsletter')); + $this->_addBreadcrumb(Mage::helper('newsletter')->__('Subscribers'), Mage::helper('newsletter')->__('Subscribers')); + + $this->_addContent( + $this->getLayout()->createBlock('adminhtml/newsletter_subscriber','subscriber') + ); + + $this->renderLayout(); + } + + public function gridAction() + { + $this->loadLayout(); + $this->getResponse()->setBody( + $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid')->toHtml() + ); + } + + /** + * Export subscribers grid to CSV format + */ + public function exportCsvAction() + { + $fileName = 'subscribers.csv'; + $content = $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid') + ->getCsv(); + + $this->_prepareDownloadResponse($fileName, $content); + } + + /** + * Export subscribers grid to XML format + */ + public function exportXmlAction() + { + $fileName = 'subscribers.xml'; + $content = $this->getLayout()->createBlock('adminhtml/newsletter_subscriber_grid') + ->getXml(); + + $this->_prepareDownloadResponse($fileName, $content); + } + + /** + * Prepare file download response + * + * @todo remove in 1.3 + * @deprecated please use $this->_prepareDownloadResponse() + * @see Mage_Adminhtml_Controller_Action::_prepareDownloadResponse() + * @param string $fileName + * @param string $content + * @param string $contentType + */ + protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream') + { + $this->_prepareDownloadResponse($fileName, $content, $contentType); + } + + public function massUnsubscribeAction() + { + $subscribersIds = $this->getRequest()->getParam('subscriber'); + if (!is_array($subscribersIds)) { + Mage::getSingleton('adminhtml/session')->addError(Mage::helper('newsletter')->__('Please select subscriber(s)')); + } + else { + try { + foreach ($subscribersIds as $subscriberId) { + $subscriber = Mage::getModel('newsletter/subscriber')->load($subscriberId); + $subscriber->unsubscribe(); + } + Mage::getSingleton('adminhtml/session')->addSuccess( + Mage::helper('adminhtml')->__( + 'Total of %d record(s) were successfully updated', count($subscribersIds) + ) + ); + } catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); + } + } + + $this->_redirect('*/*/index'); + } + + protected function _isAllowed() + { + return Mage::getSingleton('admin/session')->isAllowed('newsletter/subscriber'); + } +} diff --git a/app/code/core/Mage/Adminhtml/controllers/NotificationController.php b/app/code/core/Mage/Adminhtml/controllers/NotificationController.php index da6e641b24..6c4cf8cb71 100644 --- a/app/code/core/Mage/Adminhtml/controllers/NotificationController.php +++ b/app/code/core/Mage/Adminhtml/controllers/NotificationController.php @@ -95,7 +95,7 @@ public function massMarkAsReadAction() $session->addException($e, Mage::helper('adminnotification')->__('Error while marking as read. Please try again later.')); } } - $this->_redirectReferer(); + $this->_redirect('*/*/'); } public function removeAction() diff --git a/app/code/core/Mage/Adminhtml/controllers/Permissions/RoleController.php b/app/code/core/Mage/Adminhtml/controllers/Permissions/RoleController.php index 38b1f51040..98f1b00318 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Permissions/RoleController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Permissions/RoleController.php @@ -48,18 +48,13 @@ public function indexAction() { $this->_initAction(); - $this->_addContent($this->getLayout()->createBlock('adminhtml/permissions_roles')); - $this->renderLayout(); } public function roleGridAction() { - $this->getResponse() - ->setBody($this->getLayout() - ->createBlock('adminhtml/permissions_grid_role') - ->toHtml() - ); + $this->loadLayout(); + $this->getResponse()->setBody($this->getLayout()->getBlock('adminhtml.permission.role.grid')->toHtml()); } public function editRoleAction() @@ -78,10 +73,6 @@ public function editRoleAction() $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); - $this->_addLeft( - $this->getLayout()->createBlock('adminhtml/permissions_editroles') - ); - $this->_addContent( $this->getLayout()->createBlock('adminhtml/permissions_buttons') ->setRoleId($roleId) @@ -129,8 +120,9 @@ public function saveRoleAction() ->setId($rid) ->setName($this->getRequest()->getParam('rolename', false)) ->setPid($this->getRequest()->getParam('parent_id', false)) - ->setRoleType('G') - ->save(); + ->setRoleType('G'); + Mage::dispatchEvent('admin_permissions_role_prepare_save', array('object' => $role, 'request' => $this->getRequest())); + $role->save(); Mage::getModel("admin/rules") ->setRoleId($role->getId()) diff --git a/app/code/core/Mage/Adminhtml/controllers/Promo/CatalogController.php b/app/code/core/Mage/Adminhtml/controllers/Promo/CatalogController.php index a563b07b52..2e405e46fe 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Promo/CatalogController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Promo/CatalogController.php @@ -121,6 +121,7 @@ public function saveAction() Mage::getSingleton('adminhtml/session')->setPageData($model->getData()); try { $model->save(); + Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('catalogrule')->__('Rule was successfully saved')); Mage::getSingleton('adminhtml/session')->setPageData(false); if ($autoApply) { @@ -145,7 +146,7 @@ public function deleteAction() if ($id = $this->getRequest()->getParam('id')) { try { $model = Mage::getModel('catalogrule/rule'); - $model->setId($id); + $model->load($id); $model->delete(); Mage::app()->saveCache(1, 'catalog_rules_dirty'); Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('catalogrule')->__('Rule was successfully deleted')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Promo/QuoteController.php b/app/code/core/Mage/Adminhtml/controllers/Promo/QuoteController.php index dc18c73733..073e736090 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Promo/QuoteController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Promo/QuoteController.php @@ -77,6 +77,7 @@ public function editAction() if (!empty($data)) { $model->addData($data); } + $model->getConditions()->setJsFormObject('rule_conditions_fieldset'); $model->getActions()->setJsFormObject('rule_actions_fieldset'); @@ -86,7 +87,6 @@ public function editAction() ->setData('action', $this->getUrl('*/*/save')); $this->_initAction(); - $this->getLayout()->getBlock('head') ->setCanLoadExtJs(true) ->setCanLoadRulesJs(true); @@ -148,7 +148,7 @@ public function deleteAction() if ($id = $this->getRequest()->getParam('id')) { try { $model = Mage::getModel('salesrule/rule'); - $model->setId($id); + $model->load($id); $model->delete(); Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('salesrule')->__('Rule was successfully deleted')); $this->_redirect('*/*/'); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/CustomerController.php b/app/code/core/Mage/Adminhtml/controllers/Report/CustomerController.php index 460b80a0a4..87bc1d693b 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/CustomerController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/CustomerController.php @@ -36,6 +36,10 @@ class Mage_Adminhtml_Report_CustomerController extends Mage_Adminhtml_Controller { public function _initAction() { + $act = $this->getRequest()->getActionName(); + if(!$act) + $act = 'default'; + $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Customers'), Mage::helper('reports')->__('Customers')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php b/app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php index 3a7a145500..5ca3a5dd29 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/ProductController.php @@ -40,6 +40,9 @@ class Mage_Adminhtml_Report_ProductController extends Mage_Adminhtml_Controller_ */ public function _initAction() { + $act = $this->getRequest()->getActionName(); + if(!$act) + $act = 'default'; $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Products'), Mage::helper('reports')->__('Products')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/ReviewController.php b/app/code/core/Mage/Adminhtml/controllers/Report/ReviewController.php index 44cafaf259..1c3c807e7a 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/ReviewController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/ReviewController.php @@ -35,6 +35,10 @@ class Mage_Adminhtml_Report_ReviewController extends Mage_Adminhtml_Controller_A { public function _initAction() { + $act = $this->getRequest()->getActionName(); + if(!$act) + $act = 'default'; + $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Review'), Mage::helper('reports')->__('Reviews')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php b/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php index 6c5494bb95..7f9a49863c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php @@ -35,6 +35,9 @@ class Mage_Adminhtml_Report_SalesController extends Mage_Adminhtml_Controller_Ac { public function _initAction() { + $act = $this->getRequest()->getActionName(); + if(!$act) + $act = 'default'; $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Sales'), Mage::helper('reports')->__('Sales')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/ShopcartController.php b/app/code/core/Mage/Adminhtml/controllers/Report/ShopcartController.php index 72b8ad8ec4..d8757cc610 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/ShopcartController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/ShopcartController.php @@ -35,6 +35,7 @@ class Mage_Adminhtml_Report_ShopcartController extends Mage_Adminhtml_Controller { public function _initAction() { + $act = $this->getRequest()->getActionName(); $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Shopping Cart'), Mage::helper('reports')->__('Shopping Cart')); diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/TagController.php b/app/code/core/Mage/Adminhtml/controllers/Report/TagController.php index 8aae85276c..bbbf1036ab 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Report/TagController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Report/TagController.php @@ -35,6 +35,10 @@ class Mage_Adminhtml_Report_TagController extends Mage_Adminhtml_Controller_Acti { public function _initAction() { + $act = $this->getRequest()->getActionName(); + if(!$act) + $act = 'default'; + $this->loadLayout() ->_addBreadcrumb(Mage::helper('reports')->__('Reports'), Mage::helper('reports')->__('Reports')) ->_addBreadcrumb(Mage::helper('reports')->__('Tag'), Mage::helper('reports')->__('Tag')); diff --git a/app/code/core/Mage/Adminhtml/controllers/ReportController.php b/app/code/core/Mage/Adminhtml/controllers/ReportController.php index 6eedcafe31..3a2264f545 100644 --- a/app/code/core/Mage/Adminhtml/controllers/ReportController.php +++ b/app/code/core/Mage/Adminhtml/controllers/ReportController.php @@ -77,6 +77,8 @@ public function exportWishlistExcelAction() */ public function searchAction() { + Mage::dispatchEvent('on_view_report', array('report' => 'search')); + $this->_initAction() ->_setActiveMenu('report/search') ->_addBreadcrumb(Mage::helper('adminhtml')->__('Search Terms'), Mage::helper('adminhtml')->__('Search Terms')) diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php index c10f5886c6..5b24fc919c 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php @@ -92,6 +92,7 @@ public function indexAction() */ public function gridAction() { + $this->loadLayout(); $this->getResponse()->setBody( $this->getLayout()->createBlock('adminhtml/sales_order_grid')->toHtml() ); diff --git a/app/code/core/Mage/Adminhtml/controllers/System/AccountController.php b/app/code/core/Mage/Adminhtml/controllers/System/AccountController.php index 13f5854bf3..17be1df430 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/AccountController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/AccountController.php @@ -38,7 +38,6 @@ public function indexAction() { $this->loadLayout(); $this->_setActiveMenu('system/account'); - $this->_addContent($this->getLayout()->createBlock('adminhtml/system_account_edit')); $this->renderLayout(); } @@ -58,19 +57,25 @@ public function saveAction() $user->setPassword($this->getRequest()->getParam('password', false)); } - if( !$user->userExists() ) { + try { try { + if ($user->userExists()) { + Mage::throwException(Mage::helper('adminhtml')->__('User with the same User Name or Email aleady exists')); + } $user->save(); Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Account successfully saved')); - $this->getResponse()->setRedirect($this->getUrl("*/*/")); - } catch (Exception $e) { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Error while saving account. Please try again later')); - $this->getResponse()->setRedirect($this->getUrl("*/*/")); } - } else { - Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('User with the same User Name or Email aleady exists')); - $this->getResponse()->setRedirect($this->getUrl("*/*/")); + catch (Mage_Core_Exception $e) { + throw $e; + } + catch (Exception $e) { + throw new Exception(Mage::helper('adminhtml')->__('Error while saving account. Please try again later')); + } + } + catch (Exception $e) { + Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); } + $this->getResponse()->setRedirect($this->getUrl("*/*/")); } protected function _isAllowed() diff --git a/app/code/core/Mage/Adminhtml/controllers/System/CacheController.php b/app/code/core/Mage/Adminhtml/controllers/System/CacheController.php index 1d96051263..da4a917304 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/CacheController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/CacheController.php @@ -158,7 +158,6 @@ public function saveAction() } break; - case 'refresh_layered_navigation': try { $flag = Mage::getModel('catalogindex/catalog_index_flag')->loadSelf(); @@ -195,26 +194,54 @@ public function saveAction() case 'rebuild_search_index': try { Mage::getSingleton('catalogsearch/fulltext')->rebuildIndex(); - $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('Search Index was rebuilded successfully')); + $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('Search Index was rebuilt successfully')); } catch (Mage_Core_Exception $e) { $this->_getSession()->addError($e->getMessage()); } catch (Exception $e) { - $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('Error while rebuilded Search Index. Please try again later')); + $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('Search Index rebuild error. Please try again later')); } break; case 'rebuild_inventory_stock_status': try { Mage::getSingleton('cataloginventory/stock_status')->rebuild(); - $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('CatalogInventory Stock Status was rebuilded successfully')); + $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('CatalogInventory Stock Status was rebuilt successfully')); + } + catch (Mage_Core_Exception $e) { + $this->_getSession()->addError($e->getMessage()); + } + catch (Exception $e) { + $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('CatalogInventory Stock Status rebuild error. Please try again later')); + } + break; + + case 'rebuild_flat_catalog_category': + try { + Mage::getResourceModel('catalog/category_flat')->rebuild(); + $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('Flat Catalog Category was rebuilt successfully')); + } + catch (Mage_Core_Exception $e) { + $this->_getSession()->addError($e->getMessage()); + } + catch (Exception $e) { + $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('Flat Catalog Category rebuild error')); + } + break; + + case 'rebuild_flat_catalog_product': + try { + Mage::getResourceModel('catalog/product_flat_indexer')->rebuild(); + $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('Flat Catalog Product was rebuilt successfully')); } catch (Mage_Core_Exception $e) { $this->_getSession()->addError($e->getMessage()); } catch (Exception $e) { - $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('Error while rebuilded CatalogInventory Stock Status. Please try again later')); + echo $e; + die(); + $this->_getSession()->addException($e, Mage::helper('adminhtml')->__('Flat Catalog Product rebuild error. Please try again later')); } break; diff --git a/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php b/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php index c30cf1fd75..8e3b280bcf 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php @@ -70,7 +70,6 @@ public function editAction() $sections = $configFields->getSections($current); $section = $sections->$current; $hasChildren = $configFields->hasChildren($section, $website, $store); - if (!$hasChildren && $current) { $this->_redirect('*/*/', array('website'=>$website, 'store'=>$store)); } @@ -124,7 +123,7 @@ public function saveAction() } try { - Mage::app()->cleanCache(array('config')); + Mage::app()->cleanCache(array(Mage_Core_Model_Config::CACHE_TAG)); if (!$this->_isSectionAllowed($this->getRequest()->getParam('section'))) { throw new Exception(Mage::helper('adminhtml')->__('This section is not allowed.')); } @@ -145,11 +144,11 @@ public function saveAction() Mage::getConfig()->reinit(); Mage::app()->reinitStores(); + // website and store codes can be used in event implementation, so set them as well Mage::dispatchEvent("admin_system_config_changed_section_{$section}", array('website' => $website, 'store' => $store) ); - $session->addSuccess(Mage::helper('adminhtml')->__('Configuration successfully saved')); } catch (Mage_Core_Exception $e) { @@ -168,9 +167,6 @@ public function saveAction() /** * Custom save logic for section - * - * @param none - * @return void */ protected function _saveSection () { @@ -182,9 +178,6 @@ protected function _saveSection () /** * Description goes here... - * - * @param none - * @return void */ protected function _saveAdvanced () { diff --git a/app/code/core/Mage/Adminhtml/controllers/System/Convert/ProfileController.php b/app/code/core/Mage/Adminhtml/controllers/System/Convert/ProfileController.php index 63461eb736..dc01be85f5 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/Convert/ProfileController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/Convert/ProfileController.php @@ -267,6 +267,7 @@ public function batchFinishAction() /* @var $batchModel Mage_Dataflow_Model_Batch */ if ($batchModel->getId()) { + $result = array(); try { $batchModel->beforeFinish(); } diff --git a/app/code/core/Mage/Adminhtml/etc/config.xml b/app/code/core/Mage/Adminhtml/etc/config.xml index 55a04262a5..61fd628f23 100644 --- a/app/code/core/Mage/Adminhtml/etc/config.xml +++ b/app/code/core/Mage/Adminhtml/etc/config.xml @@ -383,6 +383,9 @@ catalog.xml + + customer.xml + diff --git a/app/code/core/Mage/Api/Controller/Action.php b/app/code/core/Mage/Api/Controller/Action.php index 8720b5694a..49e4765858 100644 --- a/app/code/core/Mage/Api/Controller/Action.php +++ b/app/code/core/Mage/Api/Controller/Action.php @@ -34,6 +34,8 @@ class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action { public function preDispatch() { + $this->getLayout()->setArea('adminhtml'); + Mage::app()->setCurrentStore('admin'); $this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standart session parent::preDispatch(); return $this; diff --git a/app/code/core/Mage/Api/Model/Config.php b/app/code/core/Mage/Api/Model/Config.php index aa257c439c..f0125a6f3d 100644 --- a/app/code/core/Mage/Api/Model/Config.php +++ b/app/code/core/Mage/Api/Model/Config.php @@ -186,6 +186,7 @@ public function getResourcesAlias() */ public function loadAclResources(Mage_Api_Model_Acl $acl, $resource=null, $parentName=null) { + $resourceName = null; if (is_null($resource)) { $resource = $this->getNode('acl/resources'); } else { diff --git a/app/code/core/Mage/Api/Model/Mysql4/Permissions/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/Permissions/Collection.php index cb806956bd..81efb60705 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Permissions/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Permissions/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Role.php b/app/code/core/Mage/Api/Model/Mysql4/Role.php index bf9a62c1b1..1085f328a0 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Role.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Role.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Role/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/Role/Collection.php index 04000e1f76..d76d585ed1 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Role/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Role/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Roles.php b/app/code/core/Mage/Api/Model/Mysql4/Roles.php index 5e85f6d78d..bf9ebcf79e 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Roles.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Roles.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Roles/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/Roles/Collection.php index 7461e5c182..43567f52c6 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Roles/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Roles/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Roles/User/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/Roles/User/Collection.php index e9fb3af5d0..61a30281cf 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Roles/User/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Roles/User/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Rules.php b/app/code/core/Mage/Api/Model/Mysql4/Rules.php index f10719fc6b..709989588e 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Rules.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Rules.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/Rules/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/Rules/Collection.php index 9f372b4cce..1dffb7adee 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/Rules/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/Rules/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Mysql4/User/Collection.php b/app/code/core/Mage/Api/Model/Mysql4/User/Collection.php index 428bce70b5..c580f55a96 100644 --- a/app/code/core/Mage/Api/Model/Mysql4/User/Collection.php +++ b/app/code/core/Mage/Api/Model/Mysql4/User/Collection.php @@ -19,7 +19,7 @@ * needs please refer to http://www.magentocommerce.com for more information. * * @category Mage - * @package Mage_Permissions + * @package Mage_Api * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ diff --git a/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php b/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php index 4e1862aadb..17b1a517f7 100644 --- a/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php +++ b/app/code/core/Mage/Api/Model/Server/Adapter/Soap.php @@ -94,6 +94,8 @@ public function getController() */ public function run() { + $urlModel = Mage::getModel('core/url') + ->setUseSession(false); if ($this->getController()->getRequest()->getParam('wsdl')) { // Generating wsdl content from template $io = new Varien_Io_File(); @@ -103,7 +105,14 @@ public function run() $template = Mage::getModel('core/email_template_filter'); $wsdlConfig = new Varien_Object(); - $wsdlConfig->setUrl(Mage::getUrl('*/*/*')); + $queryParams = $this->getController()->getRequest()->getQuery(); + if (isset($queryParams['wsdl'])) { + unset($queryParams['wsdl']); + } + + $wsdlConfig->setUrl( + htmlspecialchars($urlModel->getUrl('*/*/*', array('_query'=>$queryParams))) + ); $wsdlConfig->setName('Magento'); $wsdlConfig->setHandler($this->getHandler()); @@ -112,9 +121,8 @@ public function run() $this->getController()->getResponse() ->setHeader('Content-Type','text/xml') ->setBody($template->filter($wsdlContent)); - } elseif ($this->_extensionLoaded()) { - $this->_soap = new SoapServer(Mage::getUrl('*/*/*', array('wsdl'=>1))); + $this->_soap = new SoapServer($urlModel->getUrl('*/*/*', array('wsdl'=>1))); use_soap_error_handler(false); $this->_soap->setClass($this->getHandler()); $this->getController()->getResponse() @@ -153,7 +161,6 @@ public function fault($code, $message) /** * Check whether Soap extension is loaded * - * @param none * @return boolean */ protected function _extensionLoaded() @@ -161,4 +168,4 @@ protected function _extensionLoaded() return class_exists('SoapServer', false); } -} // Class Mage_Api_Model_Server_Adapter_Soap End \ No newline at end of file +} // Class Mage_Api_Model_Server_Adapter_Soap End diff --git a/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php b/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php index 26140a056c..ce69f229de 100644 --- a/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php +++ b/app/code/core/Mage/Api/Model/Server/Handler/Abstract.php @@ -33,6 +33,8 @@ */ abstract class Mage_Api_Model_Server_Handler_Abstract { + protected $_resourceSuffix = null; + public function __construct() { set_error_handler(array(get_class($this), 'handlePhpError'), E_ALL); @@ -107,7 +109,6 @@ protected function _isAllowed($resource, $privilege=null) /** * Check session expiration * - * @param none * @return boolean */ protected function _isSessionExpired () @@ -187,6 +188,20 @@ public function endSession($sessionId) return true; } + /** + * Enter description here... + * + * @param string $resource + * @return string + */ + protected function _prepareResourceModelName($resource) + { + if (null !== $this->_resourceSuffix) { + return $resource . $this->_resourceSuffix; + } + return $resource; + } + /** * Login user and Retrieve session id * @@ -229,7 +244,6 @@ public function call($sessionId, $apiPath, $args = array()) $resourcesAlias = $this->_getConfig()->getResourcesAlias(); $resources = $this->_getConfig()->getResources(); - if (isset($resourcesAlias->$resourceName)) { $resourceName = (string) $resourcesAlias->$resourceName; } @@ -258,7 +272,7 @@ public function call($sessionId, $apiPath, $args = array()) try { $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName); - $modelName = (string) $resources->$resourceName->model; + $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model); try { $model = Mage::getModel($modelName); if ($model instanceof Mage_Api_Model_Resource_Abstract) { @@ -374,7 +388,7 @@ public function multiCall($sessionId, array $calls = array(), $options = array() try { $method = (isset($methodInfo->method) ? (string) $methodInfo->method : $methodName); - $modelName = (string) $resources->$resourceName->model; + $modelName = $this->_prepareResourceModelName((string) $resources->$resourceName->model); try { $model = Mage::getModel($modelName); } catch (Exception $e) { diff --git a/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php b/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php new file mode 100644 index 0000000000..8b5ef96361 --- /dev/null +++ b/app/code/core/Mage/Api/Model/Server/V2/Adapter/Soap.php @@ -0,0 +1,68 @@ + + */ +class Mage_Api_Model_Server_V2_Adapter_Soap extends Mage_Api_Model_Server_Adapter_Soap +{ + /** + * Run webservice + * + * @param Mage_Api_Controller_Action $controller + * @return Mage_Api_Model_Server_Adapter_Soap + */ + public function run() + { + $urlModel = Mage::getModel('core/url') + ->setUseSession(false); + if ($this->getController()->getRequest()->getParam('wsdl')) { + $wsdlConfig = Mage::getModel('api/wsdl_config'); + $wsdlConfig->setHandler($this->getHandler()) + ->init(); + $this->getController()->getResponse() + ->setHeader('Content-Type','text/xml') + ->setBody($wsdlConfig->getWsdlContent()); + } elseif ($this->_extensionLoaded()) { + $this->_soap = new SoapServer($urlModel->getUrl('*/*/*', array('wsdl'=>1))); + use_soap_error_handler(false); + $this->_soap->setClass($this->getHandler()); + $this->getController()->getResponse() + ->setHeader('Content-Type', 'text/xml') + ->setBody($this->_soap->handle()); + + } else { + $this->fault('0', 'Unable to load Soap extension on the server'); + } + return $this; + } + + +} diff --git a/app/code/core/Mage/Api/Model/Server/V2/Handler.php b/app/code/core/Mage/Api/Model/Server/V2/Handler.php new file mode 100644 index 0000000000..c76365f1bb --- /dev/null +++ b/app/code/core/Mage/Api/Model/Server/V2/Handler.php @@ -0,0 +1,59 @@ + + */ +class Mage_Api_Model_Server_V2_Handler extends Mage_Api_Model_Server_Handler_Abstract +{ + protected $_resourceSuffix = '_v2'; + + /** + * Interceptor for all interfaces + * + * @param sttring $function + * @param array $args + */ + + public function __call( $function, $args ) + { + $sessionId = array_shift( $args ); + $apiKey = ''; + $config = Mage::getConfig(); + foreach ($config->getNode('api/v2/resources_function_prefix')->children() as $resource => $prefix) { + $prefix = $prefix->asArray(); + if (false !== strpos($function, $prefix)) { + $method = substr($function, strlen($prefix)); + $apiKey = $resource . '.' . strtolower($method[0]).substr($method, 1); + } + } + return $this->call($sessionId, $apiKey, $args); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Api/Model/Session.php b/app/code/core/Mage/Api/Model/Session.php index 7caca1bc38..ef3b6c561e 100644 --- a/app/code/core/Mage/Api/Model/Session.php +++ b/app/code/core/Mage/Api/Model/Session.php @@ -123,7 +123,6 @@ public function isAllowed($resource, $privilege=null) /** * Check session expiration * - * @param none * @return boolean */ public function isSessionExpired ($user) diff --git a/app/code/core/Mage/Api/Model/User.php b/app/code/core/Mage/Api/Model/User.php index 65042a3818..7fdacd890c 100644 --- a/app/code/core/Mage/Api/Model/User.php +++ b/app/code/core/Mage/Api/Model/User.php @@ -165,6 +165,10 @@ public function login($username, $apiKey) if ($this->authenticate($username, $apiKey)) { $this->setSessid($sessId); $this->getResource()->recordLogin($this); + Mage::dispatchEvent('api_user_authenticated', array( + 'model' => $this, + 'api_key' => $apiKey, + )); } return $this; diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config.php b/app/code/core/Mage/Api/Model/Wsdl/Config.php new file mode 100644 index 0000000000..e49dca712d --- /dev/null +++ b/app/code/core/Mage/Api/Model/Wsdl/Config.php @@ -0,0 +1,155 @@ + + */ +class Mage_Api_Model_Wsdl_Config extends Mage_Api_Model_Wsdl_Config_Base +{ + + protected $_wsdlContent = null; + + public function __construct($sourceData=null) + { + $this->setCacheId('wsdl_config_global'); + parent::__construct($sourceData); + } + + /** + * Set content of wsdl file as string + * + * @param string $wsdlContent + * @return Mage_Api_Model_Wsdl_Config + */ + public function setWsdlContent($wsdlContent) + { + $this->_wsdlContent = $wsdlContent; + return $this; + } + + /** + * Return wsdl content + * + * @return string + */ + public function getWsdlContent() + { + return $this->_wsdlContent; + } + + public function getCache() + { + return Mage::app()->getCache(); + } + + protected function _loadCache($id) + { + return Mage::app()->loadCache($id); + } + + protected function _saveCache($data, $id, $tags=array(), $lifetime=false) + { + return Mage::app()->saveCache($data, $id, $tags, $lifetime); + } + + protected function _removeCache($id) + { + return Mage::app()->removeCache($id); + } + + public function init() + { + $this->setCacheChecksum(null); + $saveCache = true; + + // check if local modules are disabled + $disableLocalModules = (string)$this->getNode('global/disable_local_modules'); + $disableLocalModules = !empty($disableLocalModules) && (('true' === $disableLocalModules) || ('1' === $disableLocalModules)); + + if ($disableLocalModules) { + /** + * Reset include path + */ + $codeDir = Mage::getConfig()->getOptions()->getCodeDir(); + $libDir = Mage::getConfig()->getOptions()->getLibDir(); + + set_include_path( + // excluded '/app/code/local' + BP . DS . 'app' . DS . 'code' . DS . 'community' . PS . + BP . DS . 'app' . DS . 'code' . DS . 'core' . PS . + BP . DS . 'lib' . PS . + /** + * Problem with concatenate BP . $codeDir + */ + /*BP . $codeDir . DS .'community' . PS . + BP . $codeDir . DS .'core' . PS . + BP . $libDir . PS .*/ + Mage::registry('original_include_path') + ); + } + + if (Mage::isInstalled()) { + if (Mage::app()->useCache('config')) { + $loaded = $this->loadCache(); + if ($loaded) { + return $this; + } + } + } + + $mergeWsdl = new Mage_Api_Model_Wsdl_Config_Base(); + $mergeWsdl->setHandler($this->getHandler()); + + $modules = Mage::getConfig()->getNode('modules')->children(); + + $baseWsdlFile = Mage::getConfig()->getModuleDir('etc', "Mage_Api").DS.'wsdl2.xml'; + $this->loadFile($baseWsdlFile); + + foreach ($modules as $modName=>$module) { +// if ($module->is('active') && $modName == 'Mage_Customer') { + if ($module->is('active') && $modName != 'Mage_Api') { + if ($disableLocalModules && ('local' === (string)$module->codePool)) { + continue; + } + $wsdlFile = Mage::getConfig()->getModuleDir('etc', $modName).DS.'wsdl.xml'; + if ($mergeWsdl->loadFile($wsdlFile)) { + $this->extend($mergeWsdl, true); + } + } + } + $this->setWsdlContent($this->_xml->asXML()); + + if (Mage::app()->useCache('config')) { + $this->saveCache(array('config')); + } + + return $this; + } +} diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php b/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php new file mode 100644 index 0000000000..f002d6478f --- /dev/null +++ b/app/code/core/Mage/Api/Model/Wsdl/Config/Base.php @@ -0,0 +1,94 @@ + + */ +class Mage_Api_Model_Wsdl_Config_Base extends Varien_Simplexml_Config +{ + protected $_handler = ''; + + /** + * @var Varien_Object + */ + protected $_wsdlVariables = null; + + public function __construct($sourceData=null) + { + $this->_elementClass = 'Mage_Api_Model_Wsdl_Config_Element'; + parent::__construct($sourceData); + } + + /** + * Set handler + * + * @param string $handler + * @return Mage_Api_Model_Wsdl_Config_Base + */ + public function setHandler($handler) + { + $this->_handler = $handler; + return $this; + } + + /** + * Get handler + * + * @return string + */ + public function getHandler() + { + return $this->_handler; + } + + /** + * Processing file data + * + * @param string $text + * @return string + */ + public function processFileData($text) + { + $template = Mage::getModel('core/email_template_filter'); + + if (null === $this->_wsdlVariables) { + $this->_wsdlVariables = new Varien_Object(); + $this->_wsdlVariables->setUrl(Mage::getUrl('*/*/*')); + $this->_wsdlVariables->setName('Magento'); + $this->_wsdlVariables->setHandler($this->getHandler()); + } + + $template->setVariables(array('wsdl'=>$this->_wsdlVariables)); + + $text = $template->filter($text); + + return $text; + } +} diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php b/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php new file mode 100644 index 0000000000..52b159aa48 --- /dev/null +++ b/app/code/core/Mage/Api/Model/Wsdl/Config/Element.php @@ -0,0 +1,256 @@ +getChildren($source) as $namespace => $children) { + foreach ($children as $child) { + $this->extendChild($child, $overwrite, $namespace); + } + } + + return $this; + } + + /** + * Extends one node + * + * @param Varien_Simplexml_Element $source + * @param boolean $overwrite + * @return Varien_Simplexml_Element + */ + public function extendChild($source, $overwrite=false, $elmNamespace = '') + { + // this will be our new target node + $targetChild = null; + + // name of the source node + $sourceName = $source->getName(); + + // here we have children of our source node + $sourceChildren = $this->getChildren($source); + + if ($elmNamespace == '') { + $elmNamespace = null; + } + + if (!$source->hasChildren()) { + // handle string node + $elm = $this->getElementByName($source, $elmNamespace); + if (!is_null($elm)) { + + // if target already has children return without regard + if ($this->getChildren($elm)) { + return $this; + } + if ($overwrite) { +// unset($this->$sourceName); + unset($elm); + } else { + return $this; + } + } + $targetChild = $this->addChild($sourceName, $source->xmlentities(), $elmNamespace); + $targetChild->setParent($this); + foreach ($this->getAttributes($source) as $namespace => $attributes) { + foreach ($attributes as $key => $value) { + if ($namespace == '') { + $namespace = null; + } + $targetChild->addAttribute($key, $this->xmlentities($value), $namespace); + } + } + return $this; + } + + $elm = $this->getElementByName($source, $elmNamespace); + if (!is_null($elm)) { + $targetChild = $elm; + } + if (is_null($targetChild)) { + // if child target is not found create new and descend + $targetChild = $this->addChild($sourceName, null, $elmNamespace); + $targetChild->setParent($this); + foreach ($this->getAttributes($source) as $namespace => $attributes) { + foreach ($attributes as $key => $value) { + if ($namespace == '') { + $namespace = null; + } + $targetChild->addAttribute($key, $this->xmlentities($value), $namespace); + } + } + } + + foreach ($sourceChildren as $elmNamespace => $children) { + foreach ($children as $childKey => $childNode) { + $targetChild->extendChild($childNode, $overwrite, $elmNamespace); + } + } + + return $this; + } + + /** + * Return attributes of all namespaces + * + * array( + * namespace => array( + * attribute_key => attribute_value, + * ... + * ) + * ) + * + * @param Varien_Simplexml_Element $source + * @return array + */ + public function getAttributes($source, $namespace = null) + { + $attributes = array(); + if (!is_null($namespace)) { + $attributes[$namespace] = $source->attributes($namespace); + return $attributes; + } + $namespaces = $source->getNamespaces(true); + $attributes[''] = $source->attributes(''); + foreach ($namespaces as $key => $value) { + if ($key == '' || $key == 'soap') { + continue; + } + $attributes[$value] = $source->attributes($value); + } + return $attributes; + } + + /** + * Return children of all namespaces + * + * @param Varien_Simplexml_Element $source + */ + public function getChildren($source) + { + $children = array(); + $namespaces = $source->getNamespaces(true); + $children[''] = $source->children(''); + foreach ($namespaces as $key => $value) { + if ($key == '' || $key == 'wsdl') { + $value = ''; + continue; + } + $children[$value] = $source->children($value); + } + return $children; + } + + /** + * Return if has children + * + * @return boolean + */ + public function hasChildren() + { + if (!$this->getChildren($this)) { + return false; + } + + // simplexml bug: @attributes is in children() but invisible in foreach + foreach ($this->getChildren($this) as $namespace => $children) { + foreach ($children as $k => $child) { + return true; + } + } + return false; + } + + /** + * Return element by tag name, and checking attributes with namespaces + * + * @param Varien_Simplexml_Element $source + * @param string $namespace + * @return null|Varien_Simplexml_Element + */ + public function getElementByName($source, $elmNamespace = '') + { + $sourceName = $source->getName(); + $extendElmAttributes = $this->getAttributes($source); + foreach ($this->children($elmNamespace) as $k => $child) { + if ($child->getName() == $sourceName) { + $elm = true; + foreach ($extendElmAttributes as $namespace => $attributes) { + /** + * if count of attributes of extend element is 0 in $namespace, + * and current element has attributes in $namespace - different elements + */ +// if (!count($attributes) && count($this->getAttributes($child, $namespace))) { +// foreach ($this->getAttributes($child, $namespace) as $attribute) { +// $elm = false; +// break; +// } +// } + foreach ($attributes as $key => $value) { + if (is_null($child->getAttribute($key, $namespace)) || $child->getAttribute($key, $namespace) != $value) { + $elm = false; + } + } + } + /** + * if count of namespaces attributes of element to extend is 0, + * but current element has namespaces attributes - different elements + */ + if (!count($extendElmAttributes) && count($this->getAttributes($child))) { + $elm = false; + } + if ($elm) { + return $child; + } + } + } + return null; + } + + /** + * Returns attribute value by attribute name + * + * @return string + */ + public function getAttribute($name, $namespace = ''){ + $attrs = $this->attributes($namespace); + return isset($attrs[$name]) ? (string)$attrs[$name] : null; + } + +} diff --git a/app/code/core/Mage/Api/controllers/V2/SoapController.php b/app/code/core/Mage/Api/controllers/V2/SoapController.php new file mode 100644 index 0000000000..d76f22c062 --- /dev/null +++ b/app/code/core/Mage/Api/controllers/V2/SoapController.php @@ -0,0 +1,44 @@ + + */ +class Mage_Api_V2_SoapController extends Mage_Api_Controller_Action +{ + public function indexAction() + { + $server = Mage::getSingleton('api/server'); + + /* @var $server Mage_Api_Model_Server */ + $this->_getServer()->init($this, 'soap_v2', 'soap_v2') + ->run(); + } +} // Class Mage_Api_IndexController End \ No newline at end of file diff --git a/app/code/core/Mage/Api/etc/api.xml b/app/code/core/Mage/Api/etc/api.xml index 8fb322d4fb..3206e5832a 100644 --- a/app/code/core/Mage/Api/etc/api.xml +++ b/app/code/core/Mage/Api/etc/api.xml @@ -38,6 +38,16 @@ + + api/server_v2_adapter_soap + soap_v2 + 1 + + + + + + api/server_adapter_xmlrpc default @@ -51,6 +61,9 @@ api/server_handler + + api/server_v2_handler + diff --git a/app/code/core/Mage/Api/etc/wsdl.xml b/app/code/core/Mage/Api/etc/wsdl.xml index d0c9484541..b8acdd4963 100644 --- a/app/code/core/Mage/Api/etc/wsdl.xml +++ b/app/code/core/Mage/Api/etc/wsdl.xml @@ -1,197 +1,191 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Call api functionality - - - - - Multiple calls of resource functionality - - - - - End web service session - - - - - Login user and retrive session id - - - - - Start web service session - - - - - List of available resources - - - - - List of resource faults - - - - - List of global faults - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Call api functionality + + + + + Multiple calls of resource functionality + + + + + End web service session + + + + + Login user and retrive session id + + + + + Start web service session + + + + + List of available resources + + + + + List of resource faults + + + + + List of global faults + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/Api/etc/wsdl2.xml b/app/code/core/Mage/Api/etc/wsdl2.xml new file mode 100644 index 0000000000..9893b25bce --- /dev/null +++ b/app/code/core/Mage/Api/etc/wsdl2.xml @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + End web service session + + + + + Login user and retrive session id + + + + + Start web service session + + + + + List of available resources + + + + + List of resource faults + + + + + List of global faults + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/Backup/Model/Db.php b/app/code/core/Mage/Backup/Model/Db.php index 3758747531..526599cf83 100644 --- a/app/code/core/Mage/Backup/Model/Db.php +++ b/app/code/core/Mage/Backup/Model/Db.php @@ -18,22 +18,23 @@ * 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_Backup - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Backup + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Database backup model * - * @category Mage - * @package Mage_Backup + * @category Mage + * @package Mage_Backup * @author Magento Core Team */ - class Mage_Backup_Model_Db { + /** * Buffer length for multi rows * default 512 Kb @@ -147,4 +148,5 @@ public function createBackup(Mage_Backup_Model_Backup $backup) return $this; } + } diff --git a/app/code/core/Mage/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php b/app/code/core/Mage/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php index 269751ddf2..24612d37fb 100644 --- a/app/code/core/Mage/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php +++ b/app/code/core/Mage/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php @@ -1,204 +1,209 @@ - - */ -class Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option extends Mage_Adminhtml_Block_Widget -{ - protected $_element = null; - protected $_customerGroups = null; - protected $_websites = null; - - protected $_oprions = null; - - public function __construct() - { - $this->setTemplate('bundle/product/edit/bundle/option.phtml'); - } - - public function getFieldId() - { - return 'bundle_option'; - } - - public function getFieldName() - { - return 'bundle_options'; - } - - public function getProduct() - { - if (!$this->getData('product')) { - $this->setData('product', Mage::registry('product')); - } - return $this->getData('product'); - } - - public function render(Varien_Data_Form_Element_Abstract $element) - { - $this->setElement($element); - return $this->toHtml(); - } - - public function setElement(Varien_Data_Form_Element_Abstract $element) - { - $this->_element = $element; - return $this; - } - - public function getElement() - { - return $this->_element; - } - - public function isMultiWebsites() - { - return !Mage::app()->isSingleStoreMode(); - } - - protected function _prepareLayout() - { - $this->setChild('add_selection_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'id' => $this->getFieldId().'_{{index}}_add_button', - 'label' => Mage::helper('bundle')->__('Add Selection'), - 'on_click' => 'bSelection.showSearch(event)', - 'class' => 'add' - ))); - - $this->setChild('close_search_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'id' => $this->getFieldId().'_{{index}}_close_button', - 'label' => Mage::helper('bundle')->__('Close'), - 'on_click' => 'bSelection.closeSearch(event)', - 'class' => 'back no-display' - ))); - - $this->setChild('option_delete_button', - $this->getLayout()->createBlock('adminhtml/widget_button') - ->setData(array( - 'label' => Mage::helper('catalog')->__('Delete Option'), - 'class' => 'delete delete-product-option', - 'on_click' => 'bOption.remove(event)' - )) - ); - - $this->setChild('selection_template', - $this->getLayout()->createBlock('bundle/adminhtml_catalog_product_edit_tab_bundle_option_selection') - ); - - return parent::_prepareLayout(); - } - - public function getAddButtonHtml() - { - return $this->getChildHtml('add_button'); - } - - public function getCloseSearchButtonHtml() - { - return $this->getChildHtml('close_search_button'); - } - - public function getAddSelectionButtonHtml() - { - return $this->getChildHtml('add_selection_button'); - } - - public function getOptions() - { - if (!$this->_options) { - $this->getProduct()->getTypeInstance()->setStoreFilter($this->getProduct()->getStoreId()); - - $optionCollection = $this->getProduct()->getTypeInstance()->getOptionsCollection(); - - $selectionCollection = $this->getProduct()->getTypeInstance()->getSelectionsCollection( - $this->getProduct()->getTypeInstance()->getOptionsIds() - ); - - - $this->_options = $optionCollection->appendSelections($selectionCollection); - } - return $this->_options; - } - - public function getAddButtonId() - { - $buttonId = $this->getLayout() - ->getBlock('admin.product.bundle.items') - ->getChild('add_button')->getId(); - return $buttonId; - } - - public function getOptionDeleteButtonHtml() - { - return $this->getChildHtml('option_delete_button'); - } - - public function getSelectionHtml() - { - return $this->getChildHtml('selection_template'); - } - - public function getTypeSelectHtml() - { - $select = $this->getLayout()->createBlock('adminhtml/html_select') - ->setData(array( - 'id' => $this->getFieldId().'_{{index}}_type', - 'class' => 'select select-product-option-type required-option-select', - 'extra_params' => 'onchange="bOption.changeType(event)"' - )) - ->setName($this->getFieldName().'[{{index}}][type]') - ->setOptions(Mage::getSingleton('bundle/source_option_type')->toOptionArray()); - - return $select->getHtml(); - } - - public function getRequireSelectHtml() - { - $select = $this->getLayout()->createBlock('adminhtml/html_select') - ->setData(array( - 'id' => $this->getFieldId().'_{{index}}_required', - 'class' => 'select' - )) - ->setName($this->getFieldName().'[{{index}}][required]') - ->setOptions(Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray()); - - return $select->getHtml(); - } - - public function isDefaultStore() - { - return ($this->getProduct()->getStoreId() == '0'); - } + + */ +class Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option extends Mage_Adminhtml_Block_Widget +{ + protected $_element = null; + protected $_customerGroups = null; + protected $_websites = null; + + protected $_oprions = null; + + public function __construct() + { + $this->setTemplate('bundle/product/edit/bundle/option.phtml'); + } + + public function getFieldId() + { + return 'bundle_option'; + } + + public function getFieldName() + { + return 'bundle_options'; + } + + /** + * Retrieve Product object + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + if (!$this->getData('product')) { + $this->setData('product', Mage::registry('product')); + } + return $this->getData('product'); + } + + public function render(Varien_Data_Form_Element_Abstract $element) + { + $this->setElement($element); + return $this->toHtml(); + } + + public function setElement(Varien_Data_Form_Element_Abstract $element) + { + $this->_element = $element; + return $this; + } + + public function getElement() + { + return $this->_element; + } + + public function isMultiWebsites() + { + return !Mage::app()->isSingleStoreMode(); + } + + protected function _prepareLayout() + { + $this->setChild('add_selection_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'id' => $this->getFieldId().'_{{index}}_add_button', + 'label' => Mage::helper('bundle')->__('Add Selection'), + 'on_click' => 'bSelection.showSearch(event)', + 'class' => 'add' + ))); + + $this->setChild('close_search_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'id' => $this->getFieldId().'_{{index}}_close_button', + 'label' => Mage::helper('bundle')->__('Close'), + 'on_click' => 'bSelection.closeSearch(event)', + 'class' => 'back no-display' + ))); + + $this->setChild('option_delete_button', + $this->getLayout()->createBlock('adminhtml/widget_button') + ->setData(array( + 'label' => Mage::helper('catalog')->__('Delete Option'), + 'class' => 'delete delete-product-option', + 'on_click' => 'bOption.remove(event)' + )) + ); + + $this->setChild('selection_template', + $this->getLayout()->createBlock('bundle/adminhtml_catalog_product_edit_tab_bundle_option_selection') + ); + + return parent::_prepareLayout(); + } + + public function getAddButtonHtml() + { + return $this->getChildHtml('add_button'); + } + + public function getCloseSearchButtonHtml() + { + return $this->getChildHtml('close_search_button'); + } + + public function getAddSelectionButtonHtml() + { + return $this->getChildHtml('add_selection_button'); + } + + public function getOptions() + { + if (!$this->_options) { + $this->getProduct()->getTypeInstance(true)->setStoreFilter($this->getProduct()->getStoreId(), $this->getProduct()); + + $optionCollection = $this->getProduct()->getTypeInstance(true)->getOptionsCollection($this->getProduct()); + + $selectionCollection = $this->getProduct()->getTypeInstance(true)->getSelectionsCollection( + $this->getProduct()->getTypeInstance(true)->getOptionsIds($this->getProduct()), + $this->getProduct() + ); + + $this->_options = $optionCollection->appendSelections($selectionCollection); + } + return $this->_options; + } + + public function getAddButtonId() + { + $buttonId = $this->getLayout() + ->getBlock('admin.product.bundle.items') + ->getChild('add_button')->getId(); + return $buttonId; + } + + public function getOptionDeleteButtonHtml() + { + return $this->getChildHtml('option_delete_button'); + } + + public function getSelectionHtml() + { + return $this->getChildHtml('selection_template'); + } + + public function getTypeSelectHtml() + { + $select = $this->getLayout()->createBlock('adminhtml/html_select') + ->setData(array( + 'id' => $this->getFieldId().'_{{index}}_type', + 'class' => 'select select-product-option-type required-option-select', + 'extra_params' => 'onchange="bOption.changeType(event)"' + )) + ->setName($this->getFieldName().'[{{index}}][type]') + ->setOptions(Mage::getSingleton('bundle/source_option_type')->toOptionArray()); + + return $select->getHtml(); + } + + public function getRequireSelectHtml() + { + $select = $this->getLayout()->createBlock('adminhtml/html_select') + ->setData(array( + 'id' => $this->getFieldId().'_{{index}}_required', + 'class' => 'select' + )) + ->setName($this->getFieldName().'[{{index}}][required]') + ->setOptions(Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray()); + + return $select->getHtml(); + } + + public function isDefaultStore() + { + return ($this->getProduct()->getStoreId() == '0'); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php index dc78c4a6e4..5b00f5c2e0 100644 --- a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -40,13 +40,14 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl public function getOptions() { if (!$this->_options) { - $this->getProduct()->getTypeInstance()->setStoreFilter($this->getProduct()->getStoreId()); + $this->getProduct()->getTypeInstance(true)->setStoreFilter($this->getProduct()->getStoreId(), $this->getProduct()); - $optionCollection = $this->getProduct()->getTypeInstance()->getOptionsCollection(); + $optionCollection = $this->getProduct()->getTypeInstance(true)->getOptionsCollection($this->getProduct()); - $selectionCollection = $this->getProduct()->getTypeInstance()->getSelectionsCollection( - $this->getProduct()->getTypeInstance()->getOptionsIds() - ); + $selectionCollection = $this->getProduct()->getTypeInstance(true)->getSelectionsCollection( + $this->getProduct()->getTypeInstance(true)->getOptionsIds($this->getProduct()), + $this->getProduct() + ); $this->_options = $optionCollection->appendSelections($selectionCollection, false, false); } diff --git a/app/code/core/Mage/Bundle/Block/Checkout/Cart/Item/Renderer.php b/app/code/core/Mage/Bundle/Block/Checkout/Cart/Item/Renderer.php index 94719a6e5f..415c1987d0 100644 --- a/app/code/core/Mage/Bundle/Block/Checkout/Cart/Item/Renderer.php +++ b/app/code/core/Mage/Bundle/Block/Checkout/Cart/Item/Renderer.php @@ -1,120 +1,121 @@ - - */ -class Mage_Bundle_Block_Checkout_Cart_Item_Renderer extends Mage_Checkout_Block_Cart_Item_Renderer -{ - /** - * Get bundled selections (slections-products collection) - * - * Returns array of options objects. - * Each option object will contain array of selections objects - * - * @return array - */ - protected function _getBundleOptions($useCache = true) - { - $options = array(); - - /** - * @var Mage_Bundle_Model_Product_Type - */ - $typeInstance = $this->getProduct()->getTypeInstance(); - - // get bundle options - $optionsQuoteItemOption = $this->getItem()->getOptionByCode('bundle_option_ids'); - $bundleOptionsIds = unserialize($optionsQuoteItemOption->getValue()); - if ($bundleOptionsIds) { - /** - * @var Mage_Bundle_Model_Mysql4_Option_Collection - */ - $optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds); - - // get and add bundle selections collection - $selectionsQuoteItemOption = $this->getItem()->getOptionByCode('bundle_selection_ids'); - - $selectionsCollection = $typeInstance->getSelectionsByIds( - unserialize($selectionsQuoteItemOption->getValue()) - ); - - $bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true); - foreach ($bundleOptions as $bundleOption) { - if ($bundleOption->getSelections()) { - $option = array('label' => $bundleOption->getTitle(), "value" => array()); - $bundleSelections = $bundleOption->getSelections(); - - foreach ($bundleSelections as $bundleSelection) { - $option['value'][] = $this->_getSelectionQty($bundleSelection->getSelectionId()).' x '. $this->htmlEscape($bundleSelection->getName()). ' ' .Mage::helper('core')->currency($this->_getSelectionFinalPrice($bundleSelection)); - } - - $options[] = $option; - } - } - } - return $options; - } - - /** - * Obtain final price of selection in a bundle product - * - * @param Mage_Catalog_Model_Product $selectionProduct - * @return decimal - */ - protected function _getSelectionFinalPrice($selectionProduct) - { - $bundleProduct = $this->getProduct(); - return $bundleProduct->getPriceModel()->getSelectionFinalPrice( - $bundleProduct, $selectionProduct, - $this->getQty(), - $this->_getSelectionQty($selectionProduct->getSelectionId()) - ); - } - - /** - * Get selection quantity - * - * @param int $selectionId - * @return decimal - */ - protected function _getSelectionQty($selectionId) - { - if ($selectionQty = $this->getProduct()->getCustomOption('selection_qty_' . $selectionId)) { - return $selectionQty->getValue(); - } - return 0; - } - - public function getOptionList() - { - return array_merge($this->_getBundleOptions(), parent::getOptionList()); - } -} + + */ +class Mage_Bundle_Block_Checkout_Cart_Item_Renderer extends Mage_Checkout_Block_Cart_Item_Renderer +{ + /** + * Get bundled selections (slections-products collection) + * + * Returns array of options objects. + * Each option object will contain array of selections objects + * + * @return array + */ + protected function _getBundleOptions($useCache = true) + { + $options = array(); + + /** + * @var Mage_Bundle_Model_Product_Type + */ + $typeInstance = $this->getProduct()->getTypeInstance(true); + + // get bundle options + $optionsQuoteItemOption = $this->getItem()->getOptionByCode('bundle_option_ids'); + $bundleOptionsIds = unserialize($optionsQuoteItemOption->getValue()); + if ($bundleOptionsIds) { + /** + * @var Mage_Bundle_Model_Mysql4_Option_Collection + */ + $optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $this->getProduct()); + + // get and add bundle selections collection + $selectionsQuoteItemOption = $this->getItem()->getOptionByCode('bundle_selection_ids'); + + $selectionsCollection = $typeInstance->getSelectionsByIds( + unserialize($selectionsQuoteItemOption->getValue()), + $this->getProduct() + ); + + $bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true); + foreach ($bundleOptions as $bundleOption) { + if ($bundleOption->getSelections()) { + $option = array('label' => $bundleOption->getTitle(), "value" => array()); + $bundleSelections = $bundleOption->getSelections(); + + foreach ($bundleSelections as $bundleSelection) { + $option['value'][] = $this->_getSelectionQty($bundleSelection->getSelectionId()).' x '. $this->htmlEscape($bundleSelection->getName()). ' ' .Mage::helper('core')->currency($this->_getSelectionFinalPrice($bundleSelection)); + } + + $options[] = $option; + } + } + } + return $options; + } + + /** + * Obtain final price of selection in a bundle product + * + * @param Mage_Catalog_Model_Product $selectionProduct + * @return decimal + */ + protected function _getSelectionFinalPrice($selectionProduct) + { + $bundleProduct = $this->getProduct(); + return $bundleProduct->getPriceModel()->getSelectionFinalPrice( + $bundleProduct, $selectionProduct, + $this->getQty(), + $this->_getSelectionQty($selectionProduct->getSelectionId()) + ); + } + + /** + * Get selection quantity + * + * @param int $selectionId + * @return decimal + */ + protected function _getSelectionQty($selectionId) + { + if ($selectionQty = $this->getProduct()->getCustomOption('selection_qty_' . $selectionId)) { + return $selectionQty->getValue(); + } + return 0; + } + + public function getOptionList() + { + return array_merge($this->_getBundleOptions(), parent::getOptionList()); + } +} diff --git a/app/code/core/Mage/Bundle/Model/Observer.php b/app/code/core/Mage/Bundle/Model/Observer.php index f120aea580..5876460040 100644 --- a/app/code/core/Mage/Bundle/Model/Observer.php +++ b/app/code/core/Mage/Bundle/Model/Observer.php @@ -1,227 +1,228 @@ - - */ -class Mage_Bundle_Model_Observer -{ - /** - * Setting Bundle Items Data to product for father processing - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function prepareProductSave($observer) - { - $request = $observer->getEvent()->getRequest(); - $product = $observer->getEvent()->getProduct(); - - if ($items = $request->getPost('bundle_options')) { - $product->setBundleOptionsData($items); - } - - if ($selections = $request->getPost('bundle_selections')) { - $product->setBundleSelectionsData($selections); - } - - if ($product->getPriceType() == '0') { - $product->setCanSaveCustomOptions(true); - if ($customOptions = $product->getProductOptions()) { - foreach ($customOptions as $key => $customOption) { - $customOptions[$key]['is_delete'] = 1; - } - $product->setProductOptions($customOptions); - } - } - - $product->setCanSaveBundleSelections((bool)$request->getPost('affect_bundle_product_selections')); - - return $this; - } - - /** - * Append bundles in upsell list for current product - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function appendUpsellProducts($observer) - { - $product = $observer->getEvent()->getProduct(); - - if ($product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) { - return $this; - } - - $collection = $observer->getEvent()->getCollection(); - $limit = $observer->getEvent()->getLimit(); - - $bundles = Mage::getModel('catalog/product')->getResourceCollection() - ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) - ->addStoreFilter() - ->addMinimalPrice() - - ->joinTable('bundle/option', 'parent_id=entity_id', array('option_id' => 'option_id')) - ->joinTable('bundle/selection', 'option_id=option_id', array('product_id' => 'product_id'), '{{table}}.product_id='.$product->getId()); - - $ids = $collection->getAllIds(); - if (count($ids)) { - $bundles->addIdFilter($ids, true); - } - - Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($bundles); - Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bundles); - - $bundles->getSelect()->group('entity_id'); - - if (isset($limit['bundle'])) { - $bundles->setPageSize($limit['bundle']); - } - $bundles->load(); - - foreach ($bundles->getItems() as $item) { - $collection->addItem($item); - } - - return $this; - } - - /** - * Append selection attributes to selection's order item - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function appendBundleSelectionData($observer) - { - $orderItem = $observer->getEvent()->getOrderItem(); - $quoteItem = $observer->getEvent()->getItem(); - - if ($attributes = $quoteItem->getProduct()->getCustomOption('bundle_selection_attributes')) { - $productOptions = $orderItem->getProductOptions(); - $productOptions['bundle_selection_attributes'] = $attributes->getValue(); - $orderItem->setProductOptions($productOptions); - } - - return $this; - } - - /** - * loadding product options for products if there is one bundle in collection - * only for front end - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function loadProductOptions($observer) - { - $collection = $observer->getEvent()->getCollection(); - foreach ($collection->getItems() as $item){ - if ($item->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { - $collection->addOptionsToResult(); - return $this; - } - } - return $this; - } - - /** - * duplicating bundle options and selections - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function duplicateProduct($observer) - { - $product = $observer->getEvent()->getCurrentProduct(); - - if ($product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { - //do nothing if not bundle - return $this; - } - - $newProduct = $observer->getEvent()->getNewProduct(); - - $product->getTypeInstance()->setStoreFilter($product->getStoreId()); - $optionCollection = $product->getTypeInstance()->getOptionsCollection(); - $selectionCollection = $product->getTypeInstance()->getSelectionsCollection( - $product->getTypeInstance()->getOptionsIds() - ); - $optionCollection->appendSelections($selectionCollection); - - $optionRawData = array(); - $selectionRawData = array(); - - $i = 0; - foreach ($optionCollection as $option) { - $optionRawData[$i] = array( - 'required' => $option->getData('required'), - 'position' => $option->getData('position'), - 'type' => $option->getData('type'), - 'title' => $option->getData('title')?$option->getData('title'):$option->getData('default_title'), - 'delete' => '' - ); - foreach ($option->getSelections() as $selection) { - $selectionRawData[$i][] = array( - 'product_id' => $selection->getProductId(), - 'position' => $selection->getPosition(), - 'is_default' => $selection->getIsDefault(), - 'selection_price_type' => $selection->getSelectionPriceType(), - 'selection_price_value' => $selection->getSelectionPriceValue(), - 'selection_qty' => $selection->getSelectionQty(), - 'selection_can_change_qty' => $selection->getSelectionCanChangeQty(), - 'delete' => '' - ); - } - $i++; - } - - $newProduct->setBundleOptionsData($optionRawData); - $newProduct->setBundleSelectionsData($selectionRawData); - return $this; - } - - /** - * Setting attribute tab block for bundle - * - * @param Varien_Object $observer - * @return Mage_Bundle_Model_Observer - */ - public function setAttributeTabBlock($observer) - { - $product = $observer->getEvent()->getProduct(); - if ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { - Mage::helper('adminhtml/catalog') - ->setAttributeTabBlock('bundle/adminhtml_catalog_product_edit_tab_attributes'); - } - return $this; - } -} + + */ +class Mage_Bundle_Model_Observer +{ + /** + * Setting Bundle Items Data to product for father processing + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function prepareProductSave($observer) + { + $request = $observer->getEvent()->getRequest(); + $product = $observer->getEvent()->getProduct(); + + if ($items = $request->getPost('bundle_options')) { + $product->setBundleOptionsData($items); + } + + if ($selections = $request->getPost('bundle_selections')) { + $product->setBundleSelectionsData($selections); + } + + if ($product->getPriceType() == '0') { + $product->setCanSaveCustomOptions(true); + if ($customOptions = $product->getProductOptions()) { + foreach ($customOptions as $key => $customOption) { + $customOptions[$key]['is_delete'] = 1; + } + $product->setProductOptions($customOptions); + } + } + + $product->setCanSaveBundleSelections((bool)$request->getPost('affect_bundle_product_selections')); + + return $this; + } + + /** + * Append bundles in upsell list for current product + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function appendUpsellProducts($observer) + { + $product = $observer->getEvent()->getProduct(); + + if ($product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) { + return $this; + } + + $collection = $observer->getEvent()->getCollection(); + $limit = $observer->getEvent()->getLimit(); + + $bundles = Mage::getModel('catalog/product')->getResourceCollection() + ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) + ->addStoreFilter() + ->addMinimalPrice() + + ->joinTable('bundle/option', 'parent_id=entity_id', array('option_id' => 'option_id')) + ->joinTable('bundle/selection', 'option_id=option_id', array('product_id' => 'product_id'), '{{table}}.product_id='.$product->getId()); + + $ids = $collection->getAllIds(); + if (count($ids)) { + $bundles->addIdFilter($ids, true); + } + + Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($bundles); + Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bundles); + + $bundles->getSelect()->group('entity_id'); + + if (isset($limit['bundle'])) { + $bundles->setPageSize($limit['bundle']); + } + $bundles->load(); + + foreach ($bundles->getItems() as $item) { + $collection->addItem($item); + } + + return $this; + } + + /** + * Append selection attributes to selection's order item + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function appendBundleSelectionData($observer) + { + $orderItem = $observer->getEvent()->getOrderItem(); + $quoteItem = $observer->getEvent()->getItem(); + + if ($attributes = $quoteItem->getProduct()->getCustomOption('bundle_selection_attributes')) { + $productOptions = $orderItem->getProductOptions(); + $productOptions['bundle_selection_attributes'] = $attributes->getValue(); + $orderItem->setProductOptions($productOptions); + } + + return $this; + } + + /** + * loadding product options for products if there is one bundle in collection + * only for front end + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function loadProductOptions($observer) + { + $collection = $observer->getEvent()->getCollection(); + foreach ($collection->getItems() as $item){ + if ($item->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { + $collection->addOptionsToResult(); + return $this; + } + } + return $this; + } + + /** + * duplicating bundle options and selections + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function duplicateProduct($observer) + { + $product = $observer->getEvent()->getCurrentProduct(); + + if ($product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { + //do nothing if not bundle + return $this; + } + + $newProduct = $observer->getEvent()->getNewProduct(); + + $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product); + $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product); + $selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection( + $product->getTypeInstance(true)->getOptionsIds($product), + $product + ); + $optionCollection->appendSelections($selectionCollection); + + $optionRawData = array(); + $selectionRawData = array(); + + $i = 0; + foreach ($optionCollection as $option) { + $optionRawData[$i] = array( + 'required' => $option->getData('required'), + 'position' => $option->getData('position'), + 'type' => $option->getData('type'), + 'title' => $option->getData('title')?$option->getData('title'):$option->getData('default_title'), + 'delete' => '' + ); + foreach ($option->getSelections() as $selection) { + $selectionRawData[$i][] = array( + 'product_id' => $selection->getProductId(), + 'position' => $selection->getPosition(), + 'is_default' => $selection->getIsDefault(), + 'selection_price_type' => $selection->getSelectionPriceType(), + 'selection_price_value' => $selection->getSelectionPriceValue(), + 'selection_qty' => $selection->getSelectionQty(), + 'selection_can_change_qty' => $selection->getSelectionCanChangeQty(), + 'delete' => '' + ); + } + $i++; + } + + $newProduct->setBundleOptionsData($optionRawData); + $newProduct->setBundleSelectionsData($selectionRawData); + return $this; + } + + /** + * Setting attribute tab block for bundle + * + * @param Varien_Object $observer + * @return Mage_Bundle_Model_Observer + */ + public function setAttributeTabBlock($observer) + { + $product = $observer->getEvent()->getProduct(); + if ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) { + Mage::helper('adminhtml/catalog') + ->setAttributeTabBlock('bundle/adminhtml_catalog_product_edit_tab_attributes'); + } + return $this; + } +} diff --git a/app/code/core/Mage/Bundle/Model/Product/Attribute/Source/Price/View.php b/app/code/core/Mage/Bundle/Model/Product/Attribute/Source/Price/View.php index 44b717fd4c..300b9103a4 100644 --- a/app/code/core/Mage/Bundle/Model/Product/Attribute/Source/Price/View.php +++ b/app/code/core/Mage/Bundle/Model/Product/Attribute/Source/Price/View.php @@ -67,4 +67,34 @@ public function getOptionText($value) } return false; } + + /** + * Get Column(s) names for flat data building + * + * @return array + */ + public function getFlatColums() + { + $columns = array(); + $columns[$this->getAttribute()->getAttributeCode()] = array( + 'type' => 'int', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + return $columns; + } + + /** + * Retrieve Select for update Attribute value in flat table + * + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return Mage::getResourceModel('eav/entity_attribute_option') + ->getFlatUpdateSelect($this->getAttribute(), $store, false); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Bundle/Model/Product/Price.php b/app/code/core/Mage/Bundle/Model/Product/Price.php index c801a87f59..177cf9847a 100644 --- a/app/code/core/Mage/Bundle/Model/Product/Price.php +++ b/app/code/core/Mage/Bundle/Model/Product/Price.php @@ -1,566 +1,581 @@ - - */ -class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Price -{ - /** - * Return product base price - * - * @return string - */ - public function getPrice($product) - { - if ($product->getPriceType()) { - return $product->getData('price'); - } else { - return 0; - } - } - - /** - * Get product final price - * - * @param double $qty - * @param Mage_Catalog_Model_Product $product - * @return double - */ - public function getFinalPrice($qty=null, $product) - { - if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) { - return $product->getCalculatedFinalPrice(); - } - - $finalPrice = $product->getPrice(); - if ($product->hasCustomOptions()) { - $customOption = $product->getCustomOption('bundle_option_ids'); - $optionIds = unserialize($customOption->getValue()); - $customOption = $product->getCustomOption('bundle_selection_ids'); - $selectionIds = unserialize($customOption->getValue()); - $selections = $product->getTypeInstance()->getSelectionsByIds($selectionIds); - foreach ($selections->getItems() as $selection) { - if ($selection->isSalable()) { - $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId()); - if ($selectionQty) { - $finalPrice = $finalPrice + $this->getSelectionPrice($product, $selection, $selectionQty->getValue()); - } - } - } - } else { - if ($options = $this->getOptions($product)) { - /* some strange thing - foreach ($options as $option) { - $selectionCount = count($option->getSelections()); - if ($selectionCount) { - foreach ($option->getSelections() as $selection) { - if ($selection->isSalable() && ($selection->getIsDefault() || ($option->getRequired() &&)) { - $finalPrice = $finalPrice + $this->getSelectionPrice($product, $selection); - } - } - } - } - */ - } - } - - $finalPrice = $this->_applyTierPrice($product, $qty, $finalPrice); - $finalPrice = $this->_applySpecialPrice($product, $finalPrice); - $product->setFinalPrice($finalPrice); - - Mage::dispatchEvent('catalog_product_get_final_price', array('product'=>$product)); - - $finalPrice = $product->getData('final_price'); - $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); - - return max(0, $product->getData('final_price')); - } - - public function getChildFinalPrice($product, $productQty, $childProduct, $childProductQty) - { - return $this->getSelectionFinalPrice($product, $childProduct, $productQty, $childProductQty, false); - } - - public function getPrices($product, $which = null) - { - $minimalPrice = $maximalPrice = $product->getPrice(); - if ($options = $this->getOptions($product)) { - foreach ($options as $option) { - if ($option->getSelections()) { - - $selectionMinimalPrices = array(); - $selectionMaximalPrices = array(); - - foreach ($option->getSelections() as $selection) { - if (!$selection->isSalable()) { - continue; - } - - $qty = $selection->getSelectionQty(); - if ($selection->getSelectionCanChangeQty() && $option->getType() != 'multi' && $option->getType() != 'checkbox') { - $qty = min(1, $qty); - } - - $selectionMinimalPrices[] = $this->getSelectionPrice($product, $selection, $qty); - $selectionMaximalPrices[] = $this->getSelectionPrice($product, $selection); - } - - if (count($selectionMinimalPrices)) { - if ($option->getRequired()) { - $minimalPrice += min($selectionMinimalPrices); - } - - if ($option->isMultiSelection()) { - $maximalPrice += array_sum($selectionMaximalPrices); - } else { - $maximalPrice += max($selectionMaximalPrices); - } - } - } - } - } - - - $minimalPrice = $this->_applySpecialPrice($product, $minimalPrice); - $maximalPrice = $this->_applySpecialPrice($product, $maximalPrice); - - if ($customOptions = $product->getOptions()) { - foreach ($customOptions as $customOption) { - if ($values = $customOption->getValues()) { - $prices = array(); - foreach ($values as $value) { - $prices[] = $value->getPrice(); - } - if (count($prices)) { - if ($customOption->getIsRequire()) { - $minimalPrice += min($prices); - } - $maximalPrice += max($prices); - } - } else { - if ($customOption->getIsRequire()) { - $minimalPrice += $customOption->getPrice(); - } - $maximalPrice += $customOption->getPrice(); - } - } - } - - if (is_null($which)) { - return array($minimalPrice, $maximalPrice); - } else if ($which = 'max') { - return $maximalPrice; - } else if ($which = 'min') { - return $minimalPrice; - } - return 0; - } - - /** - * Calculate Minimal price of bundle (counting all required options) - * - * @param Mage_Catalog_Model_Product $product - * @return decimal - */ - public function getMinimalPrice($product) - { - return $this->getPrices($product, 'min'); - } - - /** - * Calculate maximal price of bundle - * - * @param Mage_Catalog_Model_Product $product - * @return decimal - */ - public function getMaximalPrice($product) - { - return $this->getPrice($product, 'max'); - } - - /** - * Get Options with attached Selections collection - * - * @param Mage_Catalog_Model_Product $product - * @return Mage_Bundle_Model_Mysql4_Option_Collection - */ - public function getOptions($product) - { - $product->getTypeInstance()->setStoreFilter($product->getStoreId()); - - $optionCollection = $product->getTypeInstance()->getOptionsCollection(); - - $selectionCollection = $product->getTypeInstance()->getSelectionsCollection( - $product->getTypeInstance()->getOptionsIds() - ); - - return $optionCollection->appendSelections($selectionCollection, false, false); - } - - /** - * Calculate price of selection - * - * @param Mage_Catalog_Model_Product $bundleProduct - * @param Mage_Catalog_Model_Product $selectionProduct - * @param decimal $selectionQty - * @return decimal - */ - public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty = null, $multiplyQty = true) - { - if (is_null($selectionQty)) { - $selectionQty = $selectionProduct->getSelectionQty(); - } - - if ($bundleProduct->getPriceType() == Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Attributes_Extend::DYNAMIC){ - if ($multiplyQty) { - return $selectionProduct->getFinalPrice($selectionQty)*$selectionQty; - } else { - return $selectionProduct->getFinalPrice($selectionQty); - } - } else { - if ($selectionProduct->getSelectionPriceType()) { - return ($bundleProduct->getPrice()*$selectionProduct->getSelectionPriceValue()/100)*$selectionQty; - } else { - return $selectionProduct->getSelectionPriceValue()*$selectionQty; - } - } - } - - /** - * Calculate selection price for front view (with applied special of bundle) - * - * @param Mage_Catalog_Model_Product $bundleProduct - * @param Mage_Catalog_Model_Product $selectionProduct - * @param decimal - * @return decimal - */ - public function getSelectionPreFinalPrice($bundleProduct, $selectionProduct, $qty = null) - { - return $this->_applySpecialPrice($bundleProduct, $this->getSelectionPrice($bundleProduct, $selectionProduct, $qty)); - } - - - /** - * Calculate final price of selection - * - * @param Mage_Catalog_Model_Product $bundleProduct - * @param Mage_Catalog_Model_Product $selectionProduct - * @param decimal $bundleQty - * @param decimal $selectionQty - * @return decimal - */ - public function getSelectionFinalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty = null, $multiplyQty = true) - { - // apply bundle tier price - $finalPrice = $this->_applyTierPrice($bundleProduct, $bundleQty, $this->getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty, $multiplyQty)); - - // apply bundle special price - $finalPrice = $this->_applySpecialPrice($bundleProduct, $finalPrice); - - return $finalPrice; - } - - /** - * Apply tier price for bundle - * - * @param Mage_Catalog_Model_Product $product - * @param decimal $qty - * @param decimal $finalPrice - * @return decimal - */ - protected function _applyTierPrice($product, $qty, $finalPrice) - { - if (is_null($qty)) { - return $finalPrice; - } - - $tierPrice = $product->getTierPrice($qty); - if (is_numeric($tierPrice)) { - $tierPrice = $finalPrice - ($finalPrice*$tierPrice)/100; - $finalPrice = min($finalPrice, $tierPrice); - } - return $finalPrice; - } - - /** - * Get product tier price by qty - * - * @param decimal $qty - * @param Mage_Catalog_Model_Product $product - * @return decimal - */ - public function getTierPrice($qty=null, $product) - { - $allGroups = Mage_Customer_Model_Group::CUST_GROUP_ALL; - $prices = $product->getData('tier_price'); - - if (is_null($prices)) { - if ($attribute = $product->getResource()->getAttribute('tier_price')) { - $attribute->getBackend()->afterLoad($product); - $prices = $product->getData('tier_price'); - } - } - - if (is_null($prices) || !is_array($prices)) { - if (!is_null($qty)) { - return $product->getPrice(); - } - return array(array( - 'price' => $product->getPrice(), - 'website_price' => $product->getPrice(), - 'price_qty' => 1, - 'cust_group' => $allGroups, - )); - } - - $custGroup = $this->_getCustomerGroupId($product); - if ($qty) { - $prevQty = 1; - $prevPrice = 0; - $prevGroup = $allGroups; - - foreach ($prices as $price) { - if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) { - // tier not for current customer group nor is for all groups - continue; - } - if ($qty < $price['price_qty']) { - // tier is higher than product qty - continue; - } - if ($price['price_qty'] < $prevQty) { - // higher tier qty already found - continue; - } - if ($price['price_qty'] == $prevQty && $prevGroup != $allGroups && $price['cust_group'] == $allGroups) { - // found tier qty is same as current tier qty but current tier group is ALL_GROUPS - continue; - } - $prevPrice = $price['website_price']; - $prevQty = $price['price_qty']; - $prevGroup = $price['cust_group']; - } - return $prevPrice; - } else { - foreach ($prices as $i=>$price) { - if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) { - unset($prices[$i]); - } - } - } - - return ($prices) ? $prices : array(); - } - - /** - * Apply special price for bundle - * - * @param Mage_Catalog_Model_Product $product - * @param decimal $finalPrice - * @return decimal - */ - protected function _applySpecialPrice($product, $finalPrice) - { - $specialPrice = $product->getSpecialPrice(); - if (is_numeric($specialPrice)) { - $storeDate = Mage::app()->getLocale()->storeDate($product->getStore()); - $fromDate = Mage::app()->getLocale()->date($product->getSpecialFromDate(), null, null, false); - $toDate = Mage::app()->getLocale()->date($product->getSpecialToDate(), null, null, false); - - if ($product->getSpecialFromDate() && $storeDate->compare($fromDate)<0) { - } elseif ($product->getSpecialToDate() && $storeDate->compare($toDate)>0) { - } else { - // special price in percents - $specialPrice = ($finalPrice*$specialPrice)/100; - $finalPrice = min($finalPrice, $specialPrice); - } - } - return $finalPrice; - } - - public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $rulePrice = false, $wId = null, $gId = null, $productId = null) - { - $resource = Mage::getResourceSingleton('bundle/bundle'); - $selectionResource = Mage::getResourceSingleton('bundle/selection'); - $productPriceTypeId = Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'price_type'); - - if ($wId instanceof Mage_Core_Model_Store) { - $store = $wId->getId(); - $wId = $wId->getWebsiteId(); - } else { - $store = Mage::app()->getStore($wId)->getId(); - $wId = Mage::app()->getStore($wId)->getWebsiteId(); - //$store = Mage::app()->getWebsite($wId)->getDefaultGroup()->getDefaultStoreId(); - } - $storeDate = Mage::app()->getLocale()->storeDate($store); - - if (!$gId) { - $gId = Mage::getSingleton('customer/session')->getCustomerGroupId(); - } else if ($gId instanceof Mage_Customer_Model_Group) { - $gId = $gId->getId(); - } - - if (!isset(self::$attributeCache[$productId]['price_type'])) { - $attributes = $resource->getAttributeData($productId, $productPriceTypeId, $store); - self::$attributeCache[$productId]['price_type'] = $attributes; - } else { - $attributes = self::$attributeCache[$productId]['price_type']; - } - - $options = array(0); - $results = $resource->getSelectionsData($productId); - - if (!$attributes || !$attributes[0]['value']) { //dynamic - $dataRetreiver = Mage::getSingleton('catalogindex/data_simple'); - - $childrenQty = array(); - foreach ($results as $key => $result) { - if (!$result['product_id']) { - continue; - } - - if ($result['selection_can_change_qty'] && $result['type'] != 'multi' && $result['type'] != 'checkbox') { - $qty = 1; - } else { - $qty = $result['selection_qty']; - } - - $result['final_price'] = $selectionResource->getPriceFromIndex($result['product_id'], $qty, $store, $gId); - - $selectionPrice = $result['final_price']*$qty; - - if (isset($options[$result['option_id']])) { - $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice); - } else { - $options[$result['option_id']] = $selectionPrice; - } - } - $basePrice = array_sum($options); - } else { //fixed - foreach ($results as $result) { - if (!$result['product_id']) { - continue; - } - if ($result['selection_price_type']) { - $selectionPrice = $basePrice*$result['selection_price_value']/100; - } else { - $selectionPrice = $result['selection_price_value']; - } - - if ($result['selection_can_change_qty'] && $result['type'] != 'multi' && $result['type'] != 'checkbox') { - $qty = 1; - } else { - $qty = $result['selection_qty']; - } - - $selectionPrice = $selectionPrice*$qty; - - if (isset($options[$result['option_id']])) { - $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice); - } else { - $options[$result['option_id']] = $selectionPrice; - } - } - - $basePrice = $basePrice + array_sum($options); - } - - $finalPrice = $basePrice; - - $fromDate = Mage::app()->getLocale()->date($specialPriceFrom, null, null, false); - $toDate = Mage::app()->getLocale()->date($specialPriceTo, null, null, false); - - if ($specialPrice !== null && $specialPrice !== false) { - if ($specialPriceFrom && $storeDate->compare($fromDate)<0) { - } elseif ($specialPriceTo && $storeDate->compare($toDate)>0) { - } else { - // special price in percents - $specialPrice = ($finalPrice*$specialPrice)/100; - $finalPrice = min($finalPrice, $specialPrice); - } - } - - /* - * adding customer defined options price - */ - $customOptions = Mage::getResourceSingleton('catalog/product_option_collection')->reset(); - $customOptions->addFieldToFilter('is_require', '1') - ->addProductToFilter($productId) - ->addPriceToResult($store, 'price') - ->addValuesToResult(); - - foreach ($customOptions as $customOption) { - if ($values = $customOption->getValues()) { - $prices = array(); - foreach ($values as $value) { - $prices[] = $value->getPrice(); - } - if (count($prices)) { - $finalPrice += min($prices); - } - } else { - $finalPrice += $customOption->getPrice(); - } - } - - if ($rulePrice === false) { - $rulePrice = Mage::getResourceModel('catalogrule/rule')->getRulePrice($storeDate, $wId, $gId, $productId); - } - - if ($rulePrice !== null && $rulePrice !== false) { - $finalPrice = min($finalPrice, $rulePrice); - } - - $finalPrice = max($finalPrice, 0); - - return $finalPrice; - } - - - /* - public function getCustomOptionPrices($productId, $storeId, $which = null) { - - $optionsCollection = Mage::getResourceModel('catalog/product_option_collection') - ->addProductToFilter($productId) - ->; - - if (is_null($which)) { - return array($minimalPrice, $maximalPrice); - } else if ($which = 'max') { - return $maximalPrice; - } else if ($which = 'min') { - return $minimalPrice; - } - return 0; - } - */ - -} \ No newline at end of file + + */ +class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Price +{ + /** + * Return product base price + * + * @return string + */ + public function getPrice($product) + { + if ($product->getPriceType()) { + return $product->getData('price'); + } else { + return 0; + } + } + + /** + * Get product final price + * + * @param double $qty + * @param Mage_Catalog_Model_Product $product + * @return double + */ + public function getFinalPrice($qty=null, $product) + { + if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) { + return $product->getCalculatedFinalPrice(); + } + + $finalPrice = $product->getPrice(); + + /** + * Just product with fixed price calculation has price + */ + if ($finalPrice) { + $finalPrice = $this->_applyTierPrice($product, $qty, $finalPrice); + $finalPrice = $this->_applySpecialPrice($product, $finalPrice); + $product->setFinalPrice($finalPrice); + Mage::dispatchEvent('catalog_product_get_final_price', array('product'=>$product)); + $finalPrice = $product->getData('final_price'); + } + + if ($product->hasCustomOptions()) { + $customOption = $product->getCustomOption('bundle_option_ids'); +// $optionIds = unserialize($customOption->getValue()); + $customOption = $product->getCustomOption('bundle_selection_ids'); + $selectionIds = unserialize($customOption->getValue()); + $selections = $product->getTypeInstance(true)->getSelectionsByIds($selectionIds, $product); + foreach ($selections->getItems() as $selection) { + if ($selection->isSalable()) { + $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId()); + if ($selectionQty) { + $finalPrice = $finalPrice + $this->getSelectionPrice($product, $selection, $selectionQty->getValue()); + } + } + } + } else { +// if ($options = $this->getOptions($product)) { +// /* some strange thing +// foreach ($options as $option) { +// $selectionCount = count($option->getSelections()); +// if ($selectionCount) { +// foreach ($option->getSelections() as $selection) { +// if ($selection->isSalable() && ($selection->getIsDefault() || ($option->getRequired() &&)) { +// $finalPrice = $finalPrice + $this->getSelectionPrice($product, $selection); +// } +// } +// } +// } +// */ +// } + } + + $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); + $product->setFinalPrice($finalPrice); + + return max(0, $product->getData('final_price')); + } + + public function getChildFinalPrice($product, $productQty, $childProduct, $childProductQty) + { + return $this->getSelectionFinalPrice($product, $childProduct, $productQty, $childProductQty, false); + } + + public function getPrices($product, $which = null) + { + /** + * Check if product price is fixed + */ + if ($product->getPriceType()) { + $minimalPrice = $maximalPrice = $product->getFinalPrice(); + } else { + $minimalPrice = $maximalPrice = $product->getPrice(); + } + + if ($options = $this->getOptions($product)) { + foreach ($options as $option) { + if ($option->getSelections()) { + + $selectionMinimalPrices = array(); + $selectionMaximalPrices = array(); + + foreach ($option->getSelections() as $selection) { + if (!$selection->isSalable()) { + continue; + } + + $qty = $selection->getSelectionQty(); + if ($selection->getSelectionCanChangeQty() && $option->getType() != 'multi' && $option->getType() != 'checkbox') { + $qty = min(1, $qty); + } + + $selectionMinimalPrices[] = $this->getSelectionPrice($product, $selection, $qty); + $selectionMaximalPrices[] = $this->getSelectionPrice($product, $selection); + } + + if (count($selectionMinimalPrices)) { + if ($option->getRequired()) { + $minimalPrice += min($selectionMinimalPrices); + } + + if ($option->isMultiSelection()) { + $maximalPrice += array_sum($selectionMaximalPrices); + } else { + $maximalPrice += max($selectionMaximalPrices); + } + } + } + } + } + + + $minimalPrice = $this->_applySpecialPrice($product, $minimalPrice); + $maximalPrice = $this->_applySpecialPrice($product, $maximalPrice); + + if ($customOptions = $product->getOptions()) { + foreach ($customOptions as $customOption) { + if ($values = $customOption->getValues()) { + $prices = array(); + foreach ($values as $value) { + $prices[] = $value->getPrice(); + } + if (count($prices)) { + if ($customOption->getIsRequire()) { + $minimalPrice += min($prices); + } + $maximalPrice += max($prices); + } + } else { + if ($customOption->getIsRequire()) { + $minimalPrice += $customOption->getPrice(); + } + $maximalPrice += $customOption->getPrice(); + } + } + } + + if (is_null($which)) { + return array($minimalPrice, $maximalPrice); + } else if ($which = 'max') { + return $maximalPrice; + } else if ($which = 'min') { + return $minimalPrice; + } + return 0; + } + + /** + * Calculate Minimal price of bundle (counting all required options) + * + * @param Mage_Catalog_Model_Product $product + * @return decimal + */ + public function getMinimalPrice($product) + { + return $this->getPrices($product, 'min'); + } + + /** + * Calculate maximal price of bundle + * + * @param Mage_Catalog_Model_Product $product + * @return decimal + */ + public function getMaximalPrice($product) + { + return $this->getPrice($product, 'max'); + } + + /** + * Get Options with attached Selections collection + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Mysql4_Option_Collection + */ + public function getOptions($product) + { + $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product); + + $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product); + + $selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection( + $product->getTypeInstance(true)->getOptionsIds($product), + $product + ); + + return $optionCollection->appendSelections($selectionCollection, false, false); + } + + /** + * Calculate price of selection + * + * @param Mage_Catalog_Model_Product $bundleProduct + * @param Mage_Catalog_Model_Product $selectionProduct + * @param decimal $selectionQty + * @return decimal + */ + public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty = null, $multiplyQty = true) + { + if (is_null($selectionQty)) { + $selectionQty = $selectionProduct->getSelectionQty(); + } + + if ($bundleProduct->getPriceType() == Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Attributes_Extend::DYNAMIC){ + if ($multiplyQty) { + return $selectionProduct->getFinalPrice($selectionQty)*$selectionQty; + } else { + return $selectionProduct->getFinalPrice($selectionQty); + } + } else { + if ($selectionProduct->getSelectionPriceType()) { + return ($bundleProduct->getPrice()*$selectionProduct->getSelectionPriceValue()/100)*$selectionQty; + } else { + return $selectionProduct->getSelectionPriceValue()*$selectionQty; + } + } + } + + /** + * Calculate selection price for front view (with applied special of bundle) + * + * @param Mage_Catalog_Model_Product $bundleProduct + * @param Mage_Catalog_Model_Product $selectionProduct + * @param decimal + * @return decimal + */ + public function getSelectionPreFinalPrice($bundleProduct, $selectionProduct, $qty = null) + { + return $this->_applySpecialPrice($bundleProduct, $this->getSelectionPrice($bundleProduct, $selectionProduct, $qty)); + } + + + /** + * Calculate final price of selection + * + * @param Mage_Catalog_Model_Product $bundleProduct + * @param Mage_Catalog_Model_Product $selectionProduct + * @param decimal $bundleQty + * @param decimal $selectionQty + * @return decimal + */ + public function getSelectionFinalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty = null, $multiplyQty = true) + { + // apply bundle tier price + $finalPrice = $this->_applyTierPrice($bundleProduct, $bundleQty, $this->getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty, $multiplyQty)); + + // apply bundle special price + $finalPrice = $this->_applySpecialPrice($bundleProduct, $finalPrice); + + return $finalPrice; + } + + /** + * Apply tier price for bundle + * + * @param Mage_Catalog_Model_Product $product + * @param decimal $qty + * @param decimal $finalPrice + * @return decimal + */ + protected function _applyTierPrice($product, $qty, $finalPrice) + { + if (is_null($qty)) { + return $finalPrice; + } + + $tierPrice = $product->getTierPrice($qty); + if (is_numeric($tierPrice)) { + $tierPrice = $finalPrice - ($finalPrice*$tierPrice)/100; + $finalPrice = min($finalPrice, $tierPrice); + } + return $finalPrice; + } + + /** + * Get product tier price by qty + * + * @param decimal $qty + * @param Mage_Catalog_Model_Product $product + * @return decimal + */ + public function getTierPrice($qty=null, $product) + { + $allGroups = Mage_Customer_Model_Group::CUST_GROUP_ALL; + $prices = $product->getData('tier_price'); + + if (is_null($prices)) { + if ($attribute = $product->getResource()->getAttribute('tier_price')) { + $attribute->getBackend()->afterLoad($product); + $prices = $product->getData('tier_price'); + } + } + + if (is_null($prices) || !is_array($prices)) { + if (!is_null($qty)) { + return $product->getPrice(); + } + return array(array( + 'price' => $product->getPrice(), + 'website_price' => $product->getPrice(), + 'price_qty' => 1, + 'cust_group' => $allGroups, + )); + } + + $custGroup = $this->_getCustomerGroupId($product); + if ($qty) { + $prevQty = 1; + $prevPrice = 0; + $prevGroup = $allGroups; + + foreach ($prices as $price) { + if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) { + // tier not for current customer group nor is for all groups + continue; + } + if ($qty < $price['price_qty']) { + // tier is higher than product qty + continue; + } + if ($price['price_qty'] < $prevQty) { + // higher tier qty already found + continue; + } + if ($price['price_qty'] == $prevQty && $prevGroup != $allGroups && $price['cust_group'] == $allGroups) { + // found tier qty is same as current tier qty but current tier group is ALL_GROUPS + continue; + } + $prevPrice = $price['website_price']; + $prevQty = $price['price_qty']; + $prevGroup = $price['cust_group']; + } + return $prevPrice; + } else { + foreach ($prices as $i=>$price) { + if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) { + unset($prices[$i]); + } + } + } + + return ($prices) ? $prices : array(); + } + + /** + * Calculate product price based on special price data and price rules + * + * @param float $basePrice + * @param float $specialPrice + * @param string $specialPriceFrom + * @param string $specialPriceTo + * @param float|null|false $rulePrice + * @param mixed $wId + * @param mixed $gId + * @param null|int $productId + * @return float + */ + public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $rulePrice = false, $wId = null, $gId = null, $productId = null) + { + $resource = Mage::getResourceSingleton('bundle/bundle'); + $selectionResource = Mage::getResourceSingleton('bundle/selection'); + $productPriceTypeId = Mage::getSingleton('eav/entity_attribute')->getIdByCode('catalog_product', 'price_type'); + + if ($wId instanceof Mage_Core_Model_Store) { + $store = $wId->getId(); + $wId = $wId->getWebsiteId(); + } else { + $store = Mage::app()->getStore($wId)->getId(); + $wId = Mage::app()->getStore($wId)->getWebsiteId(); + //$store = Mage::app()->getWebsite($wId)->getDefaultGroup()->getDefaultStoreId(); + } + + if (!$gId) { + $gId = Mage::getSingleton('customer/session')->getCustomerGroupId(); + } else if ($gId instanceof Mage_Customer_Model_Group) { + $gId = $gId->getId(); + } + + if (!isset(self::$attributeCache[$productId]['price_type'])) { + $attributes = $resource->getAttributeData($productId, $productPriceTypeId, $store); + self::$attributeCache[$productId]['price_type'] = $attributes; + } else { + $attributes = self::$attributeCache[$productId]['price_type']; + } + + $options = array(0); + $results = $resource->getSelectionsData($productId); + + if (!$attributes || !$attributes[0]['value']) { //dynamic + foreach ($results as $result) { + if (!$result['product_id']) { + continue; + } + + if ($result['selection_can_change_qty'] && $result['type'] != 'multi' && $result['type'] != 'checkbox') { + $qty = 1; + } else { + $qty = $result['selection_qty']; + } + + $result['final_price'] = $selectionResource->getPriceFromIndex($result['product_id'], $qty, $store, $gId); + + $selectionPrice = $result['final_price']*$qty; + + if (isset($options[$result['option_id']])) { + $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice); + } else { + $options[$result['option_id']] = $selectionPrice; + } + } + $basePrice = array_sum($options); + } + else { //fixed + foreach ($results as $result) { + if (!$result['product_id']) { + continue; + } + if ($result['selection_price_type']) { + $selectionPrice = $basePrice*$result['selection_price_value']/100; + } else { + $selectionPrice = $result['selection_price_value']; + } + + if ($result['selection_can_change_qty'] && $result['type'] != 'multi' && $result['type'] != 'checkbox') { + $qty = 1; + } else { + $qty = $result['selection_qty']; + } + + $selectionPrice = $selectionPrice*$qty; + + if (isset($options[$result['option_id']])) { + $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice); + } else { + $options[$result['option_id']] = $selectionPrice; + } + } + + $basePrice = $basePrice + array_sum($options); + } + + $finalPrice = self::calculateSpecialPrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $store); + + /** + * adding customer defined options price + */ + $customOptions = Mage::getResourceSingleton('catalog/product_option_collection')->reset(); + $customOptions->addFieldToFilter('is_require', '1') + ->addProductToFilter($productId) + ->addPriceToResult($store, 'price') + ->addValuesToResult(); + + foreach ($customOptions as $customOption) { + if ($values = $customOption->getValues()) { + $prices = array(); + foreach ($values as $value) { + $prices[] = $value->getPrice(); + } + if (count($prices)) { + $finalPrice += min($prices); + } + } else { + $finalPrice += $customOption->getPrice(); + } + } + + if ($rulePrice === false) { + $rulePrice = Mage::getResourceModel('catalogrule/rule')->getRulePrice(Mage::app()->getLocale()->storeTimeStamp($store), $wId, $gId, $productId); + } + + if ($rulePrice !== null && $rulePrice !== false) { + $finalPrice = min($finalPrice, $rulePrice); + } + + $finalPrice = max($finalPrice, 0); + + return $finalPrice; + } + + /** + * Calculate and apply special price + * + * @param float $finalPrice + * @param float $specialPrice + * @param string $specialPriceFrom + * @param string $specialPriceTo + * @param mixed $store + * @return float + */ + public static function calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $store = null) + { + if (!is_null($specialPrice) && $specialPrice != false) { + if (!$store instanceof Mage_Core_Model_Store) { + $store = Mage::app()->getStore($store); + } + + $storeTimeStamp = Mage::app()->getLocale()->storeTimeStamp($store); + $fromTimeStamp = strtotime($specialPriceFrom); + $toTimeStamp = strtotime($specialPriceTo); + + if ($specialPriceFrom && $storeTimeStamp < $fromTimeStamp) { + } elseif ($specialPriceTo && $storeTimeStamp > $toTimeStamp) { + } else { + $specialPrice = ($finalPrice * $specialPrice) / 100; + $finalPrice = min($finalPrice, $specialPrice); + } + } + return $finalPrice; + } + + /* + public function getCustomOptionPrices($productId, $storeId, $which = null) { + + $optionsCollection = Mage::getResourceModel('catalog/product_option_collection') + ->addProductToFilter($productId) + ->; + + if (is_null($which)) { + return array($minimalPrice, $maximalPrice); + } else if ($which = 'max') { + return $maximalPrice; + } else if ($which = 'min') { + return $minimalPrice; + } + return 0; + } + */ +} diff --git a/app/code/core/Mage/Bundle/Model/Product/Type.php b/app/code/core/Mage/Bundle/Model/Product/Type.php index 6e4d101451..ee45cc8161 100644 --- a/app/code/core/Mage/Bundle/Model/Product/Type.php +++ b/app/code/core/Mage/Bundle/Model/Product/Type.php @@ -1,716 +1,804 @@ - - */ -class Mage_Bundle_Model_Product_Type extends Mage_Catalog_Model_Product_Type_Abstract -{ - protected $_isComposite = true; - - protected $_optionsCollection; - protected $_selectionsCollection; - protected $_storeFilter = null; - - protected $_usedSelections = null; - protected $_usedSelectionsIds = null; - protected $_usedOptions = null; - protected $_usedOptionsIds = null; - - protected $_optionsCount = null; - - /** - * Return relation info about used products - * - * @return Varien_Object Object with information data - */ - public function getRelationInfo() - { - $info = new Varien_Object(); - $info->setTable('bundle/selection') - ->setParentFieldName('parent_product_id') - ->setChildFieldName('product_id'); - return $info; - } - - /** - * Retrieve Required children ids - * Return grouped array, ex array( - * group => array(ids) - * ) - * - * @param int $parentId - * @param bool $required - * @return array - */ - public function getChildrenIds($parentId, $required = true) - { - return Mage::getResourceSingleton('bundle/selection') - ->getChildrenIds($parentId, $required); - } - - /** - * Retrieve parent ids array by requered child - * - * @param int $childId - * @return array - */ - public function getParentIdsByChild($childId) - { - return Mage::getResourceSingleton('bundle/selection') - ->getParentIdsByChild($childId); - } - - /** - * Return product sku based on sku_type attribute - * - * @return string - */ - public function getSku() - { - $sku = parent::getSku(); - - if ($this->getProduct()->getData('sku_type')) { - return $sku; - } else { - $skuParts = array($sku); - - if ($this->getProduct()->hasCustomOptions()) { - $customOption = $this->getProduct()->getCustomOption('bundle_selection_ids'); - $selectionIds = unserialize($customOption->getValue()); - $selections = $this->getSelectionsByIds($selectionIds); - foreach ($selections->getItems() as $selection) { - $skuParts[] = $selection->getSku(); - } - } - - return implode('-', $skuParts); - } - } - - /** - * Return product weight based on weight_type attribute - * - * @return decimal - */ - public function getWeight() - { - if ($this->getProduct()->getData('weight_type')) { - return $this->getProduct()->getData('weight'); - } else { - $weight = 0; - - if ($this->getProduct()->hasCustomOptions()) { - $customOption = $this->getProduct()->getCustomOption('bundle_selection_ids'); - $selectionIds = unserialize($customOption->getValue()); - $selections = $this->getSelectionsByIds($selectionIds); - foreach ($selections->getItems() as $selection) { - $weight += $selection->getWeight(); - } - } - return $weight; - } - } - - /** - * Check is virtual product - * - * @return bool - */ - public function isVirtual() - { - if ($this->getProduct()->hasCustomOptions()) { - $customOption = $this->getProduct()->getCustomOption('bundle_selection_ids'); - $selectionIds = unserialize($customOption->getValue()); - $selections = $this->getSelectionsByIds($selectionIds); - $virtualCount = 0; - foreach ($selections->getItems() as $selection) { - if ($selection->getTypeInstance()->IsVirtual()) { - $virtualCount++; - } - } - if ($virtualCount == count($selections)) { - return true; - } - } - return false; - } - - public function beforeSave() - { - parent::beforeSave(); - - $this->getProduct()->canAffectOptions(false); - - if ($this->getProduct()->getCanSaveBundleSelections()) { - $this->getProduct()->canAffectOptions(true); - if ($selections = $this->getProduct()->getBundleSelectionsData()) { - if (!empty($selections)) { - if ($options = $this->getProduct()->getBundleOptionsData()) { - foreach ($options as $option) { - if (empty($option['delete']) || 1 != (int)$option['delete']) { - $this->getProduct()->setTypeHasOptions(true); - if (1 == (int)$option['required']) { - $this->getProduct()->setTypeHasRequiredOptions(true); - break; - } - } - } - } - } - } - } - } - - public function save() - { - parent::save(); - - if ($options = $this->getProduct()->getBundleOptionsData()) { - - foreach ($options as $key => $option) { - if (isset($option['option_id']) && $option['option_id'] == '') { - unset($option['option_id']); - } - - $optionModel = Mage::getModel('bundle/option') - ->setData($option) - ->setParentId($this->getProduct()->getId()) - ->setStoreId($this->getProduct()->getStoreId()); - - $optionModel->isDeleted((bool)$option['delete']); - $optionModel->save(); - - $options[$key]['option_id'] = $optionModel->getOptionId(); - } - - $excludeSelectionIds = array(); - - if ($selections = $this->getProduct()->getBundleSelectionsData()) { - foreach ($selections as $index => $group) { - foreach ($group as $key => $selection) { - if (isset($selection['selection_id']) && $selection['selection_id'] == '') { - unset($selection['selection_id']); - } - - if (!isset($selection['is_default'])) { - $selection['is_default'] = 0; - } - - $selectionModel = Mage::getModel('bundle/selection') - ->setData($selection) - ->setOptionId($options[$index]['option_id']) - ->setParentProductId($this->getProduct()->getId()); - - $selectionModel->isDeleted((bool)$selection['delete']); - $selectionModel->save(); - - $selection['selection_id'] = $selectionModel->getSelectionId(); - - if ($selectionModel->getSelectionId()) { - $excludeSelectionIds[] = $selectionModel->getSelectionId(); - } - } - } - Mage::getResourceModel('bundle/bundle')->dropAllUnneededSelections($this->getProduct()->getId(), $excludeSelectionIds); - } - - if ($this->getProduct()->getData('price_type') != $this->getProduct()->getOrigData('price_type')) { - Mage::getResourceModel('bundle/bundle')->dropAllQuoteChildItems($this->getProduct()->getId()); - } - } - - return $this; - } - - /** - * Retrieve bundle options items - * - * @return array - */ - public function getOptions() - { - return $this->getOptionsCollection()->getItems(); - } - - /** - * Retrieve bundle options ids - * - * @return array - */ - public function getOptionsIds() - { - return $this->getOptionsCollection()->getAllIds(); - } - - /** - * Retrieve bundle option collection - * - * @return Mage_Bundle_Model_Mysql4_Option_Collection - */ - public function getOptionsCollection() - { - if (!$this->_optionsCollection) { - $this->_optionsCollection = Mage::getModel('bundle/option')->getResourceCollection() - ->setProductIdFilter($this->getProduct()->getId()) - ->setPositionOrder() - ->joinValues($this->getStoreFilter()); - } - return $this->_optionsCollection; - } - - /** - * Retrive bundle selections collection based on used options - * - * @param array $optionIds - * @return Mage_Bundle_Model_Mysql4_Selection_Collection - */ - public function getSelectionsCollection($optionIds) - { - if (!$this->_selectionsCollection) { - $this->_selectionsCollection = Mage::getResourceModel('bundle/selection_collection') - ->addAttributeToSelect('*') - ->setPositionOrder() - ->addStoreFilter($this->getStoreFilter()) - ->addFilterByRequiredOptions() - ->setOptionIdsFilter($optionIds); - } - return $this->_selectionsCollection; - } - - /** - * Method is needed for specific actions to change given quote options values - * according current product type logic - * Example: the cataloginventory validation of decimal qty can change qty to int, - * so need to change quote item qty option value too. - * - * @param array $options - * @param Varien_Object $option - * @param mixed $value - * - * @return object Mage_Bundle_Model_Product_Type - */ - public function updateQtyOption($options, Varien_Object $option, $value) - { - $optionProduct = $option->getProduct(); - - $optionCollection = $this->getOptionsCollection(); - - $selections = $this->getSelectionsCollection($optionCollection->getAllIds()); - - foreach ($selections as $selection) { - if ($selection->getProductId() == $optionProduct->getId()) { - foreach ($options as &$option) { - if ($option->getCode() == 'selection_qty_'.$selection->getSelectionId()) { - $option->setValue($value); - } - } - } - } - - return $this; - } - - /** - * Prepare Quote Item Quantity - * - * @param mixed $qty - * @return int - */ - public function prepareQuoteItemQty($qty) - { - return intval($qty); - } - - /** - * Checking if we can sale this bundle - * - * @return bool - */ - public function isSalable() - { - $salable = parent::isSalable(); - if (!is_null($salable)) { - return $salable; - } - - $optionCollection = $this->getOptionsCollection(); - - if (!count($optionCollection->getItems())) { - return false; - } - - $requiredOptionIds = array(); - - foreach ($optionCollection->getItems() as $option) { - if ($option->getRequired()) { - $requiredOptionIds[$option->getId()] = 0; - } - } - - $selectionCollection = $this->getSelectionsCollection($optionCollection->getAllIds()); - - if (!count($selectionCollection->getItems())) { - return false; - } - $salableSelectionCount = 0; - foreach ($selectionCollection as $selection) { - if ($selection->isSalable()) { - $requiredOptionIds[$selection->getOptionId()] = 1; - $salableSelectionCount++; - } - - } - - return (array_sum($requiredOptionIds) == count($requiredOptionIds) && $salableSelectionCount); - } - - /** - * Initialize product(s) for add to cart process - * - * @param Varien_Object $buyRequest - * @return unknown - */ - public function prepareForCart(Varien_Object $buyRequest) - { - $result = parent::prepareForCart($buyRequest); - - if (is_string($result)) { - return $result; - } - - $selections = array(); - - $product = $this->getProduct(); - - $_appendAllSelections = false; - if ($product->getSkipCheckRequiredOption()) { - $_appendAllSelections = true; - } - - if ($options = $buyRequest->getBundleOption()) { - $qtys = $buyRequest->getBundleOptionQty(); - foreach ($options as $_optionId => $_selections) { - if (empty($_selections)) { - unset($options[$_optionId]); - } - } - $optionIds = array_keys($options); - - if (empty($optionIds)) { - return Mage::helper('bundle')->__('Please select options for product.'); - } - - //$optionsCollection = $this->getOptionsByIds($optionIds); - $product->getTypeInstance()->setStoreFilter($product->getStoreId()); - $optionsCollection = $this->getOptionsCollection(); - if (!$this->getProduct()->getSkipCheckRequiredOption()) { - foreach ($optionsCollection->getItems() as $option) { - if ($option->getRequired() && !isset($options[$option->getId()])) { - return Mage::helper('bundle')->__('Required options not selected.'); - } - } - } - $selectionIds = array(); - - foreach ($options as $optionId => $selectionId) { - if (!is_array($selectionId)) { - if ($selectionId != '') { - $selectionIds[] = $selectionId; - } - } else { - foreach ($selectionId as $id) { - if ($id != '') { - $selectionIds[] = $id; - } - } - } - } - - $selections = $this->getSelectionsByIds($selectionIds); - - /** - * checking if selections that where added are still on sale - */ - foreach ($selections->getItems() as $key => $selection) { - if (!$selection->isSalable()) { - $_option = $optionsCollection->getItemById($selection->getOptionId()); - if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1){ - $moreSelections = true; - } else { - $moreSelections = false; - } - if ($_option->getRequired() && (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))) { - return Mage::helper('bundle')->__('Selected required options not available.'); - } - } - } - - $optionsCollection->appendSelections($selections, false, $_appendAllSelections); - - $selections = $selections->getItems(); - } else { - $product->getTypeInstance()->setStoreFilter($product->getStoreId()); - - $optionCollection = $product->getTypeInstance()->getOptionsCollection(); - - $optionIds = $product->getTypeInstance()->getOptionsIds(); - $selectionIds = array(); - - $selectionCollection = $product->getTypeInstance()->getSelectionsCollection( - $product->getTypeInstance()->getOptionsIds() - ); - - $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections); - - foreach ($options as $option) { - if ($option->getRequired() && count($option->getSelections()) == 1) { - $selections = array_merge($selections, $option->getSelections()); - } else { - $selections = array(); - break; - } - } - } - if (count($selections) > 0) { - $uniqueKey = array($product->getId()); - $selectionIds = array(); - - /* - * shaking selection array :) by option position - */ - usort($selections, array($this, "shakeSelections")); - - foreach ($selections as $selection) { - if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) { - $qty = $qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1; - } else { - $qty = $selection->getSelectionQty() ? $selection->getSelectionQty() : 1; - } - - $product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection); - $selection->addCustomOption('selection_id', $selection->getSelectionId()); - - if ($customOption = $product->getCustomOption('product_qty_' . $selection->getId())) { - $customOption->setValue($customOption->getValue() + $qty); - } else { - $product->addCustomOption('product_qty_' . $selection->getId(), $qty, $selection); - } - - /* - * creating extra attributes that will be converted - * to product options in order item - * for selection (not for all bundle) - */ - $price = $product->getPriceModel()->getSelectionPrice($product, $selection, $qty); - $attributes = array( - 'price' => Mage::app()->getStore()->convertPrice($price), - 'qty' => $qty, - 'option_label' => $selection->getOption()->getTitle(), - 'option_id' => $selection->getOption()->getId() - ); - - //if (!$product->getPriceType()) { - $_result = $selection->getTypeInstance()->prepareForCart($buyRequest); - if (is_string($_result) && !is_array($_result)) { - return $_result; - } - - if (!isset($_result[0])) { - return Mage::helper('checkout')->__('Can not add item to shopping cart'); - } - - $result[] = $_result[0]->setParentProductId($product->getId()) - ->addCustomOption('bundle_option_ids', serialize($optionIds)) - ->addCustomOption('bundle_selection_attributes', serialize($attributes)) - ->setCartQty($qty); - //} - - $selectionIds[] = $_result[0]->getSelectionId(); - $uniqueKey[] = $_result[0]->getSelectionId(); - $uniqueKey[] = $qty; - } - /** - * "unique" key for bundle selection and add it to selections and bundle for selections - */ - $uniqueKey = implode('_', $uniqueKey); - foreach ($result as $item) { - $item->addCustomOption('bundle_identity', $uniqueKey); - } - $product->addCustomOption('bundle_option_ids', serialize($optionIds)); - $product->addCustomOption('bundle_selection_ids', serialize($selectionIds)); - - return $result; - } - return Mage::helper('bundle')->__('Please specify product option(s)'); - } - - /** - * Retrieve bundle selections collection based on ids - * - * @param array $selectionIds - * @return Mage_Bundle_Model_Mysql4_Selection_Collection - */ - public function getSelectionsByIds($selectionIds) - { - sort($selectionIds); - if (!$this->_usedSelections || serialize($this->_usedSelectionsIds) != serialize($selectionIds)) { - $this->_usedSelections = Mage::getResourceModel('bundle/selection_collection') - ->addAttributeToSelect('*') - ->addStoreFilter($this->getStoreFilter()) - ->setPositionOrder() - ->addFilterByRequiredOptions() - ->setSelectionIdsFilter($selectionIds); - $this->_usedSelectionsIds = $selectionIds; - } - return $this->_usedSelections; - } - - /** - * Retrieve bundle options collection based on ids - * - * @param array $optionIds - * @return Mage_Bundle_Model_Mysql4_Option_Collection - */ - public function getOptionsByIds($optionIds) - { - sort($optionIds); - if (!$this->_usedOptions || serialize($this->_usedOptionsIds) != serialize($optionIds)) { - $this->_usedOptions = Mage::getModel('bundle/option')->getResourceCollection() - ->setProductIdFilter($this->getProduct()->getId()) - ->setPositionOrder() - ->joinValues(Mage::app()->getStore()->getId()) - ->setIdFilter($optionIds); - $this->_usedOptionsIds = $optionIds; - } - return $this->_usedOptions; - } - - /** - * Prepare additional options/information for order item which will be - * created from this product - * - * @return array - */ - - public function getOrderOptions() - { - $optionArr = parent::getOrderOptions(); - - $bundleOptions = array(); - - $product = $this->getProduct(); - - if ($product->hasCustomOptions()) { - $customOption = $product->getCustomOption('bundle_option_ids'); - $optionIds = unserialize($customOption->getValue()); - $options = $this->getOptionsByIds($optionIds); - $customOption = $product->getCustomOption('bundle_selection_ids'); - $selectionIds = unserialize($customOption->getValue()); - $selections = $this->getSelectionsByIds($selectionIds); - foreach ($selections->getItems() as $selection) { - if ($selection->isSalable()) { - $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId()); - if ($selectionQty) { - $price = $product->getPriceModel()->getSelectionPrice($product, $selection, $selectionQty->getValue()); - - $option = $options->getItemById($selection->getOptionId()); - if (!isset($bundleOptions[$option->getId()])) { - $bundleOptions[$option->getId()] = array( - 'option_id' => $option->getId(), - 'label' => $option->getTitle(), - 'value' => array() - ); - } - - $bundleOptions[$option->getId()]['value'][] = array( - 'title' => $selection->getName(), - 'qty' => $selectionQty->getValue(), - 'price' => Mage::app()->getStore()->convertPrice($price) - ); - - } - } - } - } - - $optionArr['bundle_options'] = $bundleOptions; - - /** - * Product Prices calculations save - */ - if ($product->getPriceType()) { - $optionArr['product_calculations'] = self::CALCULATE_PARENT; - } else { - $optionArr['product_calculations'] = self::CALCULATE_CHILD; - } - - $optionArr['shipment_type'] = $product->getShipmentType(); - - return $optionArr; - } - - public function shakeSelections($a, $b) - { - $aPosition = ($a->getOption()->getPosition()+1)*($a->getPosition()+1); - $bPosition = ($b->getOption()->getPosition()+1)*($b->getPosition()+1); - if ($aPosition == $bPosition) { - if ($a->getSelectionId() == $b->getSelectionId()) { - return 0; - } - return ($a->getSelectionId() < $b->getSelectionId()) ? -1 : 1; - } - return ($aPosition < $bPosition) ? -1 : 1; - } - - /** - * Return true if product has options - * - * @return bool - */ - public function hasOptions() - { - if (count($this->getSelectionsCollection($this->getOptionsCollection()->getAllIds())->getItems()) || $this->getProduct()->getOptions()) { - return true; - } - return false; - } - - /** - * Allow for updates of chidren qty's - * - * @return boolean true - */ - public function getForceChildItemQtyChanges() - { - return true; - } - -} + + */ +class Mage_Bundle_Model_Product_Type extends Mage_Catalog_Model_Product_Type_Abstract +{ + /** + * Product is composite + * + * @var bool + */ + protected $_isComposite = true; + + /** + * Cache key for Options Collection + * + * @var string + */ + protected $_keyOptionsCollection = '_cache_instance_options_collection'; + + /** + * Cache key for Selections Collection + * + * @var string + */ + protected $_keySelectionsCollection = '_cache_instance_selections_collection'; + + /** + * Cache key for used Selections + * + * @var string + */ + protected $_keyUsedSelections = '_cache_instance_used_selections'; + + /** + * Cache key for used selections ids + * + * @var string + */ + protected $_keyUsedSelectionsIds = '_cache_instance_used_selections_ids'; + + /** + * Cache key for used options + * + * @var string + */ + protected $_keyUsedOptions = '_cache_instance_used_options'; + + /** + * Cache key for used options ids + * + * @var string + */ + protected $_keyUsedOptionsIds = '_cache_instance_used_options_ids'; + + /** + * Return relation info about used products + * + * @return Varien_Object Object with information data + */ + public function getRelationInfo() + { + $info = new Varien_Object(); + $info->setTable('bundle/selection') + ->setParentFieldName('parent_product_id') + ->setChildFieldName('product_id'); + return $info; + } + + /** + * Retrieve Required children ids + * Return grouped array, ex array( + * group => array(ids) + * ) + * + * @param int $parentId + * @param bool $required + * @return array + */ + public function getChildrenIds($parentId, $required = true) + { + return Mage::getResourceSingleton('bundle/selection') + ->getChildrenIds($parentId, $required); + } + + /** + * Retrieve parent ids array by requered child + * + * @param int $childId + * @return array + */ + public function getParentIdsByChild($childId) + { + return Mage::getResourceSingleton('bundle/selection') + ->getParentIdsByChild($childId); + } + + /** + * Return product sku based on sku_type attribute + * + * @param Mage_Catalog_Model_Product $product + * @return string + */ + public function getSku($product = null) + { + $sku = parent::getSku($product); + + if ($this->getProduct($product)->getData('sku_type')) { + return $sku; + } else { + $skuParts = array($sku); + + if ($this->getProduct($product)->hasCustomOptions()) { + $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids'); + $selectionIds = unserialize($customOption->getValue()); + $selections = $this->getSelectionsByIds($selectionIds, $product); + foreach ($selections->getItems() as $selection) { + $skuParts[] = $selection->getSku(); + } + } + + return implode('-', $skuParts); + } + } + + /** + * Return product weight based on weight_type attribute + * + * @param Mage_Catalog_Model_Product $product + * @return decimal + */ + public function getWeight($product = null) + { + if ($this->getProduct($product)->getData('weight_type')) { + return $this->getProduct($product)->getData('weight'); + } else { + $weight = 0; + + if ($this->getProduct($product)->hasCustomOptions()) { + $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids'); + $selectionIds = unserialize($customOption->getValue()); + $selections = $this->getSelectionsByIds($selectionIds, $product); + foreach ($selections->getItems() as $selection) { + $weight += $selection->getWeight(); + } + } + return $weight; + } + } + + /** + * Check is virtual product + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isVirtual($product = null) + { + if ($this->getProduct($product)->hasCustomOptions()) { + $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids'); + $selectionIds = unserialize($customOption->getValue()); + $selections = $this->getSelectionsByIds($selectionIds, $product); + $virtualCount = 0; + foreach ($selections->getItems() as $selection) { + if ($selection->isVirtual()) { + $virtualCount++; + } + } + if ($virtualCount == count($selections)) { + return true; + } + } + return false; + } + + /** + * Before save type related data + * + * @param Mage_Catalog_Model_Product $product + */ + public function beforeSave($product = null) + { + parent::beforeSave($product); + + $this->getProduct($product)->canAffectOptions(false); + + if ($this->getProduct($product)->getCanSaveBundleSelections()) { + $this->getProduct($product)->canAffectOptions(true); + if ($selections = $this->getProduct($product)->getBundleSelectionsData()) { + if (!empty($selections)) { + if ($options = $this->getProduct($product)->getBundleOptionsData()) { + foreach ($options as $option) { + if (empty($option['delete']) || 1 != (int)$option['delete']) { + $this->getProduct($product)->setTypeHasOptions(true); + if (1 == (int)$option['required']) { + $this->getProduct($product)->setTypeHasRequiredOptions(true); + break; + } + } + } + } + } + } + } + } + + /** + * Save type related data + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Product_Type + */ + public function save($product = null) + { + parent::save($product); + + if ($options = $this->getProduct($product)->getBundleOptionsData()) { + + foreach ($options as $key => $option) { + if (isset($option['option_id']) && $option['option_id'] == '') { + unset($option['option_id']); + } + + $optionModel = Mage::getModel('bundle/option') + ->setData($option) + ->setParentId($this->getProduct($product)->getId()) + ->setStoreId($this->getProduct($product)->getStoreId()); + + $optionModel->isDeleted((bool)$option['delete']); + $optionModel->save(); + + $options[$key]['option_id'] = $optionModel->getOptionId(); + } + + $excludeSelectionIds = array(); + + if ($selections = $this->getProduct($product)->getBundleSelectionsData()) { + foreach ($selections as $index => $group) { + foreach ($group as $key => $selection) { + if (isset($selection['selection_id']) && $selection['selection_id'] == '') { + unset($selection['selection_id']); + } + + if (!isset($selection['is_default'])) { + $selection['is_default'] = 0; + } + + $selectionModel = Mage::getModel('bundle/selection') + ->setData($selection) + ->setOptionId($options[$index]['option_id']) + ->setParentProductId($this->getProduct($product)->getId()); + + $selectionModel->isDeleted((bool)$selection['delete']); + $selectionModel->save(); + + $selection['selection_id'] = $selectionModel->getSelectionId(); + + if ($selectionModel->getSelectionId()) { + $excludeSelectionIds[] = $selectionModel->getSelectionId(); + } + } + } + Mage::getResourceModel('bundle/bundle')->dropAllUnneededSelections($this->getProduct($product)->getId(), $excludeSelectionIds); + } + + if ($this->getProduct($product)->getData('price_type') != $this->getProduct($product)->getOrigData('price_type')) { + Mage::getResourceModel('bundle/bundle')->dropAllQuoteChildItems($this->getProduct($product)->getId()); + } + } + + return $this; + } + + /** + * Retrieve bundle options items + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getOptions($product = null) + { + return $this->getOptionsCollection($product)->getItems(); + } + + /** + * Retrieve bundle options ids + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getOptionsIds($product = null) + { + return $this->getOptionsCollection($product)->getAllIds(); + } + + /** + * Retrieve bundle option collection + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Mysql4_Option_Collection + */ + public function getOptionsCollection($product = null) + { + if (!$this->getProduct($product)->hasData($this->_keyOptionsCollection)) { + $optionsCollection = Mage::getModel('bundle/option')->getResourceCollection() + ->setProductIdFilter($this->getProduct($product)->getId()) + ->setPositionOrder() + ->joinValues($this->getStoreFilter($product)); + $this->getProduct($product)->setData($this->_keyOptionsCollection, $optionsCollection); + } + return $this->getProduct($product)->getData($this->_keyOptionsCollection); + } + + /** + * Retrive bundle selections collection based on used options + * + * @param array $optionIds + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Mysql4_Selection_Collection + */ + public function getSelectionsCollection($optionIds, $product = null) + { + if (!$this->getProduct($product)->hasData($this->_keySelectionsCollection)) { + $selectionsCollection = Mage::getResourceModel('bundle/selection_collection') + ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) + ->setFlag('require_stock_items', true) + ->setPositionOrder() + ->addStoreFilter($this->getStoreFilter($product)) + ->addFilterByRequiredOptions() + ->setOptionIdsFilter($optionIds); + $this->getProduct($product)->setData($this->_keySelectionsCollection, $selectionsCollection); + } + return $this->getProduct($product)->getData($this->_keySelectionsCollection); + } + + /** + * Method is needed for specific actions to change given quote options values + * according current product type logic + * Example: the cataloginventory validation of decimal qty can change qty to int, + * so need to change quote item qty option value too. + * + * @param array $options + * @param Varien_Object $option + * @param mixed $value + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Product_Type + */ + public function updateQtyOption($options, Varien_Object $option, $value, $product = null) + { + $optionProduct = $option->getProduct($product); + + $optionCollection = $this->getOptionsCollection($product); + + $selections = $this->getSelectionsCollection($optionCollection->getAllIds(), $product); + + foreach ($selections as $selection) { + if ($selection->getProductId() == $optionProduct->getId()) { + foreach ($options as &$option) { + if ($option->getCode() == 'selection_qty_'.$selection->getSelectionId()) { + $option->setValue($value); + } + } + } + } + + return $this; + } + + /** + * Prepare Quote Item Quantity + * + * @param mixed $qty + * @param Mage_Catalog_Model_Product $product + * @return int + */ + public function prepareQuoteItemQty($qty, $product = null) + { + return intval($qty); + } + + /** + * Checking if we can sale this bundle + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isSalable($product = null) + { + $salable = parent::isSalable($product); + if (!is_null($salable)) { + return $salable; + } + + $optionCollection = $this->getOptionsCollection($product); + + if (!count($optionCollection->getItems())) { + return false; + } + + $requiredOptionIds = array(); + + foreach ($optionCollection->getItems() as $option) { + if ($option->getRequired()) { + $requiredOptionIds[$option->getId()] = 0; + } + } + + $selectionCollection = $this->getSelectionsCollection($optionCollection->getAllIds(), $product); + + if (!count($selectionCollection->getItems())) { + return false; + } + $salableSelectionCount = 0; + foreach ($selectionCollection as $selection) { + if ($selection->isSalable()) { + $requiredOptionIds[$selection->getOptionId()] = 1; + $salableSelectionCount++; + } + + } + + return (array_sum($requiredOptionIds) == count($requiredOptionIds) && $salableSelectionCount); + } + + /** + * Initialize product(s) for add to cart process + * + * @param Varien_Object $buyRequest + * @param Mage_Catalog_Model_Product $product + * @return unknown + */ + public function prepareForCart(Varien_Object $buyRequest, $product = null) + { + $result = parent::prepareForCart($buyRequest, $product); + + if (is_string($result)) { + return $result; + } + + $selections = array(); + + $product = $this->getProduct($product); + + $_appendAllSelections = false; + if ($product->getSkipCheckRequiredOption()) { + $_appendAllSelections = true; + } + + if ($options = $buyRequest->getBundleOption()) { + $qtys = $buyRequest->getBundleOptionQty(); + foreach ($options as $_optionId => $_selections) { + if (empty($_selections)) { + unset($options[$_optionId]); + } + } + $optionIds = array_keys($options); + + if (empty($optionIds)) { + return Mage::helper('bundle')->__('Please select options for product.'); + } + + //$optionsCollection = $this->getOptionsByIds($optionIds, $product); + $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product); + $optionsCollection = $this->getOptionsCollection($product); + if (!$this->getProduct($product)->getSkipCheckRequiredOption()) { + foreach ($optionsCollection->getItems() as $option) { + if ($option->getRequired() && !isset($options[$option->getId()])) { + return Mage::helper('bundle')->__('Required options not selected.'); + } + } + } + $selectionIds = array(); + + foreach ($options as $optionId => $selectionId) { + if (!is_array($selectionId)) { + if ($selectionId != '') { + $selectionIds[] = $selectionId; + } + } else { + foreach ($selectionId as $id) { + if ($id != '') { + $selectionIds[] = $id; + } + } + } + } + + $selections = $this->getSelectionsByIds($selectionIds, $product); + + /** + * checking if selections that where added are still on sale + */ + foreach ($selections->getItems() as $key => $selection) { + if (!$selection->isSalable()) { + $_option = $optionsCollection->getItemById($selection->getOptionId()); + if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1){ + $moreSelections = true; + } else { + $moreSelections = false; + } + if ($_option->getRequired() && (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))) { + return Mage::helper('bundle')->__('Selected required options not available.'); + } + } + } + + $optionsCollection->appendSelections($selections, false, $_appendAllSelections); + + $selections = $selections->getItems(); + } else { + $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product); + + $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product); + + $optionIds = $product->getTypeInstance(true)->getOptionsIds($product); + $selectionIds = array(); + + $selectionCollection = $product->getTypeInstance(true) + ->getSelectionsCollection( + $product->getTypeInstance(true)->getOptionsIds($product), + $product + ); + + $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections); + + foreach ($options as $option) { + if ($option->getRequired() && count($option->getSelections()) == 1) { + $selections = array_merge($selections, $option->getSelections()); + } else { + $selections = array(); + break; + } + } + } + if (count($selections) > 0) { + $uniqueKey = array($product->getId()); + $selectionIds = array(); + + /* + * shaking selection array :) by option position + */ + usort($selections, array($this, "shakeSelections")); + + foreach ($selections as $selection) { + if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) { + $qty = $qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1; + } else { + $qty = $selection->getSelectionQty() ? $selection->getSelectionQty() : 1; + } + + $product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection); + $selection->addCustomOption('selection_id', $selection->getSelectionId()); + + if ($customOption = $product->getCustomOption('product_qty_' . $selection->getId())) { + $customOption->setValue($customOption->getValue() + $qty); + } else { + $product->addCustomOption('product_qty_' . $selection->getId(), $qty, $selection); + } + + /* + * creating extra attributes that will be converted + * to product options in order item + * for selection (not for all bundle) + */ + $price = $product->getPriceModel()->getSelectionPrice($product, $selection, $qty); + $attributes = array( + 'price' => Mage::app()->getStore()->convertPrice($price), + 'qty' => $qty, + 'option_label' => $selection->getOption()->getTitle(), + 'option_id' => $selection->getOption()->getId() + ); + + //if (!$product->getPriceType()) { + $_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection); + if (is_string($_result) && !is_array($_result)) { + return $_result; + } + + if (!isset($_result[0])) { + return Mage::helper('checkout')->__('Can not add item to shopping cart'); + } + + $result[] = $_result[0]->setParentProductId($product->getId()) + ->addCustomOption('bundle_option_ids', serialize($optionIds)) + ->addCustomOption('bundle_selection_attributes', serialize($attributes)) + ->setCartQty($qty); + //} + + $selectionIds[] = $_result[0]->getSelectionId(); + $uniqueKey[] = $_result[0]->getSelectionId(); + $uniqueKey[] = $qty; + } + /** + * "unique" key for bundle selection and add it to selections and bundle for selections + */ + $uniqueKey = implode('_', $uniqueKey); + foreach ($result as $item) { + $item->addCustomOption('bundle_identity', $uniqueKey); + } + $product->addCustomOption('bundle_option_ids', serialize($optionIds)); + $product->addCustomOption('bundle_selection_ids', serialize($selectionIds)); + + return $result; + } + return $this->getSpecifyOptionMessage(); + } + + /** + * Retrieve message for specify option(s) + * + * @return string + */ + public function getSpecifyOptionMessage() + { + return Mage::helper('bundle')->__('Please specify product option(s)'); + } + + /** + * Retrieve bundle selections collection based on ids + * + * @param array $selectionIds + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Mysql4_Selection_Collection + */ + public function getSelectionsByIds($selectionIds, $product = null) + { + sort($selectionIds); + + $usedSelections = $this->getProduct($product)->getData($this->_keyUsedSelections); + $usedSelectionsIds = $this->getProduct($product)->getData($this->_keyUsedSelectionsIds); + + if (!$usedSelections || serialize($usedSelectionsIds) != serialize($selectionIds)) { + $usedSelections = Mage::getResourceModel('bundle/selection_collection') + ->addAttributeToSelect('*') + ->setFlag('require_stock_items', true) + ->addStoreFilter($this->getStoreFilter($product)) + ->setPositionOrder() + ->addFilterByRequiredOptions() + ->setSelectionIdsFilter($selectionIds); + $this->getProduct($product)->setData($this->_keyUsedSelections, $usedSelections); + $this->getProduct($product)->setData($this->_keyUsedSelectionsIds, $selectionIds); + } + return $usedSelections; + } + + /** + * Retrieve bundle options collection based on ids + * + * @param array $optionIds + * @param Mage_Catalog_Model_Product $product + * @return Mage_Bundle_Model_Mysql4_Option_Collection + */ + public function getOptionsByIds($optionIds, $product = null) + { + sort($optionIds); + + $usedOptions = $this->getProduct($product)->getData($this->_keyUsedOptions); + $usedOptionsIds = $this->getProduct($product)->getData($this->_keyUsedOptionsIds); + + if (!$usedOptions || serialize($usedOptionsIds) != serialize($optionIds)) { + $usedOptions = Mage::getModel('bundle/option')->getResourceCollection() + ->setProductIdFilter($this->getProduct($product)->getId()) + ->setPositionOrder() + ->joinValues(Mage::app()->getStore()->getId()) + ->setIdFilter($optionIds); + $this->getProduct($product)->setData($this->_keyUsedOptions, $usedOptionsIds); + $this->getProduct($product)->setData($this->_keyUsedOptionsIds, $optionIds); + } + return $usedOptions; + } + + /** + * Prepare additional options/information for order item which will be + * created from this product + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getOrderOptions($product = null) + { + $optionArr = parent::getOrderOptions($product); + + $bundleOptions = array(); + + $product = $this->getProduct($product); + + if ($product->hasCustomOptions()) { + $customOption = $product->getCustomOption('bundle_option_ids'); + $optionIds = unserialize($customOption->getValue()); + $options = $this->getOptionsByIds($optionIds, $product); + $customOption = $product->getCustomOption('bundle_selection_ids'); + $selectionIds = unserialize($customOption->getValue()); + $selections = $this->getSelectionsByIds($selectionIds, $product); + foreach ($selections->getItems() as $selection) { + if ($selection->isSalable()) { + $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId()); + if ($selectionQty) { + $price = $product->getPriceModel()->getSelectionPrice($product, $selection, $selectionQty->getValue()); + + $option = $options->getItemById($selection->getOptionId()); + if (!isset($bundleOptions[$option->getId()])) { + $bundleOptions[$option->getId()] = array( + 'option_id' => $option->getId(), + 'label' => $option->getTitle(), + 'value' => array() + ); + } + + $bundleOptions[$option->getId()]['value'][] = array( + 'title' => $selection->getName(), + 'qty' => $selectionQty->getValue(), + 'price' => Mage::app()->getStore()->convertPrice($price) + ); + + } + } + } + } + + $optionArr['bundle_options'] = $bundleOptions; + + /** + * Product Prices calculations save + */ + if ($product->getPriceType()) { + $optionArr['product_calculations'] = self::CALCULATE_PARENT; + } else { + $optionArr['product_calculations'] = self::CALCULATE_CHILD; + } + + $optionArr['shipment_type'] = $product->getShipmentType(); + + return $optionArr; + } + + public function shakeSelections($a, $b) + { + $aPosition = ($a->getOption()->getPosition()+1)*($a->getPosition()+1); + $bPosition = ($b->getOption()->getPosition()+1)*($b->getPosition()+1); + if ($aPosition == $bPosition) { + if ($a->getSelectionId() == $b->getSelectionId()) { + return 0; + } + return ($a->getSelectionId() < $b->getSelectionId()) ? -1 : 1; + } + return ($aPosition < $bPosition) ? -1 : 1; + } + + /** + * Return true if product has options + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function hasOptions($product = null) + { + $this->setStoreFilter($product->getStoreId(), $product); + if (count($this->getSelectionsCollection($this->getOptionsCollection($product)->getAllIds(), $product)->getItems()) || $this->getProduct($product)->getOptions()) { + return true; + } + return false; + } + + /** + * Allow for updates of chidren qty's + * + * @param Mage_Catalog_Model_Product $product + * @return boolean true + */ + public function getForceChildItemQtyChanges($product = null) + { + return true; + } + +} diff --git a/app/code/core/Mage/Bundle/etc/config.xml b/app/code/core/Mage/Bundle/etc/config.xml index 54fc996982..c0870a3df1 100644 --- a/app/code/core/Mage/Bundle/etc/config.xml +++ b/app/code/core/Mage/Bundle/etc/config.xml @@ -28,7 +28,7 @@ - 0.1.4 + 0.1.6 diff --git a/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.4-0.1.5.php b/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.4-0.1.5.php new file mode 100644 index 0000000000..423812b589 --- /dev/null +++ b/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.4-0.1.5.php @@ -0,0 +1,32 @@ +startSetup(); +$installer->updateAttribute('catalog_product', 'price_type', 'used_in_product_listing', 1); +$installer->endSetup(); diff --git a/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.5-0.1.6.php b/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.5-0.1.6.php new file mode 100644 index 0000000000..b9ad19e8d4 --- /dev/null +++ b/app/code/core/Mage/Bundle/sql/bundle_setup/mysql4-upgrade-0.1.5-0.1.6.php @@ -0,0 +1,34 @@ +startSetup(); +$installer->updateAttribute('catalog_product', 'price_view', 'used_in_product_listing', 1); +$installer->updateAttribute('catalog_product', 'shipment_type', 'used_in_product_listing', 1); +$installer->updateAttribute('catalog_product', 'weight_type', 'used_in_product_listing', 1); +$installer->endSetup(); diff --git a/app/code/core/Mage/Catalog/Block/Breadcrumbs.php b/app/code/core/Mage/Catalog/Block/Breadcrumbs.php index 9bda5fb75a..9e7bfbc1d2 100644 --- a/app/code/core/Mage/Catalog/Block/Breadcrumbs.php +++ b/app/code/core/Mage/Catalog/Block/Breadcrumbs.php @@ -61,7 +61,7 @@ protected function _prepareLayout() )); $title = array(); - $path = Mage::helper('catalog')->getBreadcrumbPath($this->getCategory()); + $path = Mage::helper('catalog')->getBreadcrumbPath(); foreach ($path as $name => $breadcrumb) { $breadcrumbsBlock->addCrumb($name, $breadcrumb); diff --git a/app/code/core/Mage/Catalog/Block/Layer/Filter/Abstract.php b/app/code/core/Mage/Catalog/Block/Layer/Filter/Abstract.php index 2883301286..3decccc25c 100644 --- a/app/code/core/Mage/Catalog/Block/Layer/Filter/Abstract.php +++ b/app/code/core/Mage/Catalog/Block/Layer/Filter/Abstract.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,19 +29,39 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ abstract class Mage_Catalog_Block_Layer_Filter_Abstract extends Mage_Core_Block_Template { + /** + * Catalog Layer Filter Attribute model + * + * @var Mage_Catalog_Model_Layer_Filter_Attribute + */ protected $_filter; + + /** + * Filter Model Name + * + * @var string + */ protected $_filterModelName; + /** + * Initialize filter template + * + */ public function __construct() { parent::__construct(); $this->setTemplate('catalog/layer/filter.phtml'); } + /** + * Initialize filter model object + * + * @return Mage_Catalog_Block_Layer_Filter_Abstract + */ public function init() { $this->_initFilter(); @@ -66,6 +86,11 @@ protected function _initFilter() return $this; } + /** + * Prepare filter process + * + * @return Mage_Catalog_Block_Layer_Filter_Abstract + */ protected function _prepareFilter() { return $this; diff --git a/app/code/core/Mage/Catalog/Block/Layer/Filter/Price.php b/app/code/core/Mage/Catalog/Block/Layer/Filter/Price.php index 3b80c43b89..cdc8d6e29a 100644 --- a/app/code/core/Mage/Catalog/Block/Layer/Filter/Price.php +++ b/app/code/core/Mage/Catalog/Block/Layer/Filter/Price.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,16 +29,25 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Block_Layer_Filter_Price extends Mage_Catalog_Block_Layer_Filter_Abstract { + /** + * Initialize Price filter module + * + */ public function __construct() { parent::__construct(); $this->_filterModelName = 'catalog/layer_filter_price'; } + /** + * Prepare filter process + * + * @return Mage_Catalog_Block_Layer_Filter_Price + */ protected function _prepareFilter() { $this->_filter->setAttributeModel($this->getAttributeModel()); diff --git a/app/code/core/Mage/Catalog/Block/Layer/State.php b/app/code/core/Mage/Catalog/Block/Layer/State.php index f72df38e3b..71f684bf69 100644 --- a/app/code/core/Mage/Catalog/Block/Layer/State.php +++ b/app/code/core/Mage/Catalog/Block/Layer/State.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,16 +29,25 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Block_Layer_State extends Mage_Core_Block_Template { + /** + * Initialize Layer State template + * + */ public function __construct() { parent::__construct(); $this->setTemplate('catalog/layer/state.phtml'); } + /** + * Retrieve active filters + * + * @return array + */ public function getActiveFilters() { $filters = $this->getLayer()->getState()->getFilters(); @@ -48,6 +57,11 @@ public function getActiveFilters() return $filters; } + /** + * Retrieve Clear Filters URL + * + * @return string + */ public function getClearUrl() { $filterState = array(); @@ -61,6 +75,11 @@ public function getClearUrl() return Mage::getUrl('*/*/*', $params); } + /** + * Retrieve Layer object + * + * @return Mage_Catalog_Model_Layer + */ public function getLayer() { if (!$this->hasData('layer')) { diff --git a/app/code/core/Mage/Catalog/Block/Layer/View.php b/app/code/core/Mage/Catalog/Block/Layer/View.php index ebf388893e..7733ae4ef5 100644 --- a/app/code/core/Mage/Catalog/Block/Layer/View.php +++ b/app/code/core/Mage/Catalog/Block/Layer/View.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -38,10 +38,11 @@ class Mage_Catalog_Block_Layer_View extends Mage_Core_Block_Template * * @return Mage_Catalog_Block_Layer_View */ - public function _prepareLayout() + protected function _prepareLayout() { $stateBlock = $this->getLayout()->createBlock('catalog/layer_state') ->setLayer($this->getLayer()); + $categryBlock = $this->getLayout()->createBlock('catalog/layer_filter_category') ->setLayer($this->getLayer()) ->init(); @@ -62,6 +63,7 @@ public function _prepareLayout() ->setAttributeModel($attribute) ->init()); } + $this->getLayer()->apply(); return parent::_prepareLayout(); } @@ -156,6 +158,11 @@ public function canShowBlock() return $this->canShowOptions() || count($this->getLayer()->getState()->getFilters()); } + /** + * Retrieve Price Filter block + * + * @return Mage_Catalog_Block_Layer_Filter_Price + */ protected function _getPriceFilter() { return $this->getChild('_price_filter'); diff --git a/app/code/core/Mage/Catalog/Block/Navigation.php b/app/code/core/Mage/Catalog/Block/Navigation.php index 82a20783d2..cce9a73e9e 100644 --- a/app/code/core/Mage/Catalog/Block/Navigation.php +++ b/app/code/core/Mage/Catalog/Block/Navigation.php @@ -47,12 +47,20 @@ protected function _construct() public function getCacheKey() { $key = Mage::app()->getStore()->getId().'_CATALOG_NAVIGATION' . md5($this->getTemplate()); - if ($this->getCurrentCategory()) { - $key.= md5($this->getCurrentCategory()->getPath()); - } + $key.= md5($this->getCurrenCategoryKey()); + $key.= Mage::getSingleton('customer/session')->getCustomerGroupId(); return $key; } + public function getCurrenCategoryKey() + { + if ($category = Mage::registry('current_category')) { + return $category->getPath(); + } else { + return Mage::app()->getStore()->getRootCategoryId(); + } + } + /** * Get catagories of current store * @@ -74,21 +82,11 @@ public function getCurrentChildCategories() $layer = Mage::getSingleton('catalog/layer'); $category = $layer->getCurrentCategory(); /* @var $category Mage_Catalog_Model_Category */ - $collection = Mage::getModel('catalog/category')->getCollection(); - /* @var $collection Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection */ - $collection->addAttributeToSelect('url_key') - ->addAttributeToSelect('name') - ->addAttributeToSelect('is_anchor') - ->addAttributeToFilter('is_active', 1) - ->addIdFilter($category->getChildren()) - ->setOrder('position', 'ASC') - ->joinUrlRewrite() - ->load(); - + $categories = $category->getChildrenCategories(); $productCollection = Mage::getResourceModel('catalog/product_collection'); $layer->prepareProductCollection($productCollection); - $productCollection->addCountToCategories($collection); - return $collection; + $productCollection->addCountToCategories($categories); + return $categories; } /** @@ -128,6 +126,7 @@ public function getCategoryUrl($category) ->setData($category->getData()) ->getUrl(); } + return $url; } @@ -143,12 +142,16 @@ public function drawItem($category, $level=0, $last=false) { $html = ''; if (!$category->getIsActive()) { - return $html; } - - $children = $category->getChildren(); - $hasChildren = $children && $children->count(); + if (Mage::helper('catalog/category_flat')->isEnabled()) { + $children = $category->getChildrenNodes(); + $childrenCount = count($children); + } else { + $children = $category->getChildren(); + $childrenCount = $children->count(); + } + $hasChildren = $children && $childrenCount; $html.= 'getCategoryUrl($category).'">'.$this->htmlEscape($category->getName()).''."\n"; - //$html.= ''.$level.''; if ($hasChildren){ diff --git a/app/code/core/Mage/Catalog/Block/Product/Compare/List.php b/app/code/core/Mage/Catalog/Block/Product/Compare/List.php index 10bc014688..2b9728fb70 100644 --- a/app/code/core/Mage/Catalog/Block/Product/Compare/List.php +++ b/app/code/core/Mage/Catalog/Block/Product/Compare/List.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -30,13 +30,29 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ - class Mage_Catalog_Block_Product_Compare_List extends Mage_Catalog_Block_Product_Abstract - { +class Mage_Catalog_Block_Product_Compare_List extends Mage_Catalog_Block_Product_Abstract +{ + /** + * Product Compare Items Collection + * + * @var Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Compare_Item_Collection + */ protected $_items = null; + + /** + * Product Compare attributes array + * + * @var array + */ protected $_attributes = null; + /** + * Preparing layout + * + * @return Mage_Catalog_Block_Product_Compare_List + */ protected function _prepareLayout() { if ($headBlock = $this->getLayout()->getBlock('head')) { @@ -45,17 +61,26 @@ protected function _prepareLayout() return parent::_prepareLayout(); } + /** + * Retrieve Product Compare items collection + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Compare_Item_Collection + */ public function getItems() { - if(is_null($this->_items)) { + if (is_null($this->_items)) { + Mage::helper('catalog/product_compare')->setAllowUsedFlat(false); $this->_items = Mage::getResourceModel('catalog/product_compare_item_collection') ->useProductItem(true) ->setStoreId(Mage::app()->getStore()->getId()); - if(Mage::getSingleton('customer/session')->isLoggedIn()) { - $this->_items->setCustomerId(Mage::getSingleton('customer/session')->getCustomerId()); - } else { - $this->_items->setVisitorId(Mage::getSingleton('log/visitor')->getId()); + if (Mage::getSingleton('customer/session')->isLoggedIn()) { + $this->_items + ->setCustomerId(Mage::getSingleton('customer/session')->getCustomerId()); + } + else { + $this->_items + ->setVisitorId(Mage::getSingleton('log/visitor')->getId()); } $this->_items @@ -64,26 +89,37 @@ public function getItems() ->addMinimalPrice() ->addTaxPercents(); - Mage::getSingleton('catalog/product_visibility')->addVisibleInSiteFilterToCollection($this->_items); + Mage::getSingleton('catalog/product_visibility') + ->addVisibleInSiteFilterToCollection($this->_items); } return $this->_items; } + /** + * Retrieve Product Compare Attributes + * + * @return array + */ public function getAttributes() { - if(is_null($this->_attributes)) { + if (is_null($this->_attributes)) { $this->_setAttributesFromProducts(); } return $this->_attributes; } + /** + * Initialize Product Compare Attributes Process + * + * @return Mage_Catalog_Block_Product_Compare_List + */ protected function _setAttributesFromProducts() { $this->_attributes = array(); - foreach($this->getItems() as $item) { - foreach ($item->getTypeInstance()->getSetAttributes() as $attribute) { + foreach ($this->getItems() as $item) { + foreach ($item->getTypeInstance(true)->getSetAttributes($item) as $attribute) { if ($attribute->getIsComparable() && !isset($this->_attributes[$attribute->getAttributeCode()]) && $item->getData($attribute->getAttributeCode())!==null) { @@ -94,25 +130,36 @@ protected function _setAttributesFromProducts() return $this; } + /** + * Retrieve Product Attribute Value + * + * @param Mage_Catalog_Model_Product $product + * @param Mage_Catalog_Model_Resource_Eav_Attribute $attribute + * @return string + */ public function getProductAttributeValue($product, $attribute) { - if(!$product->hasData($attribute->getAttributeCode())) { + if (!$product->hasData($attribute->getAttributeCode())) { return ' '; } - if($attribute->getSourceModel() || in_array($attribute->getFrontendInput(), array('select','boolean','multiselect'))){ - + if ($attribute->getSourceModel() || in_array($attribute->getFrontendInput(), array('select','boolean','multiselect'))) { //$value = $attribute->getSource()->getOptionText($product->getData($attribute->getAttributeCode())); $value = $attribute->getFrontend()->getValue($product); - } else { + } + else { $value = $product->getData($attribute->getAttributeCode()); } return $value ? $value : ' '; } + /** + * Retrieve Print URL + * + * @return string + */ public function getPrintUrl() { return $this->getUrl('*/*/*', array('_current'=>true, 'print'=>1)); } - - } +} diff --git a/app/code/core/Mage/Catalog/Block/Product/List.php b/app/code/core/Mage/Catalog/Block/Product/List.php index dd068cc8ae..1114cac4b3 100644 --- a/app/code/core/Mage/Catalog/Block/Product/List.php +++ b/app/code/core/Mage/Catalog/Block/Product/List.php @@ -1,178 +1,251 @@ - - */ -class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract -{ - protected $_defaultToolbarBlock = 'catalog/product_list_toolbar'; - protected $_productCollection; - - /** - * Retrieve loaded category collection - * - * @return Mage_Eav_Model_Entity_Collection_Abstract - */ - protected function _getProductCollection() - { - if (is_null($this->_productCollection)) { - $layer = Mage::getSingleton('catalog/layer'); - /* @var $layer Mage_Catalog_Model_Layer */ - if ($this->getShowRootCategory()) { - $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId()); - } - - // if this is a product view page - if (Mage::registry('product')) { - // get collection of categories this product is associated with - $categories = Mage::registry('product')->getCategoryCollection() - ->setPage(1, 1) - ->load(); - // if the product is associated with any category - if ($categories->count()) { - // show products from this category - $this->setCategoryId(current($categories->getIterator())); - } - } - - $origCategory = null; - if ($this->getCategoryId()) { - $category = Mage::getModel('catalog/category')->load($this->getCategoryId()); - if ($category->getId()) { - $origCategory = $layer->getCurrentCategory(); - $layer->setCurrentCategory($category); - } - } - $this->_productCollection = $layer->getProductCollection(); - - if ($sortField = $this->getSortBy()) { - $sortOrder = 'asc'; - if (strtolower($this->getSortOrder()) == 'desc') { - $sortOrder = 'desc'; - } - $this->_productCollection->addAttributeToSort($sortField, $sortOrder); - } - - if ($origCategory) { - $layer->setCurrentCategory($origCategory); - } - } - return $this->_productCollection; - } - - /** - * Retrieve loaded category collection - * - * @return Mage_Eav_Model_Entity_Collection_Abstract - */ - public function getLoadedProductCollection() - { - return $this->_getProductCollection(); - } - - /** - * Retrieve current view mode - * - * @return string - */ - public function getMode() - { - return $this->getChild('toolbar')->getCurrentMode(); - } - - /** - * Need use as _prepareLayout - but problem in declaring collection from - * another block (was problem with search result) - */ - protected function _beforeToHtml() - { - /*$toolbar = $this->getLayout()->createBlock('catalog/product_list_toolbar', microtime()); - if ($toolbarTemplate = $this->getToolbarTemplate()) { - $toolbar->setTemplate($toolbarTemplate); - }*/ - $toolbar = $this->getToolbarBlock(); - if ($orders = $this->getAvailableOrders()) { - $toolbar->setAvailableOrders($orders); - } - if ($modes = $this->getModes()) { - $toolbar->setModes($modes); - } - $toolbar->setCollection($this->_getProductCollection()); - $this->setChild('toolbar', $toolbar); - Mage::dispatchEvent('catalog_block_product_list_collection', array( - 'collection'=>$this->_getProductCollection(), - )); - - $this->_getProductCollection()->load(); - Mage::getModel('review/review')->appendSummary($this->_getProductCollection()); - return parent::_beforeToHtml(); - } - - public function getToolbarBlock() - { - if ($blockName = $this->getToolbarBlockName()) { - if ($block = $this->getLayout()->getBlock($blockName)) { - return $block; - } - } - $block = $this->getLayout()->createBlock($this->_defaultToolbarBlock, microtime()); - return $block; - } - - /** - * Retrieve list toolbar HTML - * - * @return string - */ - public function getToolbarHtml() - { - return $this->getChildHtml('toolbar'); - } - - public function setCollection($collection) - { - $this->_productCollection = $collection; - return $this; - } - - public function addAttribute($code) - { - $this->_getProductCollection()->addAttributeToSelect($code); - return $this; - } - - public function getPriceBlockTemplate() - { - return $this->_getData('price_block_template'); - } - -} + + */ +class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract +{ + /** + * Default toolbar block name + * + * @var string + */ + protected $_defaultToolbarBlock = 'catalog/product_list_toolbar'; + + /** + * Product Collection + * + * @var Mage_Eav_Model_Entity_Collection_Abstract + */ + protected $_productCollection; + + /** + * Retrieve loaded category collection + * + * @return Mage_Eav_Model_Entity_Collection_Abstract + */ + protected function _getProductCollection() + { + if (is_null($this->_productCollection)) { + $layer = Mage::getSingleton('catalog/layer'); + /* @var $layer Mage_Catalog_Model_Layer */ + if ($this->getShowRootCategory()) { + $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId()); + } + + // if this is a product view page + if (Mage::registry('product')) { + // get collection of categories this product is associated with + $categories = Mage::registry('product')->getCategoryCollection() + ->setPage(1, 1) + ->load(); + // if the product is associated with any category + if ($categories->count()) { + // show products from this category + $this->setCategoryId(current($categories->getIterator())); + } + } + + $origCategory = null; + if ($this->getCategoryId()) { + $category = Mage::getModel('catalog/category')->load($this->getCategoryId()); + if ($category->getId()) { + $origCategory = $layer->getCurrentCategory(); + $layer->setCurrentCategory($category); + } + } + $this->_productCollection = $layer->getProductCollection(); + + $this->prepareSortableFieldsByCategory($layer->getCurrentCategory()); + + if ($origCategory) { + $layer->setCurrentCategory($origCategory); + } + } + return $this->_productCollection; + } + + /** + * Retrieve loaded category collection + * + * @return Mage_Eav_Model_Entity_Collection_Abstract + */ + public function getLoadedProductCollection() + { + return $this->_getProductCollection(); + } + + /** + * Retrieve current view mode + * + * @return string + */ + public function getMode() + { + return $this->getChild('toolbar')->getCurrentMode(); + } + + /** + * Need use as _prepareLayout - but problem in declaring collection from + * another block (was problem with search result) + */ + protected function _beforeToHtml() + { + /*$toolbar = $this->getLayout()->createBlock('catalog/product_list_toolbar', microtime()); + if ($toolbarTemplate = $this->getToolbarTemplate()) { + $toolbar->setTemplate($toolbarTemplate); + }*/ + $toolbar = $this->getToolbarBlock(); + + // called prepare sortable parameters + $collection = $this->_getProductCollection(); + + // use sortable parameters + if ($orders = $this->getAvailableOrders()) { + $toolbar->setAvailableOrders($orders); + } + if ($sort = $this->getSortBy()) { + $toolbar->setDefaultOrder($sort); + } + if ($modes = $this->getModes()) { + $toolbar->setModes($modes); + } + + // set collection to tollbar and apply sort + $toolbar->setCollection($collection); + + $this->setChild('toolbar', $toolbar); + Mage::dispatchEvent('catalog_block_product_list_collection', array( + 'collection'=>$this->_getProductCollection(), + )); + + $this->_getProductCollection()->load(); + Mage::getModel('review/review')->appendSummary($this->_getProductCollection()); + return parent::_beforeToHtml(); + } + + /** + * Retrieve Toolbar block + * + * @return Mage_Catalog_Block_Product_List_Toolbar + */ + public function getToolbarBlock() + { + if ($blockName = $this->getToolbarBlockName()) { + if ($block = $this->getLayout()->getBlock($blockName)) { + return $block; + } + } + $block = $this->getLayout()->createBlock($this->_defaultToolbarBlock, microtime()); + return $block; + } + + /** + * Retrieve list toolbar HTML + * + * @return string + */ + public function getToolbarHtml() + { + return $this->getChildHtml('toolbar'); + } + + public function setCollection($collection) + { + $this->_productCollection = $collection; + return $this; + } + + public function addAttribute($code) + { + $this->_getProductCollection()->addAttributeToSelect($code); + return $this; + } + + public function getPriceBlockTemplate() + { + return $this->_getData('price_block_template'); + } + + /** + * Retrieve Catalog Config object + * + * @return Mage_Catalog_Model_Config + */ + protected function _getConfig() + { + return Mage::getSingleton('catalog/config'); + } + + /** + * Prepare Sort By fields from Category Data + * + * @param Mage_Catalog_Model_Category $category + * @return Mage_Catalog_Block_Product_List + */ + public function prepareSortableFieldsByCategory($category) { + if (!$this->getAvailableOrders()) { + $this->setAvailableOrders($category->getAvailableSortByOptions()); + } + $availableOrders = $this->getAvailableOrders(); + if (!$this->getSortBy()) { + if ($categorySortBy = $category->getDefaultSortBy()) { + if (!$availableOrders) { + $availableOrders = $this->_getConfig()->getAttributeUsedForSortByArray(); + } + if (isset($availableOrders[$categorySortBy])) { + $this->setSortBy($categorySortBy); + } + } + } + + return $this; + } + + /** + * Retrieve url for add product to cart + * Rewrited for Product List and has required options products + * + * @param Mage_Catalog_Model_Product $product + * @param array $additional + * @return string + */ + public function getAddToCartUrl($product, $additional = array()) + { + if ($product->hasRequiredOptions()) { + $url = $product->getProductUrl(); + $link = (strpos($url, '?') !== false) ? '&' : '?'; + return $url . $link . 'options=cart'; + } + return parent::getAddToCartUrl($product, $additional); + } +} diff --git a/app/code/core/Mage/Catalog/Block/Product/List/Crosssell.php b/app/code/core/Mage/Catalog/Block/Product/List/Crosssell.php index 41eb53f7ec..aa5f2e0402 100644 --- a/app/code/core/Mage/Catalog/Block/Product/List/Crosssell.php +++ b/app/code/core/Mage/Catalog/Block/Product/List/Crosssell.php @@ -32,7 +32,7 @@ * @author Magento Core Team */ -class Mage_Catalog_Block_Product_Link_Crosssell extends Mage_Catalog_Block_Product_Abstract +class Mage_Catalog_Block_Product_List_Crosssell extends Mage_Catalog_Block_Product_Abstract { protected $_itemCollection; diff --git a/app/code/core/Mage/Catalog/Block/Product/List/Toolbar.php b/app/code/core/Mage/Catalog/Block/Product/List/Toolbar.php index 0e94a1dbaa..0c785566e8 100644 --- a/app/code/core/Mage/Catalog/Block/Product/List/Toolbar.php +++ b/app/code/core/Mage/Catalog/Block/Product/List/Toolbar.php @@ -103,6 +103,16 @@ class Mage_Catalog_Block_Product_List_Toolbar extends Mage_Page_Block_Html_Pager */ protected $_viewMode = null; + /** + * Retrieve Catalog Config object + * + * @return Mage_Catalog_Model_Config + */ + protected function _getConfig() + { + return Mage::getSingleton('catalog/config'); + } + /** * Init Toolbar * @@ -110,12 +120,12 @@ class Mage_Catalog_Block_Product_List_Toolbar extends Mage_Page_Block_Html_Pager protected function _construct() { parent::_construct(); - $this->_availableOrder = array( - 'position' => $this->__('Best Value'), - 'name' => $this->__('Name'), - 'price' => $this->__('Price') + $this->_orderField = Mage::getStoreConfig( + Mage_Catalog_Model_Config::XML_PATH_LIST_DEFAULT_SORT_BY ); + $this->_availableOrder = $this->_getConfig()->getAttributeUsedForSortByArray(); + switch (Mage::getStoreConfig('catalog/frontend/list_mode')) { case 'grid': $this->_availableMode = array('grid' => $this->__('Grid')); @@ -266,6 +276,32 @@ public function setAvailableOrders($orders) return $this; } + /** + * Add order to available orders + * + * @param string $order + * @param string $value + * @return Mage_Catalog_Block_Product_List_Toolbar + */ + public function addOrderToAvailableOrders($order, $value) + { + $this->_availableOrder[$order] = $value; + return $this; + } + /** + * Remove order from available orders if exists + * + * @param string $order + * @param Mage_Catalog_Block_Product_List_Toolbar + */ + public function removeOrderFromAvailableOrders($order) + { + if (isset($this->_availableOrder[$order])) { + unset($this->_availableOrder[$order]); + } + return $this; + } + /** * Compare defined order field vith current order field * @@ -274,7 +310,7 @@ public function setAvailableOrders($orders) */ public function isOrderCurrent($order) { - return $order == $this->getRequest()->getParam('order'); + return ($order == $this->getCurrentOrder()); } /** diff --git a/app/code/core/Mage/Catalog/Block/Product/View.php b/app/code/core/Mage/Catalog/Block/Product/View.php index a8ecfeb6fe..17da386d41 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View.php +++ b/app/code/core/Mage/Catalog/Block/Product/View.php @@ -1,164 +1,164 @@ -getLayout()->createBlock('catalog/breadcrumbs'); - if ($headBlock = $this->getLayout()->getBlock('head')) { - if ($title = $this->getProduct()->getMetaTitle()) { - $headBlock->setTitle($title); - } - - if ($keyword = $this->getProduct()->getMetaKeyword()) { - $headBlock->setKeywords($keyword); - } elseif( $currentCategory = Mage::registry('current_category') ) { - $headBlock->setKeywords($this->getProduct()->getName()); - } - - if ($description = $this->getProduct()->getMetaDescription()) { - $headBlock->setDescription( ($description) ); - } else { - $headBlock->setDescription( $this->getProduct()->getDescription() ); - } - } - return parent::_prepareLayout(); - } - - /** - * Retrieve current product model - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - if (!Mage::registry('product') && $this->getProductId()) { - $product = Mage::getModel('catalog/product')->load($this->getProductId()); - Mage::register('product', $product); - } - return Mage::registry('product'); - } - - public function canEmailToFriend() - { - $sendToFriendModel = Mage::registry('send_to_friend_model'); - return $sendToFriendModel && $sendToFriendModel->canEmailToFriend(); - } - - public function getAddToCartUrl($product, $additional = array()) - { - $additional = array(); - - if ($this->getRequest()->getParam('wishlist_next')){ - $additional['wishlist_next'] = 1; - } - - return parent::getAddToCartUrl($product, $additional); - } - - public function getJsonConfig() - { - $config = array(); - - $_request = Mage::getSingleton('tax/calculation')->getRateRequest(false, false, false); - $_request->setProductClassId($this->getProduct()->getTaxClassId()); - $defaultTax = Mage::getSingleton('tax/calculation')->getRate($_request); - - $_request = Mage::getSingleton('tax/calculation')->getRateRequest(); - $_request->setProductClassId($this->getProduct()->getTaxClassId()); - $currentTax = Mage::getSingleton('tax/calculation')->getRate($_request); - - $_regularPrice = $this->getProduct()->getPrice(); - $_finalPrice = $this->getProduct()->getFinalPrice(); - $_priceInclTax = Mage::helper('tax')->getPrice($this->getProduct(), $_finalPrice, true); - $_priceExclTax = Mage::helper('tax')->getPrice($this->getProduct(), $_finalPrice); - - $idSuffix = '__none__'; - if ($this->hasOptions()) { - $idSuffix = '_clone'; - } - - $config = array( - 'productId' => $this->getProduct()->getId(), - 'priceFormat' => Mage::app()->getLocale()->getJsPriceFormat(), - 'includeTax' => Mage::helper('tax')->priceIncludesTax() ? 'true' : 'false', - 'showIncludeTax' => Mage::helper('tax')->displayPriceIncludingTax(), - 'showBothPrices' => Mage::helper('tax')->displayBothPrices(), - 'productPrice' => Mage::helper('core')->currency($_finalPrice, false, false), - 'productOldPrice' => Mage::helper('core')->currency($_regularPrice, false, false), - 'skipCalculate' => ($_priceExclTax != $_priceInclTax ? 0 : 1), - 'defaultTax' => $defaultTax, - 'currentTax' => $currentTax, - 'idSuffix' => $idSuffix, - 'oldPlusDisposition' => 0, - 'plusDisposition' => 0, - 'oldMinusDisposition' => 0, - 'minusDisposition' => 0, - ); - - $responseObject = new Varien_Object(); - Mage::dispatchEvent('catalog_product_view_config', array('response_object'=>$responseObject)); - if (is_array($responseObject->getAdditionalOptions())) { - foreach ($responseObject->getAdditionalOptions() as $option=>$value) { - $config[$option] = $value; - } - } - - return Zend_Json::encode($config); - } - - /** - * Return true if product has options - * - * @return bool - */ - public function hasOptions() - { - if ($this->getProduct()->getTypeInstance()->hasOptions()) { - return true; - } - return false; - } - - /** - * Check if product has required options - * - * @return bool - */ - public function hasRequiredOptions() - { - return $this->getProduct()->getTypeInstance()->hasRequiredOptions(); - } -} +getLayout()->createBlock('catalog/breadcrumbs'); + if ($headBlock = $this->getLayout()->getBlock('head')) { + if ($title = $this->getProduct()->getMetaTitle()) { + $headBlock->setTitle($title); + } + + if ($keyword = $this->getProduct()->getMetaKeyword()) { + $headBlock->setKeywords($keyword); + } elseif( $currentCategory = Mage::registry('current_category') ) { + $headBlock->setKeywords($this->getProduct()->getName()); + } + + if ($description = $this->getProduct()->getMetaDescription()) { + $headBlock->setDescription( ($description) ); + } else { + $headBlock->setDescription( $this->getProduct()->getDescription() ); + } + } + return parent::_prepareLayout(); + } + + /** + * Retrieve current product model + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + if (!Mage::registry('product') && $this->getProductId()) { + $product = Mage::getModel('catalog/product')->load($this->getProductId()); + Mage::register('product', $product); + } + return Mage::registry('product'); + } + + public function canEmailToFriend() + { + $sendToFriendModel = Mage::registry('send_to_friend_model'); + return $sendToFriendModel && $sendToFriendModel->canEmailToFriend(); + } + + public function getAddToCartUrl($product, $additional = array()) + { + $additional = array(); + + if ($this->getRequest()->getParam('wishlist_next')){ + $additional['wishlist_next'] = 1; + } + + return parent::getAddToCartUrl($product, $additional); + } + + public function getJsonConfig() + { + $config = array(); + + $_request = Mage::getSingleton('tax/calculation')->getRateRequest(false, false, false); + $_request->setProductClassId($this->getProduct()->getTaxClassId()); + $defaultTax = Mage::getSingleton('tax/calculation')->getRate($_request); + + $_request = Mage::getSingleton('tax/calculation')->getRateRequest(); + $_request->setProductClassId($this->getProduct()->getTaxClassId()); + $currentTax = Mage::getSingleton('tax/calculation')->getRate($_request); + + $_regularPrice = $this->getProduct()->getPrice(); + $_finalPrice = $this->getProduct()->getFinalPrice(); + $_priceInclTax = Mage::helper('tax')->getPrice($this->getProduct(), $_finalPrice, true); + $_priceExclTax = Mage::helper('tax')->getPrice($this->getProduct(), $_finalPrice); + + $idSuffix = '__none__'; + if ($this->hasOptions()) { + $idSuffix = '_clone'; + } + + $config = array( + 'productId' => $this->getProduct()->getId(), + 'priceFormat' => Mage::app()->getLocale()->getJsPriceFormat(), + 'includeTax' => Mage::helper('tax')->priceIncludesTax() ? 'true' : 'false', + 'showIncludeTax' => Mage::helper('tax')->displayPriceIncludingTax(), + 'showBothPrices' => Mage::helper('tax')->displayBothPrices(), + 'productPrice' => Mage::helper('core')->currency($_finalPrice, false, false), + 'productOldPrice' => Mage::helper('core')->currency($_regularPrice, false, false), + 'skipCalculate' => ($_priceExclTax != $_priceInclTax ? 0 : 1), + 'defaultTax' => $defaultTax, + 'currentTax' => $currentTax, + 'idSuffix' => $idSuffix, + 'oldPlusDisposition' => 0, + 'plusDisposition' => 0, + 'oldMinusDisposition' => 0, + 'minusDisposition' => 0, + ); + + $responseObject = new Varien_Object(); + Mage::dispatchEvent('catalog_product_view_config', array('response_object'=>$responseObject)); + if (is_array($responseObject->getAdditionalOptions())) { + foreach ($responseObject->getAdditionalOptions() as $option=>$value) { + $config[$option] = $value; + } + } + + return Zend_Json::encode($config); + } + + /** + * Return true if product has options + * + * @return bool + */ + public function hasOptions() + { + if ($this->getProduct()->getTypeInstance(true)->hasOptions($this->getProduct())) { + return true; + } + return false; + } + + /** + * Check if product has required options + * + * @return bool + */ + public function hasRequiredOptions() + { + return $this->getProduct()->getTypeInstance(true)->hasRequiredOptions($this->getProduct()); + } +} diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Abstract.php b/app/code/core/Mage/Catalog/Block/Product/View/Abstract.php index 832e3eb76e..7162f272ac 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Abstract.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Abstract.php @@ -1,51 +1,51 @@ - - */ -abstract class Mage_Catalog_Block_Product_View_Abstract extends Mage_Catalog_Block_Product_Abstract -{ - /** - * Retrive product - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - $product = parent::getProduct(); - if (is_null($product->getTypeInstance()->getStoreFilter())) { - $product->getTypeInstance()->setStoreFilter(Mage::app()->getStore()); - } - - return $product; - } - -} + + */ +abstract class Mage_Catalog_Block_Product_View_Abstract extends Mage_Catalog_Block_Product_Abstract +{ + /** + * Retrive product + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + $product = parent::getProduct(); + if (is_null($product->getTypeInstance(true)->getStoreFilter($product))) { + $product->getTypeInstance(true)->setStoreFilter(Mage::app()->getStore(), $product); + } + + return $product; + } + +} diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Options.php b/app/code/core/Mage/Catalog/Block/Product/View/Options.php index 53c7fbb1b4..fa985048eb 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Options.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Options.php @@ -1,177 +1,180 @@ - - */ -class Mage_Catalog_Block_Product_View_Options extends Mage_Core_Block_Template -{ - protected $_product; - - protected $_optionRenders = array(); - - public function __construct() - { - parent::__construct(); - $this->addOptionRenderer( - 'default', - 'catalog/product_view_options_type_default', - 'catalog/product/view/options/type/default.phtml' - ); - } - - /** - * Retrieve product object - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - if (!$this->_product) { - if (Mage::registry('product')) { - $this->_product = Mage::registry('product'); - } else { - $this->_product = Mage::getSingleton('catalog/product'); - } - } - return $this->_product; - } - - /** - * Set product object - * - * @param Mage_Catalog_Model_Product $product - * @return Mage_Catalog_Block_Product_View_Options - */ - public function setProduct($product) - { - $this->_product = $product; - return $this; - } - - /** - * Add option renderer to renderers array - * - * @param string $type - * @param string $block - * @param string $template - * @return Mage_Catalog_Block_Product_View_Options - */ - public function addOptionRenderer($type, $block, $template) - { - $this->_optionRenders[$type] = array( - 'block' => $block, - 'template' => $template, - 'renderer' => null - ); - return $this; - } - - /** - * Get option render by given type - * - * @param string $type - * @return array - */ - public function getOptionRender($type) - { - if (isset($this->_optionRenders[$type])) { - return $this->_optionRenders[$type]; - } - - return $this->_optionRenders['default']; - } - - public function getGroupOfOption($type) - { - $group = Mage::getSingleton('catalog/product_option')->getGroupByType($type); - - return $group == '' ? 'default' : $group; - } - - /** - * Get product options - * - * @return array - */ - public function getOptions() - { - return $this->getProduct()->getOptions(); - } - - public function hasOptions() - { - if ($this->getOptions()) { - return true; - } - return false; - } - - public function getJsonConfig() - { - $config = array(); - - foreach ($this->getOptions() as $option) { - /* @var $option Mage_Catalog_Model_Product_Option */ - $priceValue = 0; - if ($option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $_tmpPriceValues = array(); - foreach ($option->getValues() as $value) { - /* @var $value Mage_Catalog_Model_Product_Option_Value */ - $_tmpPriceValues[$value->getId()] = Mage::helper('core')->currency($value->getPrice(true), false, false); - } - $priceValue = $_tmpPriceValues; - } else { - $priceValue = Mage::helper('core')->currency($option->getPrice(), false, false); - } - $config[$option->getId()] = $priceValue; - } - - return Zend_Json::encode($config); - } - - /** - * Get option html block - * - * @param Mage_Catalog_Model_Product_Option $option - */ - public function getOptionHtml(Mage_Catalog_Model_Product_Option $option) - { - $renderer = $this->getOptionRender( - $this->getGroupOfOption($option->getType()) - ); - if (is_null($renderer['renderer'])) { - $renderer['renderer'] = $this->getLayout()->createBlock($renderer['block']) - ->setTemplate($renderer['template']); - } - return $renderer['renderer']->setOption($option)->toHtml(); - } + + */ +class Mage_Catalog_Block_Product_View_Options extends Mage_Core_Block_Template +{ + protected $_product; + + protected $_optionRenders = array(); + + public function __construct() + { + parent::__construct(); + $this->addOptionRenderer( + 'default', + 'catalog/product_view_options_type_default', + 'catalog/product/view/options/type/default.phtml' + ); + } + + /** + * Retrieve product object + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + if (!$this->_product) { + if (Mage::registry('product')) { + $this->_product = Mage::registry('current_product'); + } else { + $this->_product = Mage::getSingleton('catalog/product'); + } + } + return $this->_product; + } + + /** + * Set product object + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Block_Product_View_Options + */ + public function setProduct(Mage_Catalog_Model_Product $product = null) + { + $this->_product = $product; + return $this; + } + + /** + * Add option renderer to renderers array + * + * @param string $type + * @param string $block + * @param string $template + * @return Mage_Catalog_Block_Product_View_Options + */ + public function addOptionRenderer($type, $block, $template) + { + $this->_optionRenders[$type] = array( + 'block' => $block, + 'template' => $template, + 'renderer' => null + ); + return $this; + } + + /** + * Get option render by given type + * + * @param string $type + * @return array + */ + public function getOptionRender($type) + { + if (isset($this->_optionRenders[$type])) { + return $this->_optionRenders[$type]; + } + + return $this->_optionRenders['default']; + } + + public function getGroupOfOption($type) + { + $group = Mage::getSingleton('catalog/product_option')->getGroupByType($type); + + return $group == '' ? 'default' : $group; + } + + /** + * Get product options + * + * @return array + */ + public function getOptions() + { + return $this->getProduct()->getOptions(); + } + + public function hasOptions() + { + if ($this->getOptions()) { + return true; + } + return false; + } + + public function getJsonConfig() + { + $config = array(); + + foreach ($this->getOptions() as $option) { + /* @var $option Mage_Catalog_Model_Product_Option */ + $priceValue = 0; + if ($option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { + $_tmpPriceValues = array(); + foreach ($option->getValues() as $value) { + /* @var $value Mage_Catalog_Model_Product_Option_Value */ + $_tmpPriceValues[$value->getId()] = Mage::helper('core')->currency($value->getPrice(true), false, false); + } + $priceValue = $_tmpPriceValues; + } else { + $priceValue = Mage::helper('core')->currency($option->getPrice(), false, false); + } + $config[$option->getId()] = $priceValue; + } + + return Zend_Json::encode($config); + } + + /** + * Get option html block + * + * @param Mage_Catalog_Model_Product_Option $option + */ + public function getOptionHtml(Mage_Catalog_Model_Product_Option $option) + { + $renderer = $this->getOptionRender( + $this->getGroupOfOption($option->getType()) + ); + if (is_null($renderer['renderer'])) { + $renderer['renderer'] = $this->getLayout()->createBlock($renderer['block']) + ->setTemplate($renderer['template']); + } + return $renderer['renderer'] + ->setProduct($this->getProduct()) + ->setOption($option) + ->toHtml(); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Options/Abstract.php b/app/code/core/Mage/Catalog/Block/Product/View/Options/Abstract.php index b99f19547e..13146c1050 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Options/Abstract.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Options/Abstract.php @@ -1,126 +1,160 @@ - - */ -abstract class Mage_Catalog_Block_Product_View_Options_Abstract extends Mage_Core_Block_Template -{ - protected $_option; - - /** - * Set option - * - * @param Mage_Catalog_Model_Product_Option $option - * @return Mage_Catalog_Block_Product_View_Options_Abstract - */ - public function setOption(Mage_Catalog_Model_Product_Option $option) - { - $this->_option = $option; - return $this; - } - - /** - * Get option - * - * @return Mage_Catalog_Model_Product_Option - */ - public function getOption() - { - return $this->_option; - } - - public function getFormatedPrice() - { - if ($option = $this->getOption()) { - return $this->_formatPrice(array( - 'is_percent' => ($option->getPriceType() == 'percent') ? true : false, - 'pricing_value' => $option->getPrice(true) - )); - } - return ''; - } - - /** - * Return formated price - * - * @param array $value - * @return string - */ - protected function _formatPrice($value, $flag=true) - { - if ($value['pricing_value'] == 0) { - return ''; - } - $sign = '+'; - if ($value['pricing_value'] < 0) { - $sign = '-'; - $value['pricing_value'] = 0 - $value['pricing_value']; - } - $priceStr = $sign; - $_priceInclTax = $this->getPrice($value['pricing_value'], true); - $_priceExclTax = $this->getPrice($value['pricing_value']); - if (Mage::helper('tax')->displayPriceIncludingTax()) { - $priceStr .= $this->helper('core')->currency($_priceInclTax, true, $flag); - } elseif (Mage::helper('tax')->displayPriceExcludingTax()) { - $priceStr .= $this->helper('core')->currency($_priceExclTax, true, $flag); - } elseif (Mage::helper('tax')->displayBothPrices()) { - $priceStr .= $this->helper('core')->currency($_priceExclTax, true, $flag); - if ($_priceInclTax != $_priceExclTax) { - $priceStr .= ' ('.$sign.$this->helper('core') - ->currency($_priceInclTax, true, $flag).' '.$this->__('Incl. Tax').')'; - } - } - - if ($flag) { - $priceStr = ''.$priceStr.''; - } - - return $priceStr; - } - - /** - * Get price with including/excluding tax - * - * @param decimal $price - * @param bool $includingTax - * @return decimal - */ - public function getPrice($price, $includingTax = null) - { - if (!is_null($includingTax)) { - $price = Mage::helper('tax')->getPrice($this->getOption()->getProduct(), $price, true); - } else { - $price = Mage::helper('tax')->getPrice($this->getOption()->getProduct(), $price); - } - return $price; - } + + */ +abstract class Mage_Catalog_Block_Product_View_Options_Abstract extends Mage_Core_Block_Template +{ + /** + * Product object + * + * @var Mage_Catalog_Model_Product + */ + protected $_product; + + /** + * Product option object + * + * @var Mage_Catalog_Model_Product_Option + */ + protected $_option; + + /** + * Set Product object + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Block_Product_View_Options_Abstract + */ + public function setProduct(Mage_Catalog_Model_Product $product = null) + { + $this->_product = $product; + return $this; + } + + /** + * Retrieve Product object + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + return $this->_product; + } + + /** + * Set option + * + * @param Mage_Catalog_Model_Product_Option $option + * @return Mage_Catalog_Block_Product_View_Options_Abstract + */ + public function setOption(Mage_Catalog_Model_Product_Option $option) + { + $this->_option = $option; + return $this; + } + + /** + * Get option + * + * @return Mage_Catalog_Model_Product_Option + */ + public function getOption() + { + return $this->_option; + } + + public function getFormatedPrice() + { + if ($option = $this->getOption()) { + return $this->_formatPrice(array( + 'is_percent' => ($option->getPriceType() == 'percent') ? true : false, + 'pricing_value' => $option->getPrice(true) + )); + } + return ''; + } + + /** + * Return formated price + * + * @param array $value + * @return string + */ + protected function _formatPrice($value, $flag=true) + { + if ($value['pricing_value'] == 0) { + return ''; + } + $sign = '+'; + if ($value['pricing_value'] < 0) { + $sign = '-'; + $value['pricing_value'] = 0 - $value['pricing_value']; + } + $priceStr = $sign; + $_priceInclTax = $this->getPrice($value['pricing_value'], true); + $_priceExclTax = $this->getPrice($value['pricing_value']); + if (Mage::helper('tax')->displayPriceIncludingTax()) { + $priceStr .= $this->helper('core')->currency($_priceInclTax, true, $flag); + } elseif (Mage::helper('tax')->displayPriceExcludingTax()) { + $priceStr .= $this->helper('core')->currency($_priceExclTax, true, $flag); + } elseif (Mage::helper('tax')->displayBothPrices()) { + $priceStr .= $this->helper('core')->currency($_priceExclTax, true, $flag); + if ($_priceInclTax != $_priceExclTax) { + $priceStr .= ' ('.$sign.$this->helper('core') + ->currency($_priceInclTax, true, $flag).' '.$this->__('Incl. Tax').')'; + } + } + + if ($flag) { + $priceStr = ''.$priceStr.''; + } + + return $priceStr; + } + + /** + * Get price with including/excluding tax + * + * @param decimal $price + * @param bool $includingTax + * @return decimal + */ + public function getPrice($price, $includingTax = null) + { + if (!is_null($includingTax)) { + $price = Mage::helper('tax')->getPrice($this->getProduct(), $price, true); + } else { + $price = Mage::helper('tax')->getPrice($this->getProduct(), $price); + } + return $price; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Options/Type/Date.php b/app/code/core/Mage/Catalog/Block/Product/View/Options/Type/Date.php index 3bf8bf0b5a..cefeebcc09 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Options/Type/Date.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Options/Type/Date.php @@ -32,9 +32,16 @@ * @package Mage_Catalog * @author Magento Core Team */ -class Mage_Catalog_Block_Product_View_Options_Type_Date - extends Mage_Catalog_Block_Product_View_Options_Abstract +class Mage_Catalog_Block_Product_View_Options_Type_Date extends Mage_Catalog_Block_Product_View_Options_Abstract { + + /** + * Fill date and time options with leading zeros or not + * + * @var boolean + */ + protected $_fillLeadingZeros = true; + protected function _prepareLayout() { if ($head = $this->getLayout()->getBlock('head')) { @@ -43,52 +50,147 @@ protected function _prepareLayout() return parent::_prepareLayout(); } - public function getCalendarHtml() + /** + * Date input + * + * @return string Formatted Html + */ + public function getDateHtml() { - $require = $this->getOption()->getIsRequire() ? ' required-entry' : ''; + if (Mage::getSingleton('catalog/product_option_type_date')->useCalendar()) { + return $this->getCalendarDateHtml(); + } else { + return $this->getDropDownsDateHtml(); + } + } + + /** + * JS Calendar html + * + * @return string Formatted Html + */ + public function getCalendarDateHtml() + { + // $require = $this->getOption()->getIsRequire() ? ' required-entry' : ''; + $require = ''; $calendar = $this->getLayout() ->createBlock('core/html_date') ->setId('options_'.$this->getOption()->getId().'_date') ->setName('options['.$this->getOption()->getId().'][date]') - ->setClass('input-text'.$require) + ->setClass('product-custom-option datetime-picker input-text' . $require) ->setImage(Mage::getDesign()->getSkinUrl('images/grid-cal.gif')) + ->setExtraParams('onchange="opConfig.reloadPrice()"') ->setFormat(Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT)); return $calendar->getHtml(); } + /** + * Date (dd/mm/yyyy) html drop-downs + * + * @return string Formatted Html + */ + public function getDropDownsDateHtml() + { + $_fieldsSeparator = ' '; + $_fieldsOrder = Mage::getSingleton('catalog/product_option_type_date')->getConfigData('date_fields_order'); + $_fieldsOrder = str_replace(',', $_fieldsSeparator, $_fieldsOrder); + + $monthsHtml = $this->_getSelectFromToHtml('month', 1, 12); + $daysHtml = $this->_getSelectFromToHtml('day', 1, 31); + + $_yearStart = Mage::getSingleton('catalog/product_option_type_date')->getYearStart(); + $_yearEnd = Mage::getSingleton('catalog/product_option_type_date')->getYearEnd(); + $yearsHtml = $this->_getSelectFromToHtml('year', $_yearStart, $_yearEnd); + + $_translations = array( + 'd' => $daysHtml, + 'm' => $monthsHtml, + 'y' => $yearsHtml + ); + return strtr($_fieldsOrder, $_translations); + } + + /** + * Time (hh:mm am/pm) html drop-downs + * + * @return string Formatted Html + */ public function getTimeHtml() { - $require = $this->getOption()->getIsRequire() ? ' required-entry' : ''; - $hour = $this->getLayout() - ->createBlock('core/html_select') - ->setData(array( - 'id' => 'options_'.$this->getOption()->getId().'_hour', - 'class' => $require - )) - ->setName('options['.$this->getOption()->getId().'][hour]') - ->setOptions(array('00' => '00', '01' => '01')); - - $minutes = $this->getLayout() - ->createBlock('core/html_select') - ->setData(array( - 'id' => 'options_'.$this->getOption()->getId().'_minutes', - 'class' => $require - )) - ->setName('options['.$this->getOption()->getId().'][minutes]') - ->setOptions(array('00' => '00', '05' => '05')); - - $timeFormat = $this->getLayout() - ->createBlock('core/html_select') - ->setData(array( - 'id' => 'options_'.$this->getOption()->getId().'_time_format', - 'class' => $require + $hourStart = 0; + if (Mage::getSingleton('catalog/product_option_type_date')->is24hTimeFormat()) { + $hourEnd = 23; + $dayPartHtml = ''; + } else { + $hourEnd = 11; + $dayPartHtml = $this->_getHtmlSelect('day_part') + ->setOptions(array( + 'am' => Mage::helper('catalog')->__('AM'), + 'pm' => Mage::helper('catalog')->__('PM') )) - ->setName('options['.$this->getOption()->getId().'][time_format]') - ->setOptions(array('am' => 'AM', 'pm' => 'PM')); + ->getHtml(); + } + $hoursHtml = $this->_getSelectFromToHtml('hour', $hourStart, $hourEnd); + $minutesHtml = $this->_getSelectFromToHtml('minute', 0, 59); + + return $hoursHtml . ' : ' . $minutesHtml . ' ' . $dayPartHtml; + } + + /** + * Return drop-down html with range of values + * + * @param string $name Id/name of html select element + * @param int $from Start position + * @param int $to End position + * @param int $value Value selected + * @return string Formatted Html + */ + protected function _getSelectFromToHtml($name, $from, $to, $value = null) + { + $options = array( + array('value' => '', 'label' => '-') + ); + for ($i = $from; $i <= $to; $i++) { + $options[] = array('value' => $i, 'label' => $this->_getValueWithLeadingZeros($i)); + } + return $this->_getHtmlSelect($name, $value) + ->setOptions($options) + ->getHtml(); + } -//Zend_Debug::dump(Mage::app()->getLocale()->getTimeFormat()); -//Zend_Debug::dump(Mage::app()->getLocale()->getTimeStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT)); - return $hour->getHtml().$minutes->getHtml().$timeFormat->getHtml(); + /** + * HTML select element + * + * @param string $name Id/name of html select element + * @return Mage_Core_Block_Html_Select + */ + protected function _getHtmlSelect($name, $value = null) + { + // $require = $this->getOption()->getIsRequire() ? ' required-entry' : ''; + $require = ''; + $select = $this->getLayout()->createBlock('core/html_select') + ->setId('options_' . $this->getOption()->getId() . '_' . $name) + ->setClass('product-custom-option datetime-picker' . $require) + ->setExtraParams('style="width:auto;" onchange="opConfig.reloadPrice()"') + ->setName('options[' . $this->getOption()->getId() . '][' . $name . ']'); + if (!is_null($value)) { + $select->setValue($value); + } + return $select; + } + + /** + * Add Leading Zeros to number less than 10 + * + * @param int + * @return string + */ + protected function _getValueWithLeadingZeros($value) + { + if (!$this->_fillLeadingZeros) { + return $value; + } + return $value < 10 ? '0'.$value : $value; } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php b/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php index dac34f4f4f..a89413d081 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php @@ -39,7 +39,8 @@ class Mage_Catalog_Block_Product_View_Type_Configurable extends Mage_Catalog_Blo public function getAllowAttributes() { - return $this->getProduct()->getTypeInstance()->getConfigurableAttributes(); + return $this->getProduct()->getTypeInstance(true) + ->getConfigurableAttributes($this->getProduct()); } public function hasOptions() @@ -60,7 +61,8 @@ public function getAllowProducts() { if (!$this->hasAllowProducts()) { $products = array(); - $allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts(); + $allProducts = $this->getProduct()->getTypeInstance(true) + ->getUsedProducts(null, $this->getProduct()); foreach ($allProducts as $product) { if ($product->isSaleable()) { $products[] = $product; diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Type/Grouped.php b/app/code/core/Mage/Catalog/Block/Product/View/Type/Grouped.php index 7585026318..7b21abd284 100644 --- a/app/code/core/Mage/Catalog/Block/Product/View/Type/Grouped.php +++ b/app/code/core/Mage/Catalog/Block/Product/View/Type/Grouped.php @@ -1,41 +1,42 @@ - - */ -class Mage_Catalog_Block_Product_View_Type_Grouped extends Mage_Catalog_Block_Product_View_Abstract -{ - public function getAssociatedProducts() - { - return $this->getProduct()->getTypeInstance()->getAssociatedProducts(); - } + + */ +class Mage_Catalog_Block_Product_View_Type_Grouped extends Mage_Catalog_Block_Product_View_Abstract +{ + public function getAssociatedProducts() + { + return $this->getProduct()->getTypeInstance(true) + ->getAssociatedProducts($this->getProduct()); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Category.php b/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Category.php new file mode 100644 index 0000000000..b5161e76f4 --- /dev/null +++ b/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Category.php @@ -0,0 +1,180 @@ + + */ +class Mage_Catalog_Block_Seo_Sitemap_Tree_Category extends Mage_Catalog_Block_Seo_Sitemap_Category +{ + CONST XML_PATH_LINES_PER_PAGE = 'catalog/sitemap/lines_perpage'; + + protected $_storeRootCategoryPath = ''; + protected $_storeRootCategoryLevel = 0; + protected $_total = 0; + protected $_from = 0; + protected $_to = 0; + protected $_currentPage = 0; + protected $_categoriesToPages = array(); + /** + * Initialize categories collection + * + * @return Mage_Catalog_Block_Seo_Sitemap_Category + */ + protected function _prepareLayout() + { + $helper = Mage::helper('catalog/category'); + /* @var $helper Mage_Catalog_Helper_Category */ + $parent = Mage::getModel('catalog/category') + ->setStoreId(Mage::app()->getStore()->getId()) + ->load(Mage::app()->getStore()->getRootCategoryId()); + $this->_storeRootCategoryPath = $parent->getPath(); + $this->_storeRootCategoryLevel = $parent->getLevel(); + $this->prepareCategoriesToPages(); + $collection = $this->getTreeCollection(); + $this->setCollection($collection); + return $this; + } + + /** + * Init pager + * + * @param string $pagerName + */ + public function bindPager($pagerName) + { + $pager = $this->getLayout()->getBlock($pagerName); + /* @var $pager Mage_Catalog_Block_Seo_Sitemap_Tree_Pager */ + if ($pager) { + $pager->setAvailableLimit(array(50 => 50)); + $pager->setTotalNum($this->_total); + $pager->setLastPageNum(count($this->_categoriesToPages)); + if (!$this->_currentPage) { + $this->_currentPage = $pager->getCurrentPage(); + $this->_prepareCollection(); + } + $pager->setFirstNum($this->_from); + $pager->setLastNum($this->_to); + $pager->setCollection($this->getCollection()); + $pager->setShowPerPage(false); + } + } + + /** + * Prepare array of categories separated into pages + * + * @return Mage_Catalog_Block_Seo_Sitemap_Tree_Category + */ + public function prepareCategoriesToPages() + { + $linesPerPage = Mage::getStoreConfig(self::XML_PATH_LINES_PER_PAGE); + $tmpCollection = Mage::getModel('catalog/category')->getCollection() + ->addIsActiveFilter() + ->addPathsFilter($this->_storeRootCategoryPath . '/') + ->addLevelFilter($this->_storeRootCategoryLevel + 1) + ->addOrderField('path'); + $count = 0; + $page = 1; + $categories = array(); + foreach ($tmpCollection as $item) { + $children = $item->getChildrenCount()+1; + $this->_total += $children; + if (($children+$count) >= $linesPerPage) { + $categories[$page][$item->getId()] = array( + 'path' => $item->getPath(), + 'children_count' => $this->_total + ); + $page++; + $count = 0; + continue; + } + $categories[$page][$item->getId()] = array( + 'path' => $item->getPath(), + 'children_count' => $this->_total + ); + $count += $children; + } + $this->_categoriesToPages = $categories; + return $this; + } + + /** + * Return collection of categories + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection + */ + public function getTreeCollection() + { + $collection = Mage::getModel('catalog/category')->getCollection() + ->addNameToResult() + ->addUrlRewriteToResult() + ->addIsActiveFilter() + ->addOrderField('path'); + return $collection; + } + + /** + * Prepare collection filtered by paths + * + * @return Mage_Catalog_Block_Seo_Sitemap_Tree_Category + */ + protected function _prepareCollection() + { + $_to = 0; + $pathFilter = array(); + if (isset($this->_categoriesToPages[$this->_currentPage])) { + foreach ($this->_categoriesToPages[$this->_currentPage] as $_categoryId=>$_categoryInfo) { + $pathFilter[] = $_categoryInfo['path']; + $_to = max($_to, $_categoryInfo['children_count']); + } + } + if (empty($pathFilter)) { + $pathFilter = $this->_storeRootCategoryPath . '/'; + } + $collection = $this->getCollection(); + $collection->addPathsFilter($pathFilter); + $this->_to = $_to; + $this->_from = $_to - $collection->count(); + return $this; + } + + /** + * Return level of indent + * + * @param Mage_Catalog_Model_Category $item + * @param integer $delta + * @return integer + */ + public function getLevel($item, $delta = 1) + { + return (int) ($item->getLevel() - $this->_storeRootCategoryLevel - 1) * $delta; + } + +} diff --git a/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Pager.php b/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Pager.php new file mode 100644 index 0000000000..137463f145 --- /dev/null +++ b/app/code/core/Mage/Catalog/Block/Seo/Sitemap/Tree/Pager.php @@ -0,0 +1,180 @@ + + * + * @todo separate order, mode and pager + */ +class Mage_Catalog_Block_Seo_Sitemap_Tree_Pager extends Mage_Page_Block_Html_Pager +{ + protected $_showPerPage = false; + protected $lastPageNumber = 1; + protected $_totalNum = 0; + protected $_firstNum = 0; + protected $_lastNum = 1; + + public function getCurrentPage($displacement = 0) + { + if ($page = (int) $this->getRequest()->getParam($this->getPageVarName()) + $displacement) { + if ($page > $this->getLastPageNum()) { + return $this->getLastPageNum(); + } + return $page; + } + return 1; + } + + public function getLimit() + { + $limits = $this->getAvailableLimit(); +// if ($limit = $this->getRequest()->getParam($this->getLimitVarName())) { +// if (isset($limits[$limit])) { +// return $limit; +// } +// } + $limits = array_keys($limits); + return $limits[0]; + } + + public function setCollection($collection) + { + $this->_collection = $collection; +// ->setCurPage($this->getCurrentPage()); + // If not int - then not limit +// if ((int) $this->getLimit()) { +// $this->_collection->setPageSize($this->getLimit()); +// } + + return $this; + } + + /** + * @return Mage_Core_Model_Mysql4_Collection_Abstract + */ + public function getCollection() + { + return $this->_collection; + } + + public function getFirstNum() + { + return $this->_firstNum + 1; + } + + public function setFirstNum($firstNum) + { + $this->_firstNum = $firstNum; + return $this; + } + + public function getLastNum() + { + return $this->_lastNum; + } + + public function setLastNum($lastNum) + { + $this->_lastNum = $lastNum; + return $this; + } + + public function getTotalNum() + { + return $this->_totalNum; + } + + public function setTotalNum($totalNum) + { + $this->_totalNum = $totalNum; + return $this; + } + + public function isFirstPage() + { + return $this->getCurrentPage() == 1; + } + + public function getLastPageNum() + { + return $this->_lastPageNumber; + } + + public function setLastPageNum($lastPageNum) + { + $this->_lastPageNumber = $lastPageNum; + return $this; + } + + public function isLastPage() + { + return $this->getCurrentPage() >= $this->getLastPageNum(); + } + + public function getPages() + { + $pages = array(); + if ($this->getLastPageNum() <= $this->_displayPages) { + $pages = range(1, $this->getLastPageNum()); + } else { + $half = ceil($this->_displayPages / 2); + if ($this->getCurrentPage() >= $half && $this->getCurrentPage() <= $this->getLastPageNum() - $half) { + $start = ($this->getCurrentPage() - $half) + 1; + $finish = ($start + $this->_displayPages) - 1; + } elseif ($this->getCurrentPage() < $half) { + $start = 1; + $finish = $this->_displayPages; + } elseif ($this->getCurrentPage() > ($this->getLastPageNum() - $half)) { + $finish = $this->getLastPageNum(); + $start = $finish - $this->_displayPages + 1; + } + $pages = range($start, $finish); + } + + return $pages; + } + + public function getPreviousPageUrl() + { + return $this->getPageUrl($this->getCurrentPage(-1)); + } + + public function getNextPageUrl() + { + return $this->getPageUrl($this->getCurrentPage(+1)); + } + + public function getLastPageUrl() + { + return $this->getPageUrl($this->getLastPageNum()); + } + +} + diff --git a/app/code/core/Mage/Catalog/Helper/Category.php b/app/code/core/Mage/Catalog/Helper/Category.php index 41de2af49d..abedbf8031 100644 --- a/app/code/core/Mage/Catalog/Helper/Category.php +++ b/app/code/core/Mage/Catalog/Helper/Category.php @@ -66,20 +66,7 @@ public function getStoreCategories($sorted=false, $asCollection=false, $toLoad=t $recursionLevel = max(0, (int) Mage::app()->getStore()->getConfig('catalog/navigation/max_depth')); - $tree = $category->getTreeModel(); - /* @var $tree Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Tree */ - - $nodes = $tree->loadNode($parent) - ->loadChildren($recursionLevel) - ->getChildren(); - - $tree->addCollectionData(null, $sorted, $parent, $toLoad, true); - - if ($asCollection) { - return $tree->getCollection(); - } else { - return $nodes; - } + return $category->getCategories($parent, $recursionLevel, $sorted, $asCollection, $toLoad); } /** @@ -117,13 +104,7 @@ public function canShow($category) if (!$category->getIsActive()) { return false; } - - $tree = Mage::getResourceSingleton('catalog/category_tree'); - /* @var $tree Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Tree */ - $tree->load(); - - $children = $tree->getChildren(Mage::app()->getStore()->getRootCategoryId(), true); - if (!in_array($category->getId(), $children)) { + if (!$category->isInRootCategoryList()) { return false; } diff --git a/app/code/core/Mage/Catalog/Helper/Category/Flat.php b/app/code/core/Mage/Catalog/Helper/Category/Flat.php new file mode 100644 index 0000000000..1995bd37b6 --- /dev/null +++ b/app/code/core/Mage/Catalog/Helper/Category/Flat.php @@ -0,0 +1,64 @@ + + */ +class Mage_Catalog_Helper_Category_Flat extends Mage_Core_Helper_Abstract +{ + const XML_PATH_IS_ENABLED_FLAT_CATALOG_CATEGORY = 'catalog/frontend/flat_catalog_category'; + + /** + * Return true if flat catalog is enabled, rebuileded and is not Admin + * + * @param boolean $skipAdmin + * @return boolean + */ + public function isEnabled($skipAdminCheck = false) + { + $flatFlag = Mage::getStoreConfigFlag(self::XML_PATH_IS_ENABLED_FLAT_CATALOG_CATEGORY); + $isFront = !Mage::app()->getStore()->isAdmin(); + if ($skipAdminCheck === true) { + $isFront = true; + } + + return (boolean) $flatFlag && $isFront; + } + + /** + * Return true if catalog category flat data rebuilt + * + * @return boolean + */ + public function isRebuilt() + { + return Mage::getResourceSingleton('catalog/category_flat')->isRebuilt(); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Helper/Data.php b/app/code/core/Mage/Catalog/Helper/Data.php index 040e57048e..e0bae9ca95 100644 --- a/app/code/core/Mage/Catalog/Helper/Data.php +++ b/app/code/core/Mage/Catalog/Helper/Data.php @@ -33,28 +33,26 @@ class Mage_Catalog_Helper_Data extends Mage_Core_Helper_Abstract { protected $_categoryPath; + /** + * Return current category path or get it from current category + * and creating array of categories|product paths for breadcrumbs + * + * @return string + */ public function getBreadcrumbPath() { if (!$this->_categoryPath) { $path = array(); - if ($this->getCategory()) { - $pathInStore = $this->getCategory()->getPathInStore(); + if ($category = $this->getCategory()) { + $pathInStore = $category->getPathInStore(); $pathIds = array_reverse(explode(',', $pathInStore)); - $categories = Mage::getResourceModel('catalog/category_collection') - ->setStore(Mage::app()->getStore()) - ->addAttributeToSelect('name') - ->addAttributeToSelect('url_key') - ->addFieldToFilter('entity_id', array('in'=>$pathIds)) - ->addFieldToFilter('is_active', 1) - ->load() - ->getItems(); + $categories = $category->getParentCategories(); // add category path breadcrumb foreach ($pathIds as $categoryId) { if (isset($categories[$categoryId]) && $categories[$categoryId]->getName()) { - $categories[$categoryId]->setStoreId(Mage::app()->getStore()->getId()); $path['category'.$categoryId] = array( 'label' => $categories[$categoryId]->getName(), 'link' => $this->_isCategoryLink($categoryId) ? $categories[$categoryId]->getUrl() : '' @@ -83,6 +81,11 @@ protected function _isCategoryLink($categoryId) return false; } + /** + * Return current category + * + * @return Mage_Catalog_Model_Category + */ public function getCategory() { return Mage::registry('current_category'); diff --git a/app/code/core/Mage/Catalog/Helper/Map.php b/app/code/core/Mage/Catalog/Helper/Map.php index d4fb8831ef..cf6dcb58e9 100644 --- a/app/code/core/Mage/Catalog/Helper/Map.php +++ b/app/code/core/Mage/Catalog/Helper/Map.php @@ -29,15 +29,26 @@ */ class Mage_Catalog_Helper_Map extends Mage_Core_Helper_Abstract { + CONST XML_PATH_USE_TREE_MODE = 'catalog/sitemap/tree_mode'; public function getCategoryUrl() - { - return $this->_getUrl('catalog/seo_sitemap/category'); - } + { + return $this->_getUrl('catalog/seo_sitemap/category'); + } - public function getProductUrl() - { - return $this->_getUrl('catalog/seo_sitemap/product'); - } + public function getProductUrl() + { + return $this->_getUrl('catalog/seo_sitemap/product'); + } + + /** + * Return true if category tree mode enabled + * + * @return boolean + */ + public function getIsUseCategoryTreeMode() + { + return (bool) Mage::getStoreConfigFlag(self::XML_PATH_USE_TREE_MODE); + } } diff --git a/app/code/core/Mage/Catalog/Helper/Product/Compare.php b/app/code/core/Mage/Catalog/Helper/Product/Compare.php index 64b65d39d1..79729d9bc6 100644 --- a/app/code/core/Mage/Catalog/Helper/Product/Compare.php +++ b/app/code/core/Mage/Catalog/Helper/Product/Compare.php @@ -20,19 +20,40 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ + /** - * Product compare helper + * Catalog Product Compare Helper * - * @author Magento Core Team + * @category Mage + * @package Mage_Catalog + * @author Magento Core Team */ class Mage_Catalog_Helper_Product_Compare extends Mage_Core_Helper_Url { + /** + * Product Compare Items Collection + * + * @var Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Compare_Item_Collection + */ protected $_itemCollection; - protected $_hasItems = null; + + /** + * Product Comapare Items Collection has items flag + * + * @var bool + */ + protected $_hasItems; + + /** + * Allow used Flat catalog product for product compare items collection + * + * @var bool + */ + protected $_allowUsedFlat = true; /** * Retrieve compare list url @@ -48,12 +69,26 @@ public function getListUrl() $params = array( 'items'=>implode(',', $itemIds), - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $this->getCurrentBase64Url() + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl() ); return $this->_getUrl('catalog/product_compare', $params); } + /** + * Get parameters used for build add product to compare list urls + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + protected function _getUrlParams($product) + { + return array( + 'product' => $product->getId(), + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl() + ); + } + /** * Retrieve url for adding product to conpare list * @@ -62,15 +97,7 @@ public function getListUrl() */ public function getAddUrl($product) { -// if ($product->isSuper()) { -// return false; -// } - - $params = array( - 'product'=>$product->getId(), - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $this->getCurrentBase64Url() - ); - return $this->_getUrl('catalog/product_compare/add', $params); + return $this->_getUrl('catalog/product_compare/add', $this->_getUrlParams($product)); } /** @@ -85,7 +112,7 @@ public function getAddToWishlistUrl($product) $params = array( 'product'=>$product->getId(), - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $beforeCompareUrl + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl($beforeCompareUrl) ); return $this->_getUrl('wishlist/index/add', $params); @@ -102,7 +129,7 @@ public function getAddToCartUrl($product) $beforeCompareUrl = $this->urlEncode(Mage::getSingleton('catalog/session')->getBeforeCompareUrl()); $params = array( 'product'=>$product->getId(), - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $beforeCompareUrl + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl($beforeCompareUrl) ); return $this->_getUrl('checkout/cart/add', $params); @@ -118,7 +145,7 @@ public function getRemoveUrl($item) { $params = array( 'product'=>$item->getId(), - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $this->getCurrentBase64Url() + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl() ); return $this->_getUrl('catalog/product_compare/remove', $params); } @@ -131,7 +158,7 @@ public function getRemoveUrl($item) public function getClearListUrl() { $params = array( - Mage_Core_Controller_Front_Action::PARAM_NAME_BASE64_URL => $this->getCurrentBase64Url() + Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl() ); return $this->_getUrl('catalog/product_compare/clear', $params); } @@ -165,6 +192,36 @@ public function getItemCollection() return $this->_itemCollection; } + /** + * Calculate cache product compare collection + * + * @return Mage_Catalog_Helper_Product_Compare + */ + public function calculate() + { + if (!Mage::getSingleton('customer/session')->isLoggedIn() + and !Mage::getSingleton('log/visitor')->hasCatalogCompareItemsCount() + ) { + Mage::getSingleton('log/visitor')->setCatalogCompareItemsCount(0); + return $this; + } + + $itemCollection = Mage::getResourceModel('catalog/product_compare_item_collection'); + /* @var $itemCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Compare_Item_Collection */ + $itemCollection->setStoreId(Mage::app()->getStore()->getId()); + if (Mage::getSingleton('customer/session')->isLoggedIn()) { + $itemCollection->setCustomerId(Mage::getSingleton('customer/session')->getCustomerId()); + } + else { + $itemCollection->setVisitorId(Mage::getSingleton('log/visitor')->getId()); + } + Mage::getSingleton('catalog/product_visibility') + ->addVisibleInSiteFilterToCollection($itemCollection); + + Mage::getSingleton('log/visitor')->setCatalogCompareItemsCount($itemCollection->getSize()); + return $this; + } + /** * Retrieve count of items in compare list * @@ -172,11 +229,41 @@ public function getItemCollection() */ public function getItemCount() { - return $this->getItemCollection()->getSize(); + if (is_null(Mage::getSingleton('log/visitor')->getCatalogCompareItemsCount())) { + $this->calculate(); + } + return Mage::getSingleton('log/visitor')->getCatalogCompareItemsCount(); } + /** + * Check has items + * + * @return bool + */ public function hasItems() { - return $this->getItemCollection()->getSize() > 0; + return $this->getItemCount() > 0; + } + + /** + * Set is allow used flat (for collection) + * + * @param bool $flag + * @return Mage_Catalog_Helper_Product_Compare + */ + public function setAllowUsedFlat($flag) + { + $this->_allowUsedFlat = (bool)$flag; + return $this; + } + + /** + * Retrieve is allow used flat (for collection) + * + * @return bool + */ + public function getAllowUsedFlat() + { + return $this->_allowUsedFlat; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Helper/Product/Flat.php b/app/code/core/Mage/Catalog/Helper/Product/Flat.php new file mode 100644 index 0000000000..e96a4ee2de --- /dev/null +++ b/app/code/core/Mage/Catalog/Helper/Product/Flat.php @@ -0,0 +1,83 @@ + + */ +class Mage_Catalog_Helper_Product_Flat extends Mage_Core_Helper_Abstract +{ + const XML_PATH_USE_PRODUCT_FLAT = 'catalog/frontend/flat_catalog_product'; + + /** + * Catalog Product Flat Flag object + * + * @var Mage_Catalog_Model_Product_Flat_Flag + */ + protected $_flagObject; + + /** + * Retrieve Catalog Product Flat Flag object + * + * @return Mage_Catalog_Model_Product_Flat_Flag + */ + public function getFlag() + { + if (is_null($this->_flagObject)) { + $this->_flagObject = Mage::getSingleton('catalog/product_flat_flag') + ->loadSelf(); + } + return $this->_flagObject; + } + + /** + * Check is builded Catalog Product Flat Data + * + * @return bool + */ + public function isBuilt() + { + return $this->getFlag()->getIsBuilt(); + } + + /** + * Check is enable catalog product for store + * + * @param mixed $store + * @return bool + */ + public function isEnabled($store = null) + { + if (Mage::app()->getStore($store)->isAdmin()) { + return false; + } + return Mage::getStoreConfigFlag(self::XML_PATH_USE_PRODUCT_FLAT, $store); + } +} diff --git a/app/code/core/Mage/Catalog/Helper/Product/Options.php b/app/code/core/Mage/Catalog/Helper/Product/Options.php new file mode 100644 index 0000000000..9ea5538159 --- /dev/null +++ b/app/code/core/Mage/Catalog/Helper/Product/Options.php @@ -0,0 +1,50 @@ + + */ +class Mage_Catalog_Helper_Product_Options extends Mage_Core_Helper_Abstract +{ + /** + * Simplest way to check if we format our option value using HTML + * + * @param string $optionValue + * @return boolean + */ + public function isHtmlFormattedOptionValue($optionValue) + { + if (is_string($optionValue) && strlen($optionValue) != strlen(strip_tags($optionValue))) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Api/Resource.php b/app/code/core/Mage/Catalog/Model/Api/Resource.php index 0004a623dc..9532c6997b 100644 --- a/app/code/core/Mage/Catalog/Model/Api/Resource.php +++ b/app/code/core/Mage/Catalog/Model/Api/Resource.php @@ -1,144 +1,144 @@ - - */ -class Mage_Catalog_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract -{ - /** - * Default ignored attribute codes - * - * @var array - */ - protected $_ignoredAttributeCodes = array('entity_id', 'attribute_set_id', 'entity_type_id'); - - /** - * Default ignored attribute types - * - * @var array - */ - protected $_ignoredAttributeTypes = array(); - - /** - * Field name in session for saving store id - * @var string - */ - protected $_storeIdSessionField = 'store_id'; - - /** - * Check is attribute allowed - * - * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute - * @param array $attributes - * @return boolean - */ - protected function _isAllowedAttribute($attribute, $attributes = null) - { - if (is_array($attributes) - && !( in_array($attribute->getAttributeCode(), $attributes) - || in_array($attribute->getAttributeId(), $attributes))) { - return false; - } - - return !in_array($attribute->getFrontendInput(), $this->_ignoredAttributeTypes) - && !in_array($attribute->getAttributeCode(), $this->_ignoredAttributeCodes); - } - - /** - * Retrives store id from store code, if no store id specified, - * it use seted session or admin store - * - * @param string|int $store - * @return int - */ - protected function _getStoreId($store = null) - { - if (is_null($store)) { - $store = ($this->_getSession()->hasData($this->_storeIdSessionField) - ? $this->_getSession()->getData($this->_storeIdSessionField) : 0); - } - - try { - $storeId = Mage::app()->getStore($store)->getId(); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - return $storeId; - } - - /** - * Return loaded product instance - * - * @param int|string $productId (SKU or ID) - * @param int|string $store - * @return object Mage_Catalog_Model_Product instance - */ - protected function _getProduct ($productId, $store = null) - { - $product = Mage::getModel('catalog/product'); - - /* @var $product Mage_Catalog_Model_Product */ - - if (is_string($productId)) { - $idBySku = $product->getIdBySku($productId); - if ($idBySku) { - $productId = $idBySku; - } - } - if ($store !== null) { - $product->setStoreId($this->_getStoreId($store)); - } - $product->load($productId); - return $product; - } - - /** - * Set current store for catalog. - * - * @param string|int $store - * @return int - */ - public function currentStore($store=null) - { - if (!is_null($store)) { - try { - $storeId = Mage::app()->getStore($store)->getId(); - } catch (Mage_Core_Model_Store_Exception $e) { - $this->_fault('store_not_exists'); - } - - $this->_getSession()->setData($this->_storeIdSessionField, $storeId); - } - - return $this->_getStoreId(); - } + + */ +class Mage_Catalog_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract +{ + /** + * Default ignored attribute codes + * + * @var array + */ + protected $_ignoredAttributeCodes = array('entity_id', 'attribute_set_id', 'entity_type_id'); + + /** + * Default ignored attribute types + * + * @var array + */ + protected $_ignoredAttributeTypes = array(); + + /** + * Field name in session for saving store id + * @var string + */ + protected $_storeIdSessionField = 'store_id'; + + /** + * Check is attribute allowed + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param array $attributes + * @return boolean + */ + protected function _isAllowedAttribute($attribute, $attributes = null) + { + if (is_array($attributes) + && !( in_array($attribute->getAttributeCode(), $attributes) + || in_array($attribute->getAttributeId(), $attributes))) { + return false; + } + + return !in_array($attribute->getFrontendInput(), $this->_ignoredAttributeTypes) + && !in_array($attribute->getAttributeCode(), $this->_ignoredAttributeCodes); + } + + /** + * Retrives store id from store code, if no store id specified, + * it use seted session or admin store + * + * @param string|int $store + * @return int + */ + protected function _getStoreId($store = null) + { + if (is_null($store)) { + $store = ($this->_getSession()->hasData($this->_storeIdSessionField) + ? $this->_getSession()->getData($this->_storeIdSessionField) : 0); + } + + try { + $storeId = Mage::app()->getStore($store)->getId(); + } catch (Mage_Core_Model_Store_Exception $e) { + $this->_fault('store_not_exists'); + } + + return $storeId; + } + + /** + * Return loaded product instance + * + * @param int|string $productId (SKU or ID) + * @param int|string $store + * @return Mage_Catalog_Model_Product + */ + protected function _getProduct ($productId, $store = null) + { + $product = Mage::getModel('catalog/product'); + + /* @var $product Mage_Catalog_Model_Product */ + + if (is_string($productId)) { + $idBySku = $product->getIdBySku($productId); + if ($idBySku) { + $productId = $idBySku; + } + } + if ($store !== null) { + $product->setStoreId($this->_getStoreId($store)); + } + $product->load($productId); + return $product; + } + + /** + * Set current store for catalog. + * + * @param string|int $store + * @return int + */ + public function currentStore($store=null) + { + if (!is_null($store)) { + try { + $storeId = Mage::app()->getStore($store)->getId(); + } catch (Mage_Core_Model_Store_Exception $e) { + $this->_fault('store_not_exists'); + } + + $this->_getSession()->setData($this->_storeIdSessionField, $storeId); + } + + return $this->_getStoreId(); + } } // Class Mage_Catalog_Model_Api_Resource End \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Category.php b/app/code/core/Mage/Catalog/Model/Category.php index f3741613b3..d9596b968b 100644 --- a/app/code/core/Mage/Catalog/Model/Category.php +++ b/app/code/core/Mage/Catalog/Model/Category.php @@ -68,7 +68,11 @@ class Mage_Catalog_Model_Category extends Mage_Catalog_Model_Abstract protected function _construct() { - $this->_init('catalog/category'); + if (Mage::helper('catalog/category_flat')->isEnabled()) { + $this->_init('catalog/category_flat'); + } else { + $this->_init('catalog/category'); + } } /** @@ -230,9 +234,35 @@ public function getLayoutUpdateHandle() return $layout; } + /** + * Return store id. + * + * If store id is underfined for category return current active store id + * + * @return integer + */ public function getStoreId() { - return $this->_getData('store_id'); + if ($this->hasData('store_id')) { + return $this->_getData('store_id'); + } + return Mage::app()->getStore()->getId(); + } + + /** + * Set store id + * + * @param integer $storeId + * @return Mage_Catalog_Model_Category + */ + public function setStoreId($storeId) + { + if (!is_numeric($storeId)) { + $storeId = Mage::app($storeId)->getStore()->getId(); + } + $this->setData('store_id', $storeId); + $this->getResource()->setStoreId($storeId); + return $this; } /** @@ -385,6 +415,15 @@ private function _getAttribute($attributeCode) */ public function getAllChildren($asArray = false) { + $children = $this->getResource()->getAllChildren($this); + if ($asArray) { + return $children; + } else { + return implode(',', $children); + } + + + $this->getTreeModelInstance()->load(); $children = $this->getTreeModelInstance()->getChildren($this->getId()); @@ -403,8 +442,7 @@ public function getAllChildren($asArray = false) public function getChildren() { - $this->getTreeModelInstance()->load(); - return implode(',', $this->getTreeModelInstance()->getChildren($this->getId(), false)); + return implode(',', $this->getResource()->getChildren($this, false)); } public function getPathInStore() @@ -509,4 +547,103 @@ public function getProductCount() } return $this->getData('product_count'); } + + /** + * Enter description here... + * + * @param unknown_type $sorted + * @param unknown_type $asCollection + * @param unknown_type $toLoad + * @return unknown_type + */ + public function getCategories($parent, $recursionLevel = 0, $sorted=false, $asCollection=false, $toLoad=true) + { + $categories = $this->getResource() + ->getCategories($parent, $recursionLevel, $sorted, $asCollection, $toLoad); + return $categories; + } + + /** + * Return parent categories of current category + * + * @return array + */ + public function getParentCategories() + { + return $this->getResource()->getParentCategories($this); + } + + /** + * Retuen children categories of current category + * + * @return array + */ + public function getChildrenCategories() + { + return $this->getResource()->getChildrenCategories($this); + } + + public function isInRootCategoryList() + { + return $this->getResource()->isInRootCategoryList($this); + } + + /** + * Retrieve Available int Product Listing sort by + * + * @return null|array + */ + public function getAvailableSortBy() + { + $available = $this->getData('available_sort_by'); + if ($available && !is_array($available)) { + $available = split(',', $available); + } + return $available; + } + + /** + * Retrieve Available Product Listing Sort By + * code as key, value - name + * + * @return array + */ + public function getAvailableSortByOptions() { + $availableSortBy = array(); + $defaultSortBy = Mage::getSingleton('catalog/config') + ->getAttributeUsedForSortByArray(); + if ($this->getAvailableSortBy()) { + foreach ($this->getAvailableSortBy() as $sortBy) { + if (isset($defaultSortBy[$sortBy])) { + $availableSortBy[$sortBy] = $defaultSortBy[$sortBy]; + } + } + } + + if (!$availableSortBy) { + $availableSortBy = $defaultSortBy; + } + + return $availableSortBy; + } + + /** + * Retrieve Product Listing Default Sort By + * + * @return string + */ + public function getDefaultSortBy() { + if (!$sortBy = $this->getData('default_sort_by')) { + $sortBy = Mage::getSingleton('catalog/config') + ->getProductListDefaultSortBy($this->getStoreId()); + } + $available = $this->getAvailableSortByOptions(); + if (!isset($available[$sortBy])) { + $sortBy = array_keys($available); + $sortBy = $sortBy[0]; + } + + return $sortBy; + } + } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Category/Api/V2.php b/app/code/core/Mage/Catalog/Model/Category/Api/V2.php new file mode 100644 index 0000000000..9f28b45751 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Category/Api/V2.php @@ -0,0 +1,139 @@ + + */ +class Mage_Catalog_Model_Category_Api_V2 extends Mage_Catalog_Model_Category_Api +{ + /** + * Retrieve category data + * + * @param int $categoryId + * @param string|int $store + * @param array $attributes + * @return array + */ + public function info($categoryId, $store = null, $attributes = null) + { + $category = $this->_initCategory($categoryId, $store); + + // Basic category data + $result = array(); + $result['category_id'] = $category->getId(); + + $result['is_active'] = $category->getIsActive(); + $result['position'] = $category->getPosition(); + $result['level'] = $category->getLevel(); + + foreach ($category->getAttributes() as $attribute) { + if ($this->_isAllowedAttribute($attribute, $attributes)) { + $result[$attribute->getAttributeCode()] = $category->getData($attribute->getAttributeCode()); + } + } + $result['parent_id'] = $category->getParentId(); + $result['children'] = $category->getChildren(); + $result['all_children'] = $category->getAllChildren(); + + return $result; + } + + /** + * Create new category + * + * @param int $parentId + * @param array $categoryData + * @return int + */ + public function create($parentId, $categoryData, $store = null) + { + $parent_category = $this->_initCategory($parentId); + + $category = Mage::getModel('catalog/category') + ->setStoreId($this->_getStoreId($store)); + + $category->addData(array('path'=>implode('/',$parent_category->getPathIds()))); + + $category ->setAttributeSetId($category->getDefaultAttributeSetId()); + /* @var $category Mage_Catalog_Model_Category */ + + foreach ($category->getAttributes() as $attribute) { + $_attrCode = $attribute->getAttributeCode(); + if ($this->_isAllowedAttribute($attribute) + && isset($categoryData->$_attrCode)) { + $category->setData( + $attribute->getAttributeCode(), + $categoryData->$_attrCode + ); + } + } + $category->setParentId($parent_category->getId()); + try { + $category->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $category->getId(); + } + + /** + * Update category data + * + * @param int $categoryId + * @param array $categoryData + * @param string|int $store + * @return boolean + */ + public function update($categoryId, $categoryData, $store = null) + { + $category = $this->_initCategory($categoryId, $store); + + foreach ($category->getAttributes() as $attribute) { + $_attrCode = $attribute->getAttributeCode(); + if ($this->_isAllowedAttribute($attribute) + && isset($categoryData->$_attrCode)) { + $category->setData( + $attribute->getAttributeCode(), + $categoryData->$_attrCode + ); + } + } + + try { + $category->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return true; + } + +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php new file mode 100644 index 0000000000..fcbb12cf9b --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Catalog_Model_Category_Attribute_Api_V2 extends Mage_Catalog_Model_Category_Attribute_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Backend/Sortby.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Backend/Sortby.php new file mode 100644 index 0000000000..d453a83a5f --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Category/Attribute/Backend/Sortby.php @@ -0,0 +1,93 @@ + + */ +class Mage_Catalog_Model_Category_Attribute_Backend_Sortby + extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract +{ + /** + * Validate process + * + * @param Varien_Object $object + * @return bool + */ + public function validate($object) + { + if (!parent::validate($object)) { + return false; + } + + $attributeCode = $this->getAttribute()->getName(); + if ($attributeCode == 'default_sort_by') { + if ($available = $object->getData('available_sort_by')) { + if (!is_array($available)) { + $available = split(',', $available); + } + if (!in_array($object->getData($attributeCode), $available)) { + Mage::throwException(Mage::helper('eav')->__('Default Product Listing Sort by not exists on Available Product Listing Sort by')); + } + } + } + + return true; + } + + /** + * Before Attribute Save Process + * + * @param Varien_Object $object + * @return Mage_Catalog_Model_Category_Attribute_Backend_Sortby + */ + public function beforeSave($object) { + $attributeCode = $this->getAttribute()->getName(); + if ($attributeCode == 'available_sort_by') { + $data = $object->getData($attributeCode); + if (!is_array($data)) { + $data = array(); + } + $object->setData($attributeCode, join(',', $data)); + } + return $this; + } + + public function afterLoad($object) { + $attributeCode = $this->getAttribute()->getName(); + if ($attributeCode == 'available_sort_by') { + $data = $object->getData($attributeCode); + if ($data) { + $object->setData($attributeCode, split(',', $data)); + } + } + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Source/Sortby.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Source/Sortby.php new file mode 100644 index 0000000000..846b24a0b6 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Category/Attribute/Source/Sortby.php @@ -0,0 +1,68 @@ + + */ +class Mage_Catalog_Model_Category_Attribute_Source_Sortby + extends Mage_Eav_Model_Entity_Attribute_Source_Abstract +{ + /** + * Retrieve Catalog Config Singleton + * + * @return Mage_Catalog_Model_Config + */ + protected function _getCatalogConfig() { + return Mage::getSingleton('catalog/config'); + } + + /** + * Retrieve All options + * + * @return array + */ + public function getAllOptions() + { + if (is_null($this->_options)) { + $this->_options = array(array( + 'label' => Mage::helper('catalog')->__('Best Value'), + 'value' => 'position' + )); + foreach ($this->_getCatalogConfig()->getAttributesUsedForSortBy() as $attribute) { + $this->_options[] = array( + 'label' => Mage::helper('catalog')->__($attribute['frontend_label']), + 'value' => $attribute['attribute_code'] + ); + } + } + return $this->_options; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Config.php b/app/code/core/Mage/Catalog/Model/Config.php index 24fb4e86ae..7718a739d2 100644 --- a/app/code/core/Mage/Catalog/Model/Config.php +++ b/app/code/core/Mage/Catalog/Model/Config.php @@ -27,6 +27,8 @@ class Mage_Catalog_Model_Config extends Mage_Eav_Model_Config { + const XML_PATH_LIST_DEFAULT_SORT_BY = 'catalog/frontend/default_sort_by'; + protected $_attributeSetsById; protected $_attributeSetsByName; @@ -35,8 +37,38 @@ class Mage_Catalog_Model_Config extends Mage_Eav_Model_Config protected $_productTypesById; + /** + * Array of attributes codes needed for product load + * + * @var array + */ + protected $_productAttributes; + + /** + * Product Attributes used in product listing + * + * @var array + */ + protected $_usedInProductListing; + + /** + * Product Attributes For Sort By + * + * @var array + */ + protected $_usedForSortBy; + const XML_PATH_PRODUCT_COLLECTION_ATTRIBUTES = 'frontend/product/collection/attributes'; + /** + * Initialize resource model + * + */ + protected function _construct() + { + $this->_init('catalog/config'); + } + public function loadAttributeSets() { if ($this->_attributeSetsById) { @@ -191,13 +223,96 @@ public function getSourceOptionId($source, $value) } /** - * Load product attributes from config file + * Load Product attributes * * @return array */ public function getProductAttributes() { - $attributes = Mage::getConfig()->getNode(self::XML_PATH_PRODUCT_COLLECTION_ATTRIBUTES)->asArray(); - return array_keys($attributes); + if (is_null($this->_productAttributes)) { + $this->_productAttributes = array(); + foreach ($this->getAttributesUsedInProductListing() as $attribute) { + $this->_productAttributes[] = $attribute['attribute_code']; + } + } + return $this->_productAttributes; + } + + /** + * Retrieve Product Collection Attributes from XML config file + * Used only for install/upgrade + * + * @return array + */ + public function getProductCollectionAttributes() { + $attributes = Mage::getConfig() + ->getNode(self::XML_PATH_PRODUCT_COLLECTION_ATTRIBUTES) + ->asArray(); + return array_keys($attributes);; + } + + /** + * Retrieve resource model + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Config + */ + protected function _getResource() + { + return Mage::getResourceModel('catalog/config'); + } + + /** + * Retrieve Attributes used in product listing + * + * @return array + */ + public function getAttributesUsedInProductListing() { + if (is_null($this->_usedInProductListing)) { + $this->_usedInProductListing = $this->_getResource() + ->getAttributesUsedInListing(); + } + return $this->_usedInProductListing; + } + + /** + * Retrieve Attributes array used for sort by + * + * @return array + */ + public function getAttributesUsedForSortBy() { + if (is_null($this->_usedForSortBy)) { + $this->_usedForSortBy = $this->_getResource() + ->getAttributesUsedForSortBy(); + } + return $this->_usedForSortBy; } + + /** + * Retrieve Attributes Used for Sort by as array + * key = code, value = name + * + * @return array + */ + public function getAttributeUsedForSortByArray() + { + $options = array( + 'position' => Mage::helper('catalog')->__('Position') + ); + foreach ($this->getAttributesUsedForSortBy() as $attribute) { + $options[$attribute['attribute_code']] = Mage::helper('catalog')->__($attribute['frontend_label']); + } + + return $options; + } + + /** + * Retrieve Product List Default Sort By + * + * @param mixed $store + * @return string + */ + public function getProductListDefaultSortBy($store = null) { + return Mage::getStoreConfig(self::XML_PATH_LIST_DEFAULT_SORT_BY, $store); + } + } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php b/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php index 9db009e1ba..854fb5dfd4 100644 --- a/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php +++ b/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php @@ -203,9 +203,6 @@ public function getProductAttributeSets() /** * Init stores - * - * @param none - * @return void */ protected function _initStores () { @@ -226,6 +223,13 @@ protected function _initStores () public function getStoreByCode($store) { $this->_initStores(); + /** + * In single store mode all data should be saved as default + */ + if (Mage::app()->isSingleStoreMode()) { + return Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID); + } + if (isset($this->_stores[$store])) { return $this->_stores[$store]; } @@ -241,6 +245,13 @@ public function getStoreByCode($store) public function getStoreById($id) { $this->_initStores(); + /** + * In single store mode all data should be saved as default + */ + if (Mage::app()->isSingleStoreMode()) { + return Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID); + } + if (isset($this->_storesIdCode[$id])) { return $this->getStoreByCode($this->_storesIdCode[$id]); } diff --git a/app/code/core/Mage/Catalog/Model/Design.php b/app/code/core/Mage/Catalog/Model/Design.php index 23f4bca1a6..7432113cc4 100644 --- a/app/code/core/Mage/Catalog/Model/Design.php +++ b/app/code/core/Mage/Catalog/Model/Design.php @@ -31,6 +31,39 @@ class Mage_Catalog_Model_Design extends Mage_Core_Model_Abstract const APPLY_FOR_CATEGORY = 2; public function applyDesign($object, $calledFrom = 0) + { + switch ($calledFrom) { + case self::APPLY_FOR_PRODUCT: + $calledFrom = 3; + break; + + case self::APPLY_FOR_CATEGORY: + $calledFrom = 4; + break; + } + if (Mage::helper('catalog/category_flat')->isEnabled()) { + $this->_applyDesign($object, $calledFrom); + } else { + $this->_applyDesignRecursively($object, $calledFrom); + } + + return $this; + } + + private function _apply($package, $theme) + { + Mage::getSingleton('core/design_package') + ->setPackageName($package) + ->setTheme($theme); + } + + /** + * Apply design recursively + * + * @param Varien_Object $object + * @param integer $calledFrom + */ + protected function _applyDesignRecursively($object, $calledFrom = 0) { $error = 0; $package = ''; @@ -46,14 +79,6 @@ public function applyDesign($object, $calledFrom = 0) } switch ($calledFrom) { - case self::APPLY_FOR_PRODUCT: - $calledFrom = 3; - break; - - case self::APPLY_FOR_CATEGORY: - $calledFrom = 4; - break; - case 3: if ($application && $application != 1 && $application != 3) $error = 1; @@ -98,14 +123,94 @@ public function applyDesign($object, $calledFrom = 0) } if ($category && $category->getId()){ - $this->applyDesign($category, $calledFrom); + $this->_applyDesignRecursively($category, $calledFrom); } } - private function _apply($package, $theme) + /** + * Apply design + * + * @param Varien_Object|array $designUpdateData + * @param integer $calledFrom + * @param boolean $loaded + * @return Mage_Catalog_Model_Design + */ + protected function _applyDesign($designUpdateData, $calledFrom = 0, $loaded = false) { - Mage::getSingleton('core/design_package') - ->setPackageName($package) - ->setTheme($theme); + $objects = array(); + if (is_object($designUpdateData)) { + $objects = array($designUpdateData); + } elseif (is_array($designUpdateData)) { + $objects = &$designUpdateData; + } + foreach ($objects as $object) { + $error = 0; + $package = ''; + $theme = ''; + $design = $object->getCustomDesign(); + $date = $object->getCustomDesignDate(); + $application= $object->getCustomDesignApply(); + + $designInfo = explode("/", $design); + if (count($designInfo) > 1){ + $package= $designInfo[0]; + $theme = $designInfo[1]; + } + + switch ($calledFrom) { + case 3: + if ($application && $application != 1 && $application != 3) + $error = 1; + $calledFrom = 0; + break; + case 4: + if ($application && $application != 1 && $application != 4) + $error = 1; + //$calledFrom = 0; + break; + default: + if ($application && $application != 1) + $error = 1; + break; + } + + if ($package && $theme) { + $date['from'] = strtotime($date['from']); + $date['to'] = strtotime($date['to']); + + if ($date['from'] && $date['from'] > strtotime("today")) { + $error = 1; + } else if ($date['to'] && $date['to'] < strtotime("today")) { + $error = 1; + } + + if (!$error) { + $this->_apply($package, $theme); + return; + } + } + } + if (false === $loaded && is_object($designUpdateData)) { + $_designUpdateData = array(); + if ($designUpdateData instanceof Mage_Catalog_Model_Product) { + $_category = $designUpdateData->getCategory(); + $_designUpdateData = array_merge( + $_designUpdateData, array($_category) + ); + } elseif ($designUpdateData instanceof Mage_Catalog_Model_Category) { + $_category = &$designUpdateData; + } + if ($_category && $_category->getId()) { + $_designUpdateData = array_merge( + $_designUpdateData, + $_category->getResource()->getDesignUpdateData($_category) + ); + $this->_applyDesign( + $_designUpdateData, + $calledFrom, true + ); + } + } + return $this; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Layer.php b/app/code/core/Mage/Catalog/Model/Layer.php index e3680d6af4..8c567e7e82 100644 --- a/app/code/core/Mage/Catalog/Model/Layer.php +++ b/app/code/core/Mage/Catalog/Model/Layer.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -34,6 +34,11 @@ */ class Mage_Catalog_Model_Layer extends Varien_Object { + /** + * Product collections array + * + * @var array + */ protected $_productCollections = array(); /** @@ -62,7 +67,8 @@ public function getStateKey() { if ($this->_stateKey === null) { $this->_stateKey = 'STORE_'.Mage::app()->getStore()->getId() - . '_CAT_'.$this->getCurrentCategory()->getId(); + . '_CAT_'.$this->getCurrentCategory()->getId() + . '_CUSTGROUP_' . Mage::getSingleton('customer/session')->getCustomerGroupId(); } return $this->_stateKey; } @@ -108,7 +114,9 @@ public function getProductCollection() */ public function prepareProductCollection($collection) { - $collection->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes()) + $attributes = Mage::getSingleton('catalog/config') + ->getProductAttributes(); + $collection->addAttributeToSelect($attributes) ->addMinimalPrice() ->addFinalPrice() ->addTaxPercents() @@ -206,28 +214,27 @@ public function getCurrentStore() */ public function getFilterableAttributes() { - $entity = $this->getProductCollection()->getEntity(); - $setIds = $this->_getSetIds(); + $entity = Mage::getSingleton('eav/config') + ->getEntityType('catalog_product'); - if (!$setIds) + $setIds = $this->_getSetIds(); + if (!$setIds) { return array(); + } - $collection = Mage::getModel('eav/entity_attribute')->getCollection() + $collection = Mage::getModel('eav/entity_attribute') + ->getCollection() ->setItemObjectClass('catalog/resource_eav_attribute'); /* @var $collection Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ $collection->getSelect()->distinct(true); - $collection->setEntityTypeFilter($entity->getTypeId()) + $collection + ->setEntityTypeFilter($entity->getId()) ->setAttributeSetFilter($setIds) ->setOrder('position', 'ASC'); $collection = $this->_prepareAttributeCollection($collection); $collection->load(); - foreach ($collection as $item) { - $this->_prepareAttribute($item); - $item->setEntity($entity); - } - return $collection; } @@ -264,8 +271,10 @@ public function getState() { $state = $this->getData('state'); if (is_null($state)) { + Varien_Profiler::start(__METHOD__); $state = Mage::getModel('catalog/layer_state'); $this->setData('state', $state); + Varien_Profiler::stop(__METHOD__); } return $state; } diff --git a/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php b/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php index d039da7f65..9a3312dea5 100644 --- a/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php +++ b/app/code/core/Mage/Catalog/Model/Layer/Filter/Abstract.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,7 +29,7 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ abstract class Mage_Catalog_Model_Layer_Filter_Abstract extends Varien_Object { @@ -238,6 +238,6 @@ public function getAttributeModel() */ public function getName() { - return $this->getAttributeModel()->getFrontend()->getLabel(); + return $this->getAttributeModel()->getFrontendLabel(); } } diff --git a/app/code/core/Mage/Catalog/Model/Layer/Filter/Attribute.php b/app/code/core/Mage/Catalog/Model/Layer/Filter/Attribute.php index 45b7ffdafc..1f913c3a3a 100644 --- a/app/code/core/Mage/Catalog/Model/Layer/Filter/Attribute.php +++ b/app/code/core/Mage/Catalog/Model/Layer/Filter/Attribute.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,7 +29,7 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Model_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer_Filter_Abstract { @@ -37,6 +37,7 @@ class Mage_Catalog_Model_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer /** * Construct attribute filter + * */ public function __construct() { @@ -50,7 +51,7 @@ public function __construct() * @param int $optionId * @return unknown */ - protected function _getOptionText($optionId) + protected function _getOptionText($optionId) { return $this->getAttributeModel()->getFrontend()->getOption($optionId); } @@ -136,4 +137,4 @@ protected function _getItemsData() } return $data; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php b/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php index 83a3aaea31..e7b2b3554a 100644 --- a/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php +++ b/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -33,7 +33,18 @@ */ class Mage_Catalog_Model_Layer_Filter_Category extends Mage_Catalog_Model_Layer_Filter_Abstract { + /** + * Active Category Id + * + * @var int + */ protected $_categoryId; + + /** + * Applied Category + * + * @var Mage_Catalog_Model_Category + */ protected $_appliedCategory = null; /** @@ -120,8 +131,9 @@ public function getName() */ public function getCategory() { - if ($this->_categoryId) { - $category = Mage::getModel('catalog/category')->load($this->_categoryId); + if (!is_null($this->_categoryId)) { + $category = Mage::getModel('catalog/category') + ->load($this->_categoryId); if ($category->getId()) { return $category; } @@ -141,21 +153,14 @@ protected function _getItemsData() if ($data === null) { $categoty = $this->getCategory(); - $collection = Mage::getResourceModel('catalog/category_collection') - ->addAttributeToSelect('name') - ->addAttributeToSelect('all_children') - ->addAttributeToSelect('is_anchor') - ->addAttributeToFilter('is_active', 1) - ->addAttributeToSort('position', 'asc') - ->joinUrlRewrite() - ->addIdFilter($categoty->getChildren()) - ->load(); + /** @var $categoty Mage_Catalog_Model_Categeory */ + $categories = $categoty->getChildrenCategories(); $this->getLayer()->getProductCollection() - ->addCountToCategories($collection); + ->addCountToCategories($categories); - $data=array(); - foreach ($collection as $category) { + $data = array(); + foreach ($categories as $category) { if ($category->getIsActive() && $category->getProductCount()) { $data[] = array( 'label' => $category->getName(), @@ -169,4 +174,4 @@ protected function _getItemsData() } return $data; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php b/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php index de3854b8b4..bddc62c872 100644 --- a/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php +++ b/app/code/core/Mage/Catalog/Model/Layer/Filter/Price.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -37,6 +37,7 @@ class Mage_Catalog_Model_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Fil /** * Class constructor + * */ public function __construct() { diff --git a/app/code/core/Mage/Catalog/Model/Observer.php b/app/code/core/Mage/Catalog/Model/Observer.php index dd2ed1200d..6221b860c5 100644 --- a/app/code/core/Mage/Catalog/Model/Observer.php +++ b/app/code/core/Mage/Catalog/Model/Observer.php @@ -20,10 +20,18 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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 Observer + * + * @category Mage + * @package Mage_Catalog + * @author Magento Core Team + */ class Mage_Catalog_Model_Observer { /** @@ -32,7 +40,7 @@ class Mage_Catalog_Model_Observer * @param Varien_Event_Observer $observer * @return Mage_Catalog_Model_Observer */ - public function storeEdit($observer) + public function storeEdit(Varien_Event_Observer $observer) { $store = $observer->getEvent()->getStore(); /* @var $store Mage_Core_Model_Store */ @@ -44,6 +52,9 @@ public function storeEdit($observer) array(), array($store->getId()) ); + if (Mage::helper('catalog/category_flat')->isEnabled(true)) { + Mage::getResourceModel('catalog/category_flat')->synchronize(null, array($store->getId())); + } Mage::getResourceSingleton('catalog/product')->refreshEnabledIndex($store); } return $this; @@ -55,7 +66,7 @@ public function storeEdit($observer) * @param Varien_Event_Observer $observer * @return Mage_Catalog_Model_Observer */ - public function storeAdd($observer) + public function storeAdd(Varien_Event_Observer $observer) { $store = $observer->getEvent()->getStore(); /* @var $store Mage_Core_Model_Store */ @@ -67,6 +78,10 @@ public function storeAdd($observer) array(), array($store->getId()) ); + if (Mage::helper('catalog/category_flat')->isEnabled(true)) { + Mage::getResourceModel('catalog/category_flat') + ->synchronize(null, array($store->getId())); + } Mage::getResourceModel('catalog/product')->refreshEnabledIndex($store); return $this; } @@ -77,7 +92,7 @@ public function storeAdd($observer) * @param Varien_Event_Observer $observer * @return Mage_Catalog_Model_Observer */ - public function storeGroupSave($observer) + public function storeGroupSave(Varien_Event_Observer $observer) { $group = $observer->getEvent()->getGroup(); /* @var $group Mage_Core_Model_Store_Group */ @@ -90,6 +105,10 @@ public function storeGroupSave($observer) array(), array($store->getId()) ); + if (Mage::helper('catalog/category_flat')->isEnabled(true)) { + Mage::getResourceModel('catalog/category_flat') + ->synchronize(null, array($store->getId())); + } } } return $this; @@ -101,7 +120,7 @@ public function storeGroupSave($observer) * @param Varien_Event_Observer $observer * @return Mage_Catalog_Model_Observer */ - public function categoryMove($observer) + public function categoryMove(Varien_Event_Observer $observer) { $categoryId = $observer->getEvent()->getCategoryId(); $prevParentId = $observer->getEvent()->getPrevParentId(); @@ -110,9 +129,12 @@ public function categoryMove($observer) Mage::getResourceSingleton('catalog/category')->refreshProductIndex(array( $categoryId, $prevParentId, $parentId )); - $model = Mage::getModel('catalog/category')->load($prevParentId)->save(); - $model = Mage::getModel('catalog/category')->load($parentId)->save(); - $model = null; + Mage::getModel('catalog/category')->load($prevParentId)->save(); + Mage::getModel('catalog/category')->load($parentId)->save(); + if (Mage::helper('catalog/category_flat')->isEnabled(true)) { + Mage::getResourceModel('catalog/category_flat') + ->move($categoryId, $prevParentId, $parentId); + } return $this; } @@ -122,7 +144,7 @@ public function categoryMove($observer) * @param Varien_Event_Observer $observer * @return Mage_Catalog_Model_Observer */ - public function catalogProductImportAfter($observer) + public function catalogProductImportAfter(Varien_Event_Observer $observer) { Mage::getModel('catalog/url')->refreshRewrites(); Mage::getResourceSingleton('catalog/category')->refreshProductIndex(); @@ -140,4 +162,19 @@ public function catalogProductCompareClean(Varien_Event_Observer $observer) Mage::getModel('catalog/product_compare_item')->clean(); return $this; } + + /** + * After save event of category + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Observer + */ + public function categorySaveAfter(Varien_Event_Observer $observer) + { + if (Mage::helper('catalog/category_flat')->isEnabled(true)) { + $category = $observer->getEvent()->getCategory(); + Mage::getResourceModel('catalog/category_flat')->synchronize($category); + } + return $this; + } } diff --git a/app/code/core/Mage/Catalog/Model/Product.php b/app/code/core/Mage/Catalog/Model/Product.php index a841e8d6c9..cfd89bf00f 100644 --- a/app/code/core/Mage/Catalog/Model/Product.php +++ b/app/code/core/Mage/Catalog/Model/Product.php @@ -44,7 +44,12 @@ class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract * * @var Mage_Catalog_Model_Product_Type_Abstract */ - protected $_typeInstance = null; + protected $_typeInstance = null; + + /** + * Product type instance as singleton + */ + protected $_typeInstanceSingleton = null; /** * Product link instance @@ -86,16 +91,53 @@ class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract */ protected function _construct() { - $this->_urlModel = Mage::getSingleton('catalog/product_url'); $this->_init('catalog/product'); } + /** + * Get collection instance + * + * @return object + */ + public function getResourceCollection() + { + if (empty($this->_resourceCollectionName)) { + Mage::throwException(Mage::helper('core')->__('Model collection resource name is not defined')); + } + $collection = Mage::getResourceModel($this->_resourceCollectionName); + $collection->setStoreId($this->getStoreId()); + return $collection; + } + + /** + * Get product url model + * + * @return Mage_Catalog_Model_Product_Url + */ + public function getUrlModel() + { + if ($this->_urlModel === null) { + $this->_urlModel = Mage::getSingleton('catalog/product_url'); + } + return $this->_urlModel; + } + + /** + * Validate Product Data + * + * @return Mage_Catalog_Model_Product + */ public function validate() { $this->_getResource()->validate($this); return $this; } + /** + * Get product name + * + * @return string + */ public function getName() { return $this->_getData('name'); @@ -111,11 +153,21 @@ public function getPrice() return $this->getPriceModel()->getPrice($this); } + /** + * Get product type identifier + * + * @return int + */ public function getTypeId() { return $this->_getData('type_id'); } + /** + * Get product status + * + * @return int + */ public function getStatus() { return $this->_getData('status'); @@ -126,24 +178,46 @@ public function getStatus() * * Type instance implement type depended logic * + * @param bool $singleton * @return Mage_Catalog_Model_Product_Type_Abstract */ - public function getTypeInstance() + public function getTypeInstance($singleton = false) { + if ($singleton === true) { + if (is_null($this->_typeInstanceSingleton)) { + $this->_typeInstanceSingleton = Mage::getSingleton('catalog/product_type') + ->factory($this, true); + } + return $this->_typeInstanceSingleton; + } + if ($this->_typeInstance === null) { - $this->_typeInstance = Mage::getSingleton('catalog/product_type')->factory($this); + $this->_typeInstance = Mage::getSingleton('catalog/product_type') + ->factory($this); } return $this->_typeInstance; } - public function setTypeInstance($instance) + /** + * Set type instance for external + * + * @param Mage_Catalog_Model_Product_Type_Abstract $singleton + * @param bool $singleton + * @return Mage_Catalog_Model_Product + */ + public function setTypeInstance($instance, $singleton = false) { - $this->_typeInstance = $instance; + if ($singleton === true) { + $this->_typeInstanceSingleton = $instance; + } + else { + $this->_typeInstance = $instance; + } return $this; } /** - * Retrieve type instance + * Retrieve link instance * * @return Mage_Catalog_Model_Product_Link */ @@ -249,6 +323,11 @@ public function getWebsiteIds() return $this->getData('website_ids'); } + /** + * Get all sore ids where product is presented + * + * @return array + */ public function getStoreIds() { if (!$this->hasStoreIds()) { @@ -274,7 +353,7 @@ public function getStoreIds() */ public function getAttributes($groupId = null, $skipSuper=false) { - $productAttributes = $this->getTypeInstance()->getEditableAttributes(); + $productAttributes = $this->getTypeInstance(true)->getEditableAttributes($this); if ($groupId) { $attributes = array(); foreach ($productAttributes as $attribute) { @@ -292,7 +371,6 @@ public function getAttributes($groupId = null, $skipSuper=false) /** * Check product options and type options and save them, too - * */ protected function _beforeSave() { @@ -300,14 +378,15 @@ protected function _beforeSave() $this->setTypeHasOptions(false); $this->setTypeHasRequiredOptions(false); - $this->getTypeInstance()->beforeSave(); + $this->getTypeInstance(true)->beforeSave($this); $hasOptions = false; $hasRequiredOptions = false; /** * $this->_canAffectOptions - set by type instance only - * $this->getCanSaveCustomOptions() - set either in controller when "Custom Options" ajax tab is loaded, or in type instance as well + * $this->getCanSaveCustomOptions() - set either in controller when "Custom Options" ajax tab is loaded, + * or in type instance as well */ $this->canAffectOptions($this->_canAffectOptions && $this->getCanSaveCustomOptions()); if ($this->getCanSaveCustomOptions()) { @@ -352,8 +431,8 @@ protected function _beforeSave() * Check/set if options can be affected when saving product * If value specified, it will be set. * - * @param bool $value - * @return bool + * @param bool $value + * @return bool */ public function canAffectOptions($value = null) { @@ -366,29 +445,27 @@ public function canAffectOptions($value = null) /** * Saving product type related data * - * @return unknown + * @return Mage_Catalog_Model_Product */ protected function _afterSave() { $this->getLinkInstance()->saveProductRelations($this); - $this->getTypeInstance()->save(); + $this->getTypeInstance(true)->save($this); /** - * Product Custom Options + * Product Options */ - /* @var $optionModel Mage_Catalog_Model_Product_Option */ -// $options = $this->getProductOptions(); -// if (is_array($options)) { -// foreach ($this->getProductOptions() as $option) { -// $this->getOptionInstance()->addOption($option); -// } -// } $this->getOptionInstance()->setProduct($this) ->saveOptions(); parent::_afterSave(); } + /** + * Clear chache related with product and protect delete from not admin + * + * @return Mage_Catalog_Model_Product + */ protected function _beforeDelete() { $this->cleanCache(); @@ -397,30 +474,41 @@ protected function _beforeDelete() } /** - * deprecated - * @see Mage_Sales_Model_Observer::substractQtyFromQuotes() + * Load product options if they exists + * + * @return Mage_Catalog_Model_Product */ - protected function _substractQtyFromQuotes() - { - // kept for legacy purposes - } - protected function _afterLoad() { parent::_afterLoad(); - foreach ($this->getProductOptionsCollection() as $option) { - $option->setProduct($this); - $this->addOption($option); + /** + * Load product options + */ + if ($this->getHasOptions()) { + foreach ($this->getProductOptionsCollection() as $option) { + $option->setProduct($this); + $this->addOption($option); + } } - return $this; } + /** + * Clear cache related with product id + * + * @return Mage_Catalog_Model_Product + */ public function cleanCache() { Mage::app()->cleanCache('catalog_product_'.$this->getId()); + return $this; } + /** + * Get product price model + * + * @return Mage_Catalog_Model_Product_Type_Price + */ public function getPriceModel() { return Mage::getSingleton('catalog/product_type')->priceFactory($this->getTypeId()); @@ -476,6 +564,10 @@ public function getFormatedPrice() */ public function getFinalPrice($qty=null) { + $price = $this->_getData('final_price'); + if ($price !== null) { + return $price; + } return $this->getPriceModel()->getFinalPrice($qty, $this); } @@ -762,7 +854,7 @@ public function getMediaGalleryImages() */ public function addImageToMediaGallery($file, $mediaAttribute=null, $move=false, $exclude=true) { - $attributes = $this->getTypeInstance()->getSetAttributes(); + $attributes = $this->getTypeInstance(true)->getSetAttributes($this); if (!isset($attributes['media_gallery'])) { return $this; } @@ -956,7 +1048,7 @@ public function isSalable() 'product' => $this )); - $salable = $this->getTypeInstance()->isSalable(); + $salable = $this->getTypeInstance(true)->isSalable($this); $object = new Varien_Object(array( 'product' => $this, @@ -969,6 +1061,17 @@ public function isSalable() return $object->getIsSalable(); } + /** + * Check is a virtual product + * Data helper wraper + * + * @return bool + */ + public function isVirtual() + { + return $this->getIsVirtual(); + } + public function isSaleable() { return $this->isSalable(); @@ -1004,12 +1107,12 @@ public function getCustomDesignDate() */ public function getProductUrl($useSid = true) { - return $this->_urlModel->getProductUrl($this, $useSid); + return $this->getUrlModel()->getProductUrl($this, $useSid); } public function formatUrlKey($str) { - return $this->_urlModel->formatUrlKey($str); + return $this->getUrlModel()->formatUrlKey($str); } /** @@ -1020,7 +1123,7 @@ public function formatUrlKey($str) */ public function getUrlPath($category=null) { - return $this->_urlModel->getUrlPath($this, $category); + return $this->getUrlModel()->getUrlPath($this, $category); } public function addAttributeUpdate($code, $value, $store) @@ -1097,7 +1200,7 @@ public function getRatingSummary() */ public function isComposite() { - return $this->getTypeInstance()->isComposite(); + return $this->getTypeInstance(true)->isComposite($this); } /** @@ -1107,7 +1210,7 @@ public function isComposite() */ public function getSku() { - return $this->getTypeInstance()->getSku(); + return $this->getTypeInstance(true)->getSku($this); } /** @@ -1117,7 +1220,7 @@ public function getSku() */ public function getWeight() { - return $this->getTypeInstance()->getWeight(); + return $this->getTypeInstance(true)->getWeight($this); } /** @@ -1190,7 +1293,7 @@ public function getOptions() */ public function getIsVirtual() { - return $this->getTypeInstance()->isVirtual(); + return $this->getTypeInstance(true)->isVirtual($this); } /** @@ -1325,13 +1428,12 @@ public function getThumbnailUrl($width = 75, $height = 75) /** * Returns system reserved attribute codes * - * @param none * @return array Reserved attribute names */ public function getReservedAttributes() { if ($this->_reservedAttributes === null) { - $_reserved = array(); + $_reserved = array('position'); $methods = get_class_methods(__CLASS__); foreach ($methods as $method) { if (preg_match('/^get([A-Z]{1}.+)/', $method, $matches)) { @@ -1359,4 +1461,29 @@ public function isReservedAttribute ($attribute) return $attribute->getIsUserDefined() && in_array($attribute->getAttributeCode(), $this->getReservedAttributes()); } + + /** + * Set original loaded data if needed + * + * @param string $key + * @param mixed $data + * @return Varien_Object + */ + public function setOrigData($key=null, $data=null) + { + if (Mage::app()->getStore()->isAdmin()) { + return parent::setOrigData($key, $data); + } + + return $this; + } + + /** + * @deprecated + * @see Mage_Sales_Model_Observer::substractQtyFromQuotes() + */ + protected function _substractQtyFromQuotes() + { + // kept for legacy purposes + } } diff --git a/app/code/core/Mage/Catalog/Model/Product/Api.php b/app/code/core/Mage/Catalog/Model/Product/Api.php index d1e6e7dd2e..9a39ccb804 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Api.php +++ b/app/code/core/Mage/Catalog/Model/Product/Api.php @@ -1,301 +1,301 @@ - - */ -class Mage_Catalog_Model_Product_Api extends Mage_Catalog_Model_Api_Resource -{ - protected $_filtersMap = array( - 'product_id' => 'entity_id', - 'set' => 'attribute_set_id', - 'type' => 'type_id' - ); - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - $this->_ignoredAttributeTypes[] = 'gallery'; - $this->_ignoredAttributeTypes[] = 'media_image'; - } - - /** - * Retrieve list of products with basic info (id, sku, type, set, name) - * - * @param array $filters - * @param string|int $store - * @return array - */ - public function items($filters = null, $store = null) - { - $collection = Mage::getModel('catalog/product')->getCollection() - ->setStoreId($this->_getStoreId($store)) - ->addAttributeToSelect('name'); - - if (is_array($filters)) { - try { - foreach ($filters as $field => $value) { - if (isset($this->_filtersMap[$field])) { - $field = $this->_filtersMap[$field]; - } - - $collection->addFieldToFilter($field, $value); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('filters_invalid', $e->getMessage()); - } - } - - $result = array(); - - foreach ($collection as $product) { -// $result[] = $product->getData(); - $result[] = array( // Basic product data - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'name' => $product->getName(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'category_ids' => $product->getCategoryIds() - ); - } - - return $result; - } - - /** - * Retrieve product info - * - * @param int|string $productId - * @param string|int $store - * @param array $attributes - * @return array - */ - public function info($productId, $store = null, $attributes = null) - { - $product = $this->_getProduct($productId, $store); - - if (!$product->getId()) { - $this->_fault('not_exists'); - } - - $result = array( // Basic product data - 'product_id' => $product->getId(), - 'sku' => $product->getSku(), - 'set' => $product->getAttributeSetId(), - 'type' => $product->getTypeId(), - 'categories' => $product->getCategoryIds(), - 'websites' => $product->getWebsiteIds() - ); - - foreach ($product->getTypeInstance()->getEditableAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute, $attributes)) { - $result[$attribute->getAttributeCode()] = $product->getData( - $attribute->getAttributeCode()); - } - } - - return $result; - } - - /** - * Create new product. - * - * @param string $type - * @param int $set - * @param array $productData - * @return int - */ - public function create($type, $set, $sku, $productData) - { - if (!$type || !$set || !$sku) { - $this->_fault('data_invalid'); - } - - $product = Mage::getModel('catalog/product'); - /* @var $product Mage_Catalog_Model_Product */ - $product->setStoreId($this->_getStoreId($store)) - ->setAttributeSetId($set) - ->setTypeId($type) - ->setSku($sku); - - foreach ($product->getTypeInstance()->getEditableAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute) - && isset($productData[$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData[$attribute->getAttributeCode()] - ); - } - } - - $this->_prepareDataForSave($product, $productData); - - if (is_array($errors = $product->validate())) { - $this->_fault('data_invalid', implode("\n", $errors)); - } - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return $product->getId(); - } - - /** - * Update product data - * - * @param int|string $productId - * @param array $productData - * @param string|int $store - * @return boolean - */ - public function update($productId, $productData = array(), $store = null) - { - $product = $this->_getProduct($productId, $store); - - if (!$product->getId()) { - $this->_fault('not_exists'); - } - - foreach ($product->getTypeInstance()->getEditableAttributes() as $attribute) { - if ($this->_isAllowedAttribute($attribute) - && isset($productData[$attribute->getAttributeCode()])) { - $product->setData( - $attribute->getAttributeCode(), - $productData[$attribute->getAttributeCode()] - ); - } - } - - $this->_prepareDataForSave($product, $productData); - - try { - if (is_array($errors = $product->validate())) { - $this->_fault('data_invalid', implode("\n", $errors)); - } - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('data_invalid', $e->getMessage()); - } - - return true; - } - - /** - * Set additional data before product saved - * - * @param Mage_Catalog_Model_Product $product - * @param array $productData - * @return object - */ - protected function _prepareDataForSave ($product, $productData) - { - if (isset($productData['categories']) && is_array($productData['categories'])) { - $product->setCategoryIds($productData['categories']); - } - - if (isset($productData['websites']) && is_array($productData['websites'])) { - foreach ($productData['websites'] as &$website) { - if (is_string($website)) { - try { - $website = Mage::app()->getWebsite($website)->getId(); - } catch (Exception $e) { } - } - } - $product->setWebsiteIds($productData['websites']); - } - - if (isset($productData['stock_data']) && is_array($productData['stock_data'])) { - $product->setStockData($productData['stock_data']); - } - } - - /** - * Update product special price - * - * @param int|string $productId - * @param float $specialPrice - * @param string $fromDate - * @param string $toDate - * @param string|int $store - * @return boolean - */ - public function setSpecialPrice($productId, $specialPrice = null, $fromDate = null, $toDate = null, $store = null) - { - return $this->update($productId, array( - 'special_price' => $specialPrice, - 'special_from_date' => $fromDate, - 'special_to_date' => $toDate - ), $store); - } - - /** - * Retrieve product special price - * - * @param int|string $productId - * @param string|int $store - * @return array - */ - public function getSpecialPrice($productId, $store = null) - { - return $this->info($productId, $store, array('special_price', 'special_from_date', 'special_to_date')); - } - - /** - * Delete product - * - * @param int|string $productId - * @return boolean - */ - public function delete($productId) - { - $product = $this->_getProduct($productId); - - if (!$product->getId()) { - $this->_fault('not_exists'); - } - - try { - $product->delete(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_deleted', $e->getMessage()); - } - - return true; - } + + */ +class Mage_Catalog_Model_Product_Api extends Mage_Catalog_Model_Api_Resource +{ + protected $_filtersMap = array( + 'product_id' => 'entity_id', + 'set' => 'attribute_set_id', + 'type' => 'type_id' + ); + + public function __construct() + { + $this->_storeIdSessionField = 'product_store_id'; + $this->_ignoredAttributeTypes[] = 'gallery'; + $this->_ignoredAttributeTypes[] = 'media_image'; + } + + /** + * Retrieve list of products with basic info (id, sku, type, set, name) + * + * @param array $filters + * @param string|int $store + * @return array + */ + public function items($filters = null, $store = null) + { + $collection = Mage::getModel('catalog/product')->getCollection() + ->setStoreId($this->_getStoreId($store)) + ->addAttributeToSelect('name'); + + if (is_array($filters)) { + try { + foreach ($filters as $field => $value) { + if (isset($this->_filtersMap[$field])) { + $field = $this->_filtersMap[$field]; + } + + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + + foreach ($collection as $product) { +// $result[] = $product->getData(); + $result[] = array( // Basic product data + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'name' => $product->getName(), + 'set' => $product->getAttributeSetId(), + 'type' => $product->getTypeId(), + 'category_ids' => $product->getCategoryIds() + ); + } + + return $result; + } + + /** + * Retrieve product info + * + * @param int|string $productId + * @param string|int $store + * @param array $attributes + * @return array + */ + public function info($productId, $store = null, $attributes = null) + { + $product = $this->_getProduct($productId, $store); + + if (!$product->getId()) { + $this->_fault('not_exists'); + } + + $result = array( // Basic product data + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'set' => $product->getAttributeSetId(), + 'type' => $product->getTypeId(), + 'categories' => $product->getCategoryIds(), + 'websites' => $product->getWebsiteIds() + ); + + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + if ($this->_isAllowedAttribute($attribute, $attributes)) { + $result[$attribute->getAttributeCode()] = $product->getData( + $attribute->getAttributeCode()); + } + } + + return $result; + } + + /** + * Create new product. + * + * @param string $type + * @param int $set + * @param array $productData + * @return int + */ + public function create($type, $set, $sku, $productData) + { + if (!$type || !$set || !$sku) { + $this->_fault('data_invalid'); + } + + $product = Mage::getModel('catalog/product'); + /* @var $product Mage_Catalog_Model_Product */ + $product->setStoreId($this->_getStoreId($store)) + ->setAttributeSetId($set) + ->setTypeId($type) + ->setSku($sku); + + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + if ($this->_isAllowedAttribute($attribute) + && isset($productData[$attribute->getAttributeCode()])) { + $product->setData( + $attribute->getAttributeCode(), + $productData[$attribute->getAttributeCode()] + ); + } + } + + $this->_prepareDataForSave($product, $productData); + + if (is_array($errors = $product->validate())) { + $this->_fault('data_invalid', implode("\n", $errors)); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $product->getId(); + } + + /** + * Update product data + * + * @param int|string $productId + * @param array $productData + * @param string|int $store + * @return boolean + */ + public function update($productId, $productData = array(), $store = null) + { + $product = $this->_getProduct($productId, $store); + + if (!$product->getId()) { + $this->_fault('not_exists'); + } + + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + if ($this->_isAllowedAttribute($attribute) + && isset($productData[$attribute->getAttributeCode()])) { + $product->setData( + $attribute->getAttributeCode(), + $productData[$attribute->getAttributeCode()] + ); + } + } + + $this->_prepareDataForSave($product, $productData); + + try { + if (is_array($errors = $product->validate())) { + $this->_fault('data_invalid', implode("\n", $errors)); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return true; + } + + /** + * Set additional data before product saved + * + * @param Mage_Catalog_Model_Product $product + * @param array $productData + * @return object + */ + protected function _prepareDataForSave ($product, $productData) + { + if (isset($productData['categories']) && is_array($productData['categories'])) { + $product->setCategoryIds($productData['categories']); + } + + if (isset($productData['websites']) && is_array($productData['websites'])) { + foreach ($productData['websites'] as &$website) { + if (is_string($website)) { + try { + $website = Mage::app()->getWebsite($website)->getId(); + } catch (Exception $e) { } + } + } + $product->setWebsiteIds($productData['websites']); + } + + if (isset($productData['stock_data']) && is_array($productData['stock_data'])) { + $product->setStockData($productData['stock_data']); + } + } + + /** + * Update product special price + * + * @param int|string $productId + * @param float $specialPrice + * @param string $fromDate + * @param string $toDate + * @param string|int $store + * @return boolean + */ + public function setSpecialPrice($productId, $specialPrice = null, $fromDate = null, $toDate = null, $store = null) + { + return $this->update($productId, array( + 'special_price' => $specialPrice, + 'special_from_date' => $fromDate, + 'special_to_date' => $toDate + ), $store); + } + + /** + * Retrieve product special price + * + * @param int|string $productId + * @param string|int $store + * @return array + */ + public function getSpecialPrice($productId, $store = null) + { + return $this->info($productId, $store, array('special_price', 'special_from_date', 'special_to_date')); + } + + /** + * Delete product + * + * @param int|string $productId + * @return boolean + */ + public function delete($productId) + { + $product = $this->_getProduct($productId); + + if (!$product->getId()) { + $this->_fault('not_exists'); + } + + try { + $product->delete(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_deleted', $e->getMessage()); + } + + return true; + } } // Class Mage_Catalog_Model_Product_Api End \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Api/V2.php new file mode 100644 index 0000000000..01c6a23807 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Api/V2.php @@ -0,0 +1,325 @@ + + */ +class Mage_Catalog_Model_Product_Api_V2 extends Mage_Catalog_Model_Product_Api +{ + + /** + * Retrieve list of products with basic info (id, sku, type, set, name) + * + * @param array $filters + * @param string|int $store + * @return array + */ + public function items($filters = null, $store = null) + { + $collection = Mage::getModel('catalog/product')->getCollection() + ->setStoreId($this->_getStoreId($store)) + ->addAttributeToSelect('name'); + + $preparedFilters = array(); + if (isset($filters->filter)) { + foreach ($filters->filter as $_filter) { + $preparedFilters[$_filter->key] = $_filter->value; + } + } + if (isset($filters->complex_filter)) { + foreach ($filters->complex_filter as $_filter) { + $_value = $_filter->value; + $preparedFilters[$_filter->key] = array( + $_value->key => $_value->value + ); + } + } + + if (!empty($preparedFilters)) { + try { + foreach ($preparedFilters as $field => $value) { + if (isset($this->_filtersMap[$field])) { + $field = $this->_filtersMap[$field]; + } + + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + + foreach ($collection as $product) { +// $result[] = $product->getData(); + $result[] = array( // Basic product data + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'name' => $product->getName(), + 'set' => $product->getAttributeSetId(), + 'type' => $product->getTypeId(), + 'category_ids' => $product->getCategoryIds() + ); + } + + return $result; + } + + /** + * Retrieve product info + * + * @param int|string $productId + * @param string|int $store + * @param stdClass $attributes + * @return array + */ + public function info($productId, $store = null, $attributes = null) + { + $product = $this->_getProduct($productId, $store); + + if (!$product->getId()) { + $this->_fault('not_exists'); + } + + $result = array( // Basic product data + 'product_id' => $product->getId(), + 'sku' => $product->getSku(), + 'set' => $product->getAttributeSetId(), + 'type' => $product->getTypeId(), + 'categories' => $product->getCategoryIds(), + 'websites' => $product->getWebsiteIds() + ); + + $allAttributes = array(); + if (isset($attributes['attributes'])) { + $allAttributes += array_merge($allAttributes, $attributes['attributes']); + } + + $_additionalAttributeCodes = array(); + if (isset($attributes['additional_attributes'])) { + foreach ($attributes['additional_attributes'] as $k => $_attributeCode) { + $allAttributes[] = $_attributeCode; + $_additionalAttributeCodes[] = $_attributeCode; + } + } + + $_additionalAttribute = 0; + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + if ($this->_isAllowedAttribute($attribute, $allAttributes)) { + if (in_array($attribute->getAttributeCode(), $_additionalAttributeCodes)) { + $result['additional_attributes'][$_additionalAttribute]['key'] = $attribute->getAttributeCode(); + $result['additional_attributes'][$_additionalAttribute]['value'] = $product->getData($attribute->getAttributeCode()); + $_additionalAttribute++; + } else { + $result[$attribute->getAttributeCode()] = $product->getData($attribute->getAttributeCode()); + } + } + } + + return $result; + } + + /** + * Create new product. + * + * @param string $type + * @param int $set + * @param array $productData + * @return int + */ + public function create($type, $set, $sku, $productData) + { + if (!$type || !$set || !$sku) { + $this->_fault('data_invalid'); + } + $store = null; + $product = Mage::getModel('catalog/product'); + /* @var $product Mage_Catalog_Model_Product */ + $product->setStoreId($this->_getStoreId($store)) + ->setAttributeSetId($set) + ->setTypeId($type) + ->setSku($sku); + + if (property_exists($productData, 'additional_attributes')) { + foreach ($productData->additional_attributes as $_attribute) { + $_attrCode = $_attribute->key; + $productData->$_attrCode = $_attribute->value; + } + unset($productData->additional_attributes); + } + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + $_attrCode = $attribute->getAttributeCode(); + if ($this->_isAllowedAttribute($attribute) + && isset($productData->$_attrCode)) { + $product->setData( + $attribute->getAttributeCode(), + $productData->$_attrCode + ); + } + } + + $this->_prepareDataForSave($product, $productData); + + if (is_array($errors = $product->validate())) { + $this->_fault('data_invalid', implode("\n", $errors)); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $product->getId(); + } + + /** + * Update product data + * + * @param int|string $productId + * @param array $productData + * @param string|int $store + * @return boolean + */ + public function update($productId, $productData, $store = null) + { + $product = $this->_getProduct($productId, $store); + + if (!$product->getId()) { + $this->_fault('not_exists'); + } + + if (property_exists($productData, 'additional_attributes')) { + foreach ($productData->additional_attributes as $_attribute) { + $_attrCode = $_attribute->key; + $productData->$_attrCode = $_attribute->value; + } + unset($productData->additional_attributes); + } + + foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { + $_attrCode = $attribute->getAttributeCode(); + if ($this->_isAllowedAttribute($attribute) + && isset($productData->$_attrCode)) { + $product->setData( + $attribute->getAttributeCode(), + $productData->$_attrCode + ); + } + } + + $this->_prepareDataForSave($product, $productData); + + try { + if (is_array($errors = $product->validate())) { + $this->_fault('data_invalid', implode("\n", $errors)); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return true; + } + + /** + * Set additional data before product saved + * + * @param Mage_Catalog_Model_Product $product + * @param array $productData + * @return object + */ + protected function _prepareDataForSave ($product, $productData) + { + if (property_exists($productData, 'categories') && is_array($productData->categories)) { + $product->setCategoryIds($productData->categories); + } + + if (property_exists($productData, 'websites') && is_array($productData->websites)) { + foreach ($productData->websites as &$website) { + if (is_string($website)) { + try { + $website = Mage::app()->getWebsite($website)->getId(); + } catch (Exception $e) { } + } + } + $product->setWebsiteIds($productData->websites); + } + + if (property_exists($productData, 'stock_data') && is_array($productData->stock_data)) { + $product->setStockData($productData->stock_data); + } + } + + /** + * Update product special price + * + * @param int|string $productId + * @param float $specialPrice + * @param string $fromDate + * @param string $toDate + * @param string|int $store + * @return boolean + */ + public function setSpecialPrice($productId, $specialPrice = null, $fromDate = null, $toDate = null, $store = null) + { + $obj = new stdClass(); + $obj->special_price = $specialPrice; + $obj->special_from_date = $fromDate; + $obj->special_to_date = $toDate; + return $this->update($productId, $obj, $store); + } + + /** + * Retrieve product special price + * + * @param int|string $productId + * @param string|int $store + * @return array + */ + public function getSpecialPrice($productId, $store = null) + { + return $this->info($productId, $store, array( + 'attributes' => array( + 'special_price', + 'special_from_date', + 'special_to_date' + ) + ) + ); + } + +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php index b7fc5eddf6..d113560cb1 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php @@ -89,22 +89,27 @@ public function items($setId) */ public function options($attributeId, $store = null) { - $attribute = Mage::getModel('catalog/entity_attribute'); - $attribute + $attribute = Mage::getModel('catalog/product') ->setStoreId($this->_getStoreId($store)) - ->load($attributeId); + ->getResource() + ->getAttribute($attributeId); /* @var $attribute Mage_Catalog_Model_Entity_Attribute */ - if (!$attribute->getId()) { + if (!$attribute) { $this->_fault('not_exists'); } $options = array(); if ($attribute->usesSource()) { - $options = Mage::getResourceModel('eav/entity_attribute_option_collection') - ->setAttributeFilter($attribute->getId()) - ->setStoreFilter() - ->load() - ->toOptionArray(); + foreach ($attribute->getSource()->getAllOptions() as $optionId=>$optionValue) { + if (is_array($optionValue)) { + $options[] = $optionValue; + } else { + $options[] = array( + 'value' => $optionId, + 'label' => $optionValue + ); + } + } } return $options; } diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php new file mode 100644 index 0000000000..97a1fbfa86 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Catalog_Model_Product_Attribute_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php index b61dfea825..d22dbca640 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php @@ -1,368 +1,369 @@ - - */ -class Mage_Catalog_Model_Product_Attribute_Media_Api extends Mage_Catalog_Model_Api_Resource -{ - /** - * Attribute code for media gallery - * - */ - const ATTRIBUTE_CODE = 'media_gallery'; - - /** - * Allowed mime types for image - * - * @var array - */ - protected $_mimeTypes = array( - 'image/jpeg' => 'jpg', - 'image/gif' => 'gif', - 'image/png' => 'png' - ); - - public function __construct() - { - $this->_storeIdSessionField = 'product_store_id'; - } - - /** - * Retrieve images for product - * - * @param int|string $productId - * @param string|int $store - * @return array - */ - public function items($productId, $store = null) - { - $product = $this->_initProduct($productId, $store); - - $gallery = $this->_getGalleryAttribute($product); - - $galleryData = $product->getData(self::ATTRIBUTE_CODE); - - if (!isset($galleryData['images']) || !is_array($galleryData['images'])) { - return array(); - } - - $result = array(); - - foreach ($galleryData['images'] as &$image) { - $result[] = $this->_imageToArray($image, $product); - } - - return $result; - } - - /** - * Retrieve image data - * - * @param int|string $productId - * @param string $file - * @param string|int $store - * @return array - */ - public function info($productId, $file, $store = null) - { - $product = $this->_initProduct($productId, $store); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$image = $gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - return $this->_imageToArray($image, $product); - } - - /** - * Create new image for product and return image filename - * - * @param int|string $productId - * @param array $data - * @param string|int $store - * @return string - */ - public function create($productId, $data, $store = null) - { - $product = $this->_initProduct($productId, $store); - - $gallery = $this->_getGalleryAttribute($product); - - if (!isset($data['file']) || !isset($data['file']['mime']) || !isset($data['file']['content'])) { - $this->_fault('data_invalid', Mage::helper('catalog')->__('Image not specified.')); - } - - if (!isset($this->_mimeTypes[$data['file']['mime']])) { - $this->_fault('data_invalid', Mage::helper('catalog')->__('Invalid image type.')); - } - - $fileContent = @base64_decode($data['file']['content'], true); - if (!$fileContent) { - $this->_fault('data_invalid', Mage::helper('catalog')->__('Image content is not valid base64 data.')); - } - - unset($data['file']['content']); - - $tmpDirectory = Mage::getBaseDir('var') . DS . 'api' . DS . $this->_getSession()->getSessionId(); - $fileName = 'image.' . $this->_mimeTypes[$data['file']['mime']]; - $ioAdapter = new Varien_Io_File(); - try { - // Create temporary directory for api - $ioAdapter->checkAndCreateFolder($tmpDirectory); - $ioAdapter->open(array('path'=>$tmpDirectory)); - // Write image file - $ioAdapter->write($fileName, $fileContent, 0666); - unset($fileContent); - - // Adding image to gallery - $file = $gallery->getBackend()->addImage( - $product, - $tmpDirectory . DS . $fileName, - null, - true - ); - - // Remove temporary directory - $ioAdapter->rmdir($tmpDirectory, true); - - $gallery->getBackend()->updateImage($product, $file, $data); - - if (isset($data['types'])) { - $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); - } - - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_created', $e->getMessage()); - } catch (Exception $e) { - $this->_fault('not_created', Mage::helper('catalog')->__('Can\'t create image.')); - } - - return $gallery->getBackend()->getRenamedImage($file); - } - - /** - * Update image data - * - * @param int|string $productId - * @param string $file - * @param array $data - * @param string|int $store - * @return boolean - */ - public function update($productId, $file, $data, $store = null) - { - $product = $this->_initProduct($productId, $store); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - $gallery->getBackend()->updateImage($product, $file, $data); - - if (isset($data['types']) && is_array($data['types'])) { - $oldTypes = array(); - foreach ($product->getMediaAttributes() as $attribute) { - if ($product->getData($attribute->getAttributeCode()) == $file) { - $oldTypes[] = $attribute->getAttributeCode(); - } - } - - $clear = array_diff($oldTypes, $data['types']); - - if (count($clear) > 0) { - $gallery->getBackend()->clearMediaAttribute($product, $clear); - } - - $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); - } - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_updated', $e->getMessage()); - } - - return true; - } - - /** - * Remove image from product - * - * @param int|string $productId - * @param string $file - * @return boolean - */ - public function remove($productId, $file) - { - $product = $this->_initProduct($productId); - - $gallery = $this->_getGalleryAttribute($product); - - if (!$gallery->getBackend()->getImage($product, $file)) { - $this->_fault('not_exists'); - } - - $gallery->getBackend()->removeImage($product, $file); - - try { - $product->save(); - } catch (Mage_Core_Exception $e) { - $this->_fault('not_removed', $e->getMessage()); - } - - return true; - } - - - /** - * Retrieve image types (image, small_image, thumbnail, etc...) - * - * @param int $setId - * @return array - */ - public function types($setId) - { - $attributes = Mage::getModel('catalog/product')->getResource() - ->loadAllAttributes() - ->getSortedAttributes($setId); - - $result = array(); - - foreach ($attributes as $attribute) { - /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ - if ($attribute->isInSet($setId) - && $attribute->getFrontendInput() == 'media_image') { - if ($attribute->isScopeGlobal()) { - $scope = 'global'; - } elseif ($attribute->isScopeWebsite()) { - $scope = 'website'; - } else { - $scope = 'store'; - } - - $result[] = array( - 'code' => $attribute->getAttributeCode(), - 'scope' => $scope - ); - } - } - - return $result; - } - - /** - * Retrieve gallery attribute from product - * - * @param Mage_Catalog_Model_Product $product - * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Attribute|boolean - */ - protected function _getGalleryAttribute($product) - { - $attributes = $product->getTypeInstance()->getSetAttributes(); - - if (!isset($attributes[self::ATTRIBUTE_CODE])) { - $this->_fault('not_media'); - } - - return $attributes[self::ATTRIBUTE_CODE]; - } - - /** - * Retrie - * ve media config - * - * @return Mage_Catalog_Model_Product_Media_Config - */ - protected function _getMediaConfig() - { - return Mage::getSingleton('catalog/product_media_config'); - } - - /** - * Converts image to api array data - * - * @param array $image - * @param Mage_Catalog_Model_Product $product - * @return array - */ - protected function _imageToArray(&$image, $product) - { - $result = array( - 'file' => $image['file'], - 'label' => $image['label'], - 'position' => $image['position'], - 'exclude' => $image['disabled'], - 'url' => $this->_getMediaConfig()->getMediaUrl($image['file']), - 'types' => array() - ); - - - foreach ($product->getMediaAttributes() as $attribute) { - if ($product->getData($attribute->getAttributeCode()) == $image['file']) { - $result['types'][] = $attribute->getAttributeCode(); - } - } - - return $result; - } - - /** - * Retrieve product - * - * @param int|string $productId - * @param string|int $store - * @return Mage_Catalog_Model_Product - */ - protected function _initProduct($productId, $store = null) - { - $product = Mage::getModel('catalog/product') - ->setStoreId($this->_getStoreId($store)); - - $idBySku = $product->getIdBySku($productId); - if ($idBySku) { - $productId = $idBySku; - } - /* @var $product Mage_Catalog_Model_Product */ - - $product->load($productId); - - if (!$product->getId()) { - $this->_fault('product_not_exists'); - } - - return $product; - } + + */ +class Mage_Catalog_Model_Product_Attribute_Media_Api extends Mage_Catalog_Model_Api_Resource +{ + /** + * Attribute code for media gallery + * + */ + const ATTRIBUTE_CODE = 'media_gallery'; + + /** + * Allowed mime types for image + * + * @var array + */ + protected $_mimeTypes = array( + 'image/jpeg' => 'jpg', + 'image/gif' => 'gif', + 'image/png' => 'png' + ); + + public function __construct() + { + $this->_storeIdSessionField = 'product_store_id'; + } + + /** + * Retrieve images for product + * + * @param int|string $productId + * @param string|int $store + * @return array + */ + public function items($productId, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + $galleryData = $product->getData(self::ATTRIBUTE_CODE); + + if (!isset($galleryData['images']) || !is_array($galleryData['images'])) { + return array(); + } + + $result = array(); + + foreach ($galleryData['images'] as &$image) { + $result[] = $this->_imageToArray($image, $product); + } + + return $result; + } + + /** + * Retrieve image data + * + * @param int|string $productId + * @param string $file + * @param string|int $store + * @return array + */ + public function info($productId, $file, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + if (!$image = $gallery->getBackend()->getImage($product, $file)) { + $this->_fault('not_exists'); + } + + return $this->_imageToArray($image, $product); + } + + /** + * Create new image for product and return image filename + * + * @param int|string $productId + * @param array $data + * @param string|int $store + * @return string + */ + public function create($productId, $data, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + if (!isset($data['file']) || !isset($data['file']['mime']) || !isset($data['file']['content'])) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Image not specified.')); + } + + if (!isset($this->_mimeTypes[$data['file']['mime']])) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Invalid image type.')); + } + + $fileContent = @base64_decode($data['file']['content'], true); + if (!$fileContent) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Image content is not valid base64 data.')); + } + + unset($data['file']['content']); + + $tmpDirectory = Mage::getBaseDir('var') . DS . 'api' . DS . $this->_getSession()->getSessionId(); + $fileName = 'image.' . $this->_mimeTypes[$data['file']['mime']]; + $ioAdapter = new Varien_Io_File(); + try { + // Create temporary directory for api + $ioAdapter->checkAndCreateFolder($tmpDirectory); + $ioAdapter->open(array('path'=>$tmpDirectory)); + // Write image file + $ioAdapter->write($fileName, $fileContent, 0666); + unset($fileContent); + + // Adding image to gallery + $file = $gallery->getBackend()->addImage( + $product, + $tmpDirectory . DS . $fileName, + null, + true + ); + + // Remove temporary directory + $ioAdapter->rmdir($tmpDirectory, true); + + $gallery->getBackend()->updateImage($product, $file, $data); + + if (isset($data['types'])) { + $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); + } + + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_created', $e->getMessage()); + } catch (Exception $e) { + $this->_fault('not_created', Mage::helper('catalog')->__('Can\'t create image.')); + } + + return $gallery->getBackend()->getRenamedImage($file); + } + + /** + * Update image data + * + * @param int|string $productId + * @param string $file + * @param array $data + * @param string|int $store + * @return boolean + */ + public function update($productId, $file, $data, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + if (!$gallery->getBackend()->getImage($product, $file)) { + $this->_fault('not_exists'); + } + + $gallery->getBackend()->updateImage($product, $file, $data); + + if (isset($data['types']) && is_array($data['types'])) { + $oldTypes = array(); + foreach ($product->getMediaAttributes() as $attribute) { + if ($product->getData($attribute->getAttributeCode()) == $file) { + $oldTypes[] = $attribute->getAttributeCode(); + } + } + + $clear = array_diff($oldTypes, $data['types']); + + if (count($clear) > 0) { + $gallery->getBackend()->clearMediaAttribute($product, $clear); + } + + $gallery->getBackend()->setMediaAttribute($product, $data['types'], $file); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_updated', $e->getMessage()); + } + + return true; + } + + /** + * Remove image from product + * + * @param int|string $productId + * @param string $file + * @return boolean + */ + public function remove($productId, $file) + { + $product = $this->_initProduct($productId); + + $gallery = $this->_getGalleryAttribute($product); + + if (!$gallery->getBackend()->getImage($product, $file)) { + $this->_fault('not_exists'); + } + + $gallery->getBackend()->removeImage($product, $file); + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_removed', $e->getMessage()); + } + + return true; + } + + + /** + * Retrieve image types (image, small_image, thumbnail, etc...) + * + * @param int $setId + * @return array + */ + public function types($setId) + { + $attributes = Mage::getModel('catalog/product')->getResource() + ->loadAllAttributes() + ->getSortedAttributes($setId); + + $result = array(); + + foreach ($attributes as $attribute) { + /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ + if ($attribute->isInSet($setId) + && $attribute->getFrontendInput() == 'media_image') { + if ($attribute->isScopeGlobal()) { + $scope = 'global'; + } elseif ($attribute->isScopeWebsite()) { + $scope = 'website'; + } else { + $scope = 'store'; + } + + $result[] = array( + 'code' => $attribute->getAttributeCode(), + 'scope' => $scope + ); + } + } + + return $result; + } + + /** + * Retrieve gallery attribute from product + * + * @param Mage_Catalog_Model_Product $product + * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Attribute|boolean + */ + protected function _getGalleryAttribute($product) + { + $attributes = $product->getTypeInstance(true) + ->getSetAttributes($product); + + if (!isset($attributes[self::ATTRIBUTE_CODE])) { + $this->_fault('not_media'); + } + + return $attributes[self::ATTRIBUTE_CODE]; + } + + /** + * Retrie + * ve media config + * + * @return Mage_Catalog_Model_Product_Media_Config + */ + protected function _getMediaConfig() + { + return Mage::getSingleton('catalog/product_media_config'); + } + + /** + * Converts image to api array data + * + * @param array $image + * @param Mage_Catalog_Model_Product $product + * @return array + */ + protected function _imageToArray(&$image, $product) + { + $result = array( + 'file' => $image['file'], + 'label' => $image['label'], + 'position' => $image['position'], + 'exclude' => $image['disabled'], + 'url' => $this->_getMediaConfig()->getMediaUrl($image['file']), + 'types' => array() + ); + + + foreach ($product->getMediaAttributes() as $attribute) { + if ($product->getData($attribute->getAttributeCode()) == $image['file']) { + $result['types'][] = $attribute->getAttributeCode(); + } + } + + return $result; + } + + /** + * Retrieve product + * + * @param int|string $productId + * @param string|int $store + * @return Mage_Catalog_Model_Product + */ + protected function _initProduct($productId, $store = null) + { + $product = Mage::getModel('catalog/product') + ->setStoreId($this->_getStoreId($store)); + + $idBySku = $product->getIdBySku($productId); + if ($idBySku) { + $productId = $idBySku; + } + /* @var $product Mage_Catalog_Model_Product */ + + $product->load($productId); + + if (!$product->getId()) { + $this->_fault('product_not_exists'); + } + + return $product; + } } // Class Mage_Catalog_Model_Product_Attribute_Media_Api End \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php new file mode 100644 index 0000000000..9da997471d --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api/V2.php @@ -0,0 +1,177 @@ + + */ +class Mage_Catalog_Model_Product_Attribute_Media_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Media_Api +{ + /** + * Prepare data to create or update image + * + * @param stdClass $data + * @return array + */ + protected function _prepareImageData($data) + { + $_imageData = array(); + if (isset($data->label)) { + $_imageData['label'] = $data->label; + } + if (isset($data->position)) { + $_imageData['position'] = $data->position; + } + if (isset($data->disabled)) { + $_imageData['disabled'] = $data->disabled; + } + if (isset($data->exclude)) { + $_imageData['exclude'] = $data->exclude; + } + return $_imageData; + } + + /** + * Create new image for product and return image filename + * + * @param int|string $productId + * @param array $data + * @param string|int $store + * @return string + */ + public function create($productId, $data, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + if (!isset($data->file) || !isset($data->file->mime) || !isset($data->file->content)) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Image not specified.')); + } + + if (!isset($this->_mimeTypes[$data->file->mime])) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Invalid image type.')); + } + + $fileContent = @base64_decode($data->file->content, true); + if (!$fileContent) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Image content is not valid base64 data.')); + } + + unset($data->file->content); + + $tmpDirectory = Mage::getBaseDir('var') . DS . 'api' . DS . $this->_getSession()->getSessionId(); + $fileName = 'image.' . $this->_mimeTypes[$data->file->mime]; + $ioAdapter = new Varien_Io_File(); + try { + // Create temporary directory for api + $ioAdapter->checkAndCreateFolder($tmpDirectory); + $ioAdapter->open(array('path'=>$tmpDirectory)); + // Write image file + $ioAdapter->write($fileName, $fileContent, 0666); + unset($fileContent); + + // Adding image to gallery + $file = $gallery->getBackend()->addImage( + $product, + $tmpDirectory . DS . $fileName, + null, + true + ); + + // Remove temporary directory + $ioAdapter->rmdir($tmpDirectory, true); + + $_imageData = $this->_prepareImageData($data); + + $gallery->getBackend()->updateImage($product, $file, $_imageData); + + if (isset($data->types)) { + $gallery->getBackend()->setMediaAttribute($product, $data->types, $file); + } + + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_created', $e->getMessage()); + } catch (Exception $e) { + $this->_fault('not_created', Mage::helper('catalog')->__('Can\'t create image.')); + } + + return $gallery->getBackend()->getRenamedImage($file); + } + + /** + * Update image data + * + * @param int|string $productId + * @param string $file + * @param array $data + * @param string|int $store + * @return boolean + */ + public function update($productId, $file, $data, $store = null) + { + $product = $this->_initProduct($productId, $store); + + $gallery = $this->_getGalleryAttribute($product); + + if (!$gallery->getBackend()->getImage($product, $file)) { + $this->_fault('not_exists'); + } + + $_imageData = $this->_prepareImageData($data); + + $gallery->getBackend()->updateImage($product, $file, $_imageData); + + if (isset($data->types) && is_array($data->types)) { + $oldTypes = array(); + foreach ($product->getMediaAttributes() as $attribute) { + if ($product->getData($attribute->getAttributeCode()) == $file) { + $oldTypes[] = $attribute->getAttributeCode(); + } + } + + $clear = array_diff($oldTypes, $data->types); + + if (count($clear) > 0) { + $gallery->getBackend()->clearMediaAttribute($product, $clear); + } + + $gallery->getBackend()->setMediaAttribute($product, $data->types, $file); + } + + try { + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_updated', $e->getMessage()); + } + + return true; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php new file mode 100644 index 0000000000..290dc3c03f --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Catalog_Model_Product_Attribute_Set_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Set_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php new file mode 100644 index 0000000000..dd9bf3d9af --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.php @@ -0,0 +1,105 @@ + + */ +class Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Tierprice_Api +{ + /** + * Update tier prices of product + * + * @param int|string $productId + * @param array $tierPrices + * @return boolean + */ + public function update($productId, $tierPrices) + { + Mage::log($tierPrices); + $product = $this->_initProduct($productId); + if (!is_array($tierPrices)) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Invalid Tier Prices')); + } + + $updateValue = array(); + + foreach ($tierPrices as $tierPrice) { + if (!is_object($tierPrice) + || !isset($tierPrice->qty) + || !isset($tierPrice->price)) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Invalid Tier Prices')); + } + + if (!isset($tierPrice->website) || $tierPrice->website == 'all') { + $tierPrice->website = 0; + } else { + try { + $tierPrice->website = Mage::app()->getWebsite($tierPrice->website)->getId(); + } catch (Mage_Core_Exception $e) { + $tierPrice->website = 0; + } + } + + if (!isset($tierPrice->customer_group_id)) { + $tierPrice->customer_group_id = 'all'; + } + + if ($tierPrice->customer_group_id == 'all') { + $tierPrice->customer_group_id = Mage_Customer_Model_Group::CUST_GROUP_ALL; + } + + $updateValue[] = array( + 'website_id' => $tierPrice->website, + 'cust_group' => $tierPrice->customer_group_id, + 'price_qty' => $tierPrice->qty, + 'price' => $tierPrice->price + ); + + } + + try { + if (is_array($errors = $product->validate())) { + $this->_fault('data_invalid', implode("\n", $errors)); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + try { + $product->setData(self::ATTRIBUTE_CODE ,$updateValue); + $product->validate(); + $product->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_updated', $e->getMessage()); + } + + return true; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Compare/Item.php b/app/code/core/Mage/Catalog/Model/Product/Compare/Item.php index c9a99d1c75..70fa05e758 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Compare/Item.php +++ b/app/code/core/Mage/Catalog/Model/Product/Compare/Item.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -30,16 +30,25 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Model_Product_Compare_Item extends Mage_Core_Model_Abstract { - + /** + * Initialize resourse model + * + */ protected function _construct() { $this->_init('catalog/product_compare_item'); } + /** + * Add customer data from customer object + * + * @param Mage_Customer_Model_Customer $customer + * @return Mage_Catalog_Model_Product_Compare_Item + */ public function addCustomerData(Mage_Customer_Model_Customer $customer) { $this->setCustomerId($customer->getId()); @@ -47,18 +56,36 @@ public function addCustomerData(Mage_Customer_Model_Customer $customer) return $this; } + /** + * Set visitor + * + * @param int $visitorId + * @return Mage_Catalog_Model_Product_Compare_Item + */ public function addVisitorId($visitorId) { $this->setVisitorId($visitorId); return $this; } + /** + * Load compare item by product + * + * @param mixed $product + * @return Mage_Catalog_Model_Product_Compare_Item + */ public function loadByProduct($product) { - $this->_getResource()->loadByProduct($this,$product); + $this->_getResource()->loadByProduct($this, $product); return $this; } + /** + * Set product data + * + * @param mixed $product + * @return Mage_Catalog_Model_Product_Compare_Item + */ public function addProductData($product) { if ($product instanceof Mage_Catalog_Model_Product) { @@ -71,6 +98,11 @@ public function addProductData($product) return $this; } + /** + * Retrieve data for save + * + * @return array + */ public function getDataForSave() { $data = array(); @@ -81,6 +113,11 @@ public function getDataForSave() return $data; } + /** + * Customer login bind process + * + * @return Mage_Catalog_Model_Product_Compare_Item + */ public function bindCustomerLogin() { $customer = Mage::getSingleton('customer/session')->getCustomer(); @@ -106,6 +143,8 @@ public function bindCustomerLogin() ->save(); } } + + Mage::helper('catalog/product_compare')->calculate(); return $this; } @@ -116,7 +155,7 @@ public function bindCustomerLogin() */ public function clean() { - $this->getResource()->clean($this); + $this->_getResource()->clean($this); return $this; } } diff --git a/app/code/core/Mage/Catalog/Model/Product/Flat/Flag.php b/app/code/core/Mage/Catalog/Model/Product/Flat/Flag.php new file mode 100644 index 0000000000..b426dffd4c --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Flat/Flag.php @@ -0,0 +1,84 @@ + + */ +class Mage_Catalog_Model_Product_Flat_Flag extends Mage_Core_Model_Flag +{ + /** + * Flag code + * + * @var string + */ + protected $_flagCode = 'catalog_product_flat'; + + /** + * Retrieve flag data array + * + * @return array + */ + public function getFlagData() { + $flagData = parent::getFlagData(); + if (!is_array($flagData)) { + $flagData = array(); + $this->setFlagData($flagData); + } + return $flagData; + } + + /** + * Retrieve Catalog Product Flat is built flag + * + * @return bool + */ + public function getIsBuilt() { + $flagData = $this->getFlagData(); + if (!isset($flagData['is_built'])) { + $flagData['is_built'] = false; + $this->setFlagData($flagData); + } + return (bool)$flagData['is_built']; + } + + /** + * Set Catalog Product Flat is built flag + * + * @param bool $flag + * @return Mage_Catalog_Model_Product_Flat_Flag + */ + public function setIsBuild($flag) { + $flagData = $this->getFlagData(); + $flagData['is_built'] = (bool)$flag; + $this->setFlagData($flagData); + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Flat/Indexer.php b/app/code/core/Mage/Catalog/Model/Product/Flat/Indexer.php new file mode 100644 index 0000000000..b3328e6a0c --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Flat/Indexer.php @@ -0,0 +1,243 @@ + + */ +class Mage_Catalog_Model_Product_Flat_Indexer extends Mage_Core_Model_Abstract +{ + /** + * Standart model resource initialization + * + */ + protected function _construct() + { + $this->_init('catalog/product_flat_indexer'); + } + + /** + * Get resource instance + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + protected function _getResource() + { + return parent::_getResource(); + } + + /** + * Rebuild Catalog Product Flat Data + * + * @param mixed $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function rebuild($store = null) + { + $this->_getResource()->rebuild($store); + return $this; + } + + /** + * Update attribute data for flat table + * + * @param string $attributeCode + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function updateAttribute($attributeCode, $store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->updateAttribute($attributeCode, $store->getId()); + } + + return $this; + } + + $this->_getResource()->prepareFlatTable($store); + $attribute = $this->_getResource()->getAttribute($attributeCode); + $this->_getResource()->updateAttribute($attribute, $store); + $this->_getResource()->updateChildrenDataFromParent($store); + + return $this; + } + + /** + * Prepare datastorage for catalog product flat + * + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function prepareDataStorage($store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->prepareDataStorage($store->getId()); + } + + return $this; + } + + $this->_getResource()->prepareFlatTable($store); + + return $this; + } + + /** + * Update events observer attributes + * + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function updateEventAttributes($store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->updateEventAttributes($store->getId()); + } + + return $this; + } + + $this->_getResource()->prepareFlatTable($store); + $this->_getResource()->updateEventAttributes($store); + $this->_getResource()->updateRelationProducts($store); + + return $this; + } + + /** + * Update product status + * + * @param int $productId + * @param int $status + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function updateProductStatus($productId, $status, $store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->updateProductStatus($productId, $status, $store->getId()); + } + return $this; + } + + if ($status == Mage_Catalog_Model_Product_Status::STATUS_ENABLED) { + $this->_getResource()->updateProduct($productId, $store); + $this->_getResource()->updateChildrenDataFromParent($store, $productId); + } + else { + $this->_getResource()->removeProduct($productId, $store); + } + + return $this; + } + + /** + * Update Catalog Product Flat data + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function updateProduct($productIds, $store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->updateProduct($productIds, $store->getId()); + } + return $this; + } + + $this->_getResource()->removeProduct($productIds, $store); + $this->_getResource()->updateProduct($productIds, $store); + $this->_getResource()->updateRelationProducts($store, $productIds); + + return $this; + } + + /** + * Save Catalog Product(s) Flat data + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function saveProduct($productIds, $store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->saveProduct($productIds, $store->getId()); + } + return $this; + } + + $this->_getResource()->removeProduct($productIds, $store); + $this->_getResource()->saveProduct($productIds, $store); + $this->_getResource()->updateRelationProducts($store, $productIds); + + return $this; + } + + /** + * Remove product from flat + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function removeProduct($productIds, $store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->removeProduct($productIds, $store->getId()); + } + return $this; + } + + $this->_getResource()->removeProduct($productIds, $store); + + return $this; + } + + /** + * Delete store process + * + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function deleteStore($store) + { + $this->_getResource()->deleteFlatTable($store); + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Flat/Observer.php b/app/code/core/Mage/Catalog/Model/Product/Flat/Observer.php new file mode 100644 index 0000000000..074949adbc --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Flat/Observer.php @@ -0,0 +1,290 @@ + + */ +class Mage_Catalog_Model_Product_Flat_Observer +{ + /** + * Retrieve Catalog Product Flat Helper + * + * @return Mage_Catalog_Helper_Product_Flat + */ + protected function _getHelper() + { + return Mage::helper('catalog/product_flat'); + } + + /** + * Retrieve Catalog Product Flat Indexer model + * + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + protected function _getIndexer() { + return Mage::getSingleton('catalog/product_flat_indexer'); + } + + /** + * Catalog Entity attribute after save process + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function catalogEntityAttributeSaveAfter(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $attribute = $observer->getEvent()->getAttribute(); + /* @var $attribute Mage_Catalog_Model_Entity_Attribute */ + + $enableBefore = ($attribute->getOrigData('backend_type') == 'static') + || ($attribute->getOrigData('is_filterable') > 0) + || ($attribute->getOrigData('is_filterable_in_search') == 1) + || ($attribute->getOrigData('used_in_product_listing') == 1) + || ($attribute->getOrigData('used_for_sort_by') == 1); + $enableAfter = ($attribute->getData('backend_type') == 'static') + || ($attribute->getData('is_filterable') > 0) + || ($attribute->getData('is_filterable_in_search') == 1) + || ($attribute->getData('used_in_product_listing') == 1) + || ($attribute->getData('used_for_sort_by') == 1); + + if (!$enableAfter && !$enableBefore) { + return $this; + } + + if ($enableBefore && !$enableAfter) { + // delete attribute data from flat + $this->_getIndexer()->prepareDataStorage(); + } + else { + $this->_getIndexer()->updateAttribute($attribute->getAttributeCode()); + } + + return $this; + } + + /** + * Catalog Product Status Update + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function catalogProductStatusUpdate(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $productId = $observer->getEvent()->getProductId(); + $status = $observer->getEvent()->getStatus(); + $storeId = $observer->getEvent()->getStoreId(); + $storeId = $storeId > 0 ? $storeId : null; + + $this->_getIndexer()->updateProductStatus($productId, $status, $storeId); + + return $this; + } + + /** + * Catalog Product Website(s) update + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function catalogProductWebsiteUpdate(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $websiteIds = $observer->getEvent()->getWebsiteIds(); + $productIds = $observer->getEvent()->getProductIds(); + + foreach ($websiteIds as $websiteId) { + $website = Mage::app()->getWebsite($websiteId); + foreach ($website->getStores() as $store) { + if ($observer->getEvent()->getAction() == 'remove') { + $this->_getIndexer()->removeProduct($productIds, $store->getId()); + } + else { + $this->_getIndexer()->updateProduct($productIds, $store->getId()); + } + } + } + + return $this; + } + + /** + * Catalog Product After Save + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function catalogProductSaveAfter(Varien_Event_Observer $observer) { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $product = $observer->getEvent()->getProduct(); + $productId = $product->getId(); + + $this->_getIndexer()->saveProduct($productId); + + return $this; + } + + /** + * Add new store flat process + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function storeAdd(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $store = $observer->getEvent()->getStore(); + /* @var $store Mage_Core_Model_Store */ + $this->_getIndexer()->rebuild($store->getId()); + + return $this; + } + + /** + * Store edit action, check change store group + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function storeEdit(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $store = $observer->getEvent()->getStore(); + /* @var $store Mage_Core_Model_Store */ + if ($store->dataHasChangedFor('group_id')) { + $this->_getIndexer()->rebuild($store->getId()); + } + + return $this; + } + + /** + * Store delete after process + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function storeDelete(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $store = $observer->getEvent()->getStore(); + /* @var $store Mage_Core_Model_Store */ + + $this->_getIndexer()->deleteStore($store->getId()); + + return $this; + } + + /** + * Store Group Save process + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function storeGroupSave(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $group = $observer->getEvent()->getGroup(); + /* @var $group Mage_Core_Model_Store_Group */ + + if ($group->dataHasChangedFor('website_id')) { + foreach ($group->getStores() as $store) { + /* @var $store Mage_Core_Model_Store */ + $this->_getIndexer()->rebuild($store->getId()); + } + } + + return $this; + } + + /** + * Catalog Product Import After process + * + * @param Varien_Event_Observer $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function catalogProductImportAfter(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $this->_getIndexer()->rebuild(); + + return $this; + } + + /** + * Customer Group save after process + * + * @param Varien_Event_Observer_Collection $observer + * @return Mage_Catalog_Model_Product_Flat_Observer + */ + public function customerGroupSaveAfter(Varien_Event_Observer $observer) + { + if (!$this->_getHelper()->isBuilt()) { + return $this; + } + + $customerGroup = $observer->getEvent()->getObject(); + /* @var $customerGroup Mage_Customer_Model_Group */ + if ($customerGroup->dataHasChangedFor($customerGroup->getIdFieldName()) + || $customerGroup->dataHasChangedFor('tax_class_id')) { + $this->_getIndexer()->updateEventAttributes(); + } + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php new file mode 100644 index 0000000000..fee59b80ed --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php @@ -0,0 +1,119 @@ + + */ +class Mage_Catalog_Model_Product_Link_Api_V2 extends Mage_Catalog_Model_Product_Link_Api +{ + /** + * Add product link association + * + * @param string $type + * @param int|string $productId + * @param int|string $linkedProductId + * @param array $data + * @return boolean + */ + public function assign($type, $productId, $linkedProductId, $data = array()) + { + $typeId = $this->_getTypeId($type); + + $product = $this->_initProduct($productId); + + $link = $product->getLinkInstance() + ->setLinkTypeId($typeId); + + $collection = $this->_initCollection($link, $product); + $idBySku = $product->getIdBySku($linkedProductId); + if ($idBySku) { + $linkedProductId = $idBySku; + } + + $links = $this->_collectionToEditableArray($collection); + + $links[(int)$linkedProductId] = array(); + foreach ($collection->getLinkModel()->getAttributes() as $attribute) { + if (isset($data->$attribute['code'])) { + $links[(int)$linkedProductId][$attribute['code']] = $data->$attribute['code']; + } + } + + try { + $link->getResource()->saveProductLinks($product, $links, $typeId); + } catch (Exception $e) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Link product not exists.')); + } + + return true; + } + + /** + * Update product link association info + * + * @param string $type + * @param int|string $productId + * @param int|string $linkedProductId + * @param array $data + * @return boolean + */ + public function update($type, $productId, $linkedProductId, $data = array()) + { + $typeId = $this->_getTypeId($type); + + $product = $this->_initProduct($productId); + + $link = $product->getLinkInstance() + ->setLinkTypeId($typeId); + + $collection = $this->_initCollection($link, $product); + + $links = $this->_collectionToEditableArray($collection); + + $idBySku = $product->getIdBySku($linkedProductId); + if ($idBySku) { + $linkedProductId = $idBySku; + } + + foreach ($collection->getLinkModel()->getAttributes() as $attribute) { + if (isset($data->$attribute['code'])) { + $links[(int)$linkedProductId][$attribute['code']] = $data->$attribute['code']; + } + } + + try { + $link->getResource()->saveProductLinks($product, $links, $typeId); + } catch (Exception $e) { + $this->_fault('data_invalid', Mage::helper('catalog')->__('Link product not exists.')); + } + + return true; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Media/Config.php b/app/code/core/Mage/Catalog/Model/Product/Media/Config.php index 0d6e4b3184..c1de7ce732 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Media/Config.php +++ b/app/code/core/Mage/Catalog/Model/Product/Media/Config.php @@ -28,84 +28,83 @@ /** * Catalog product media config * - * @category Mage - * @package Mage_Catalog + * @category Mage + * @package Mage_Catalog * @author Magento Core Team */ class Mage_Catalog_Model_Product_Media_Config implements Mage_Media_Model_Image_Config_Interface { - - public function getBaseMediaPath() - { - return Mage::getBaseDir('media') . DS . 'catalog' . DS . 'product'; - } - - public function getBaseMediaUrl() - { - return Mage::getBaseUrl('media') . 'catalog/product'; - } - - public function getBaseTmpMediaPath() - { - return Mage::getBaseDir('media') . DS . 'tmp' . DS . 'catalog' . DS . 'product'; + public function getBaseMediaPath() + { + return Mage::getBaseDir('media') . DS . 'catalog' . DS . 'product'; + } + + public function getBaseMediaUrl() + { + return Mage::getBaseUrl('media') . 'catalog/product'; + } + + public function getBaseTmpMediaPath() + { + return Mage::getBaseDir('media') . DS . 'tmp' . DS . 'catalog' . DS . 'product'; + } + + public function getBaseTmpMediaUrl() + { + return Mage::getBaseUrl('media') . 'tmp/catalog/product'; + } + + public function getMediaUrl($file) + { + $file = $this->_prepareFileForUrl($file); + + if(substr($file, 0, 1) == '/') { + return $this->getBaseMediaUrl() . $file; } - public function getBaseTmpMediaUrl() - { - return Mage::getBaseUrl('media') . 'tmp/catalog/product'; - } - - public function getMediaUrl($file) - { - $file = $this->_prepareFileForUrl($file); + return $this->getBaseMediaUrl() . '/' . $file; + } - if(substr($file, 0, 1) == '/') { - return $this->getBaseMediaUrl() . $file; - } + public function getMediaPath($file) + { + $file = $this->_prepareFileForPath($file); - return $this->getBaseMediaUrl() . '/' . $file; + if(substr($file, 0, 1) == DS) { + return $this->getBaseMediaPath() . DS . substr($file, 1); } - public function getMediaPath($file) - { - $file = $this->_prepareFileForPath($file); + return $this->getBaseMediaPath() . DS . $file; + } - if(substr($file, 0, 1) == DS) { - return $this->getBaseMediaPath() . DS . substr($file, 1); - } + public function getTmpMediaUrl($file) + { + $file = $this->_prepareFileForUrl($file); - return $this->getBaseMediaPath() . DS . $file; + if(substr($file, 0, 1) == '/') { + return $this->getBaseTmpMediaUrl() . $file; } - public function getTmpMediaUrl($file) - { - $file = $this->_prepareFileForUrl($file); + return $this->getBaseTmpMediaUrl() . '/' . $file; + } - if(substr($file, 0, 1) == '/') { - return $this->getBaseTmpMediaUrl() . $file; - } + public function getTmpMediaPath($file) + { + $file = $this->_prepareFileForPath($file); - return $this->getBaseTmpMediaUrl() . '/' . $file; + if(substr($file, 0, 1) == DS) { + return $this->getBaseTmpMediaPath() . DS . substr($file, 1); } - public function getTmpMediaPath($file) - { - $file = $this->_prepareFileForPath($file); + return $this->getBaseTmpMediaPath() . DS . $file; + } - if(substr($file, 0, 1) == DS) { - return $this->getBaseTmpMediaPath() . DS . substr($file, 1); - } - - return $this->getBaseTmpMediaPath() . DS . $file; - } + protected function _prepareFileForUrl($file) + { + return str_replace(DS, '/', $file); + } - protected function _prepareFileForUrl($file) - { - return str_replace(DS, '/', $file); - } - - protected function _prepareFileForPath($file) - { - return str_replace('/', DS, $file); - } + protected function _prepareFileForPath($file) + { + return str_replace('/', DS, $file); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option.php b/app/code/core/Mage/Catalog/Model/Product/Option.php index d780df37f5..7135fd4560 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Option.php +++ b/app/code/core/Mage/Catalog/Model/Product/Option.php @@ -168,7 +168,7 @@ public function getProduct() * @param Mage_Catalog_Model_Product $product * @return Mage_Catalog_Model_Product_Option */ - public function setProduct(Mage_Catalog_Model_Product $product) + public function setProduct(Mage_Catalog_Model_Product $product = null) { $this->_product = $product; return $this; @@ -201,6 +201,21 @@ public function getGroupByType($type = null) return isset($optionGroupsToTypes[$type])?$optionGroupsToTypes[$type]:''; } + /** + * Group model factory + * + * @param string $type Option type + * @return Mage_Catalog_Model_Product_Option_Group_Abstract + */ + public function groupFactory($type) + { + $group = $this->getGroupByType($type); + if (!empty($group)) { + return Mage::getModel('catalog/product_option_type_' . $group); + } + Mage::throwException(Mage::helper('catalog')->__('Wrong option type to get group instance.')); + } + /** * Save options. * @@ -242,6 +257,8 @@ public function saveOptions() break; case self::OPTION_GROUP_FILE: $this->setData('file_extension', ''); + $this->setData('image_size_x', '0'); + $this->setData('image_size_y', '0'); break; case self::OPTION_GROUP_TEXT: $this->setData('max_characters', '0'); diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Observer.php b/app/code/core/Mage/Catalog/Model/Product/Option/Observer.php new file mode 100644 index 0000000000..8e66c64aa1 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Observer.php @@ -0,0 +1,67 @@ + + */ +class Mage_Catalog_Model_Product_Option_Observer +{ + /** + * Copy quote custom option files to order custom option files + * + * @param Varien_Object $observer + * @return Mage_Catalog_Model_Product_Option_Observer + */ + public function copyQuoteFilesToOrderFiles($observer) + { + /* @var $quoteItem Mage_Sales_Model_Quote_Item */ + $quoteItem = $observer->getEvent()->getItem(); + + if (is_array($quoteItem->getOptions())) { + foreach ($quoteItem->getOptions() as $itemOption) { + $code = explode('_', $itemOption->getCode()); + if (isset($code[1]) && is_numeric($code[1]) && ($option = $quoteItem->getProduct()->getOptionById($code[1]))) { + if ($option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_FILE) { + /* @var $_option Mage_Catalog_Model_Product_Option */ + try { + $group = $option->groupFactory($option->getType()) + ->setQuoteItemOption($itemOption) + ->copyQuoteToOrder(); + + } catch (Exception $e) { + continue; + } + } + } + } + } + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Date.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Date.php new file mode 100644 index 0000000000..5f9e9e7804 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Date.php @@ -0,0 +1,313 @@ + + */ +class Mage_Catalog_Model_Product_Option_Type_Date extends Mage_Catalog_Model_Product_Option_Type_Default +{ + /** + * Validate user input for option + * + * @throws Mage_Core_Exception + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function validateUserValue($values) + { + parent::validateUserValue($values); + + $option = $this->getOption(); + $value = $this->getUserValue(); + + $dateValid = true; + if ($this->_dateExists()) { + if ($this->useCalendar()) { + $dateValid = isset($value['date']) && preg_match('/^[0-9]{1,4}.+[0-9]{1,4}.+[0-9]{1,4}$/', $value['date']); + } else { + $dateValid = isset($value['day']) && isset($value['month']) && isset($value['year']) + && $value['day'] > 0 && $value['month'] > 0 && $value['year'] > 0; + } + } + + $timeValid = true; + if ($this->_timeExists()) { + $timeValid = isset($value['hour']) && isset($value['minute']) + && is_numeric($value['hour']) && is_numeric($value['minute']); + } + + $isValid = $dateValid && $timeValid; + + if ($isValid) { + $this->setUserValue( + array( + 'date' => isset($value['date']) ? $value['date'] : '', + 'year' => isset($value['year']) ? intval($value['year']) : 0, + 'month' => isset($value['month']) ? intval($value['month']) : 0, + 'day' => isset($value['day']) ? intval($value['day']) : 0, + 'hour' => isset($value['hour']) ? intval($value['hour']) : 0, + 'minute' => isset($value['minute']) ? intval($value['minute']) : 0, + 'day_part' => isset($value['day_part']) ? $value['day_part'] : '', + 'date_internal' => isset($value['date_internal']) ? $value['date_internal'] : '', + ) + ); + } elseif (!$isValid && $option->getIsRequire() && !$this->getProduct()->getSkipCheckRequiredOption()) { + $this->setIsValid(false); + if (!$dateValid) { + Mage::throwException(Mage::helper('catalog')->__('Please specify date required option(s)')); + } elseif (!$timeValid) { + Mage::throwException(Mage::helper('catalog')->__('Please specify time required option(s)')); + } else { + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } + } else { + $this->setUserValue(null); + return $this; + } + + return $this; + } + + /** + * Prepare option value for cart + * + * @throws Mage_Core_Exception + * @return mixed Prepared option value + */ + public function prepareForCart() + { + if ($this->getIsValid() && $this->getUserValue() !== null) { + $option = $this->getOption(); + $value = $this->getUserValue(); + + if (isset($value['date_internal']) && $value['date_internal'] != '') { + $this->_setInternalInRequest($value['date_internal']); + return $value['date_internal']; + } + + $timestamp = 0; + + if ($this->_dateExists()) { + if ($this->useCalendar()) { + $format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); + $timestamp += Mage::app()->getLocale()->date($value['date'], $format, null, false)->getTimestamp(); + } else { + $timestamp += mktime(0, 0, 0, $value['month'], $value['day'], $value['year']); + } + } else { + $timestamp += mktime(0, 0, 0, date('m'), date('d'), date('Y')); + } + + if ($this->_timeExists()) { + $hour = $this->is24hTimeFormat() ? $value['hour'] : $value['hour'] + 12; + $timestamp += 60 * 60 * $hour + 60 * $value['minute']; + } + + $date = new Zend_Date($timestamp); + $result = $date->toString(Varien_date::DATETIME_INTERNAL_FORMAT); + + // Save date in internal format to avoid locale date bugs + $this->_setInternalInRequest($result); + + return $result; + } else { + return null; + } + } + + /** + * Return formatted option value for quote option + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getFormattedOptionValue($optionValue) + { + $option = $this->getOption(); + + if ($this->getOption()->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE) { + $format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM); + $result = Mage::app()->getLocale()->date($optionValue, Zend_Date::ISO_8601, null, false)->toString($format); + } elseif ($this->getOption()->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE_TIME) { + $format = Mage::app()->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); + $result = Mage::app()->getLocale()->date($optionValue, Varien_Date::DATETIME_INTERNAL_FORMAT, null, false)->toString($format); + } elseif ($this->getOption()->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_TIME) { + $date = new Zend_Date($optionValue); + $result = date($this->is24hTimeFormat() ? 'H:i' : 'h:i a', $date->getTimestamp()); + } else { + $result = $optionValue; + } + return $result; + } + + /** + * Return formatted option value ready to edit, ready to parse + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getEditableOptionValue($optionValue) + { + return $this->getFormattedOptionValue($optionValue); + } + + /** + * Parse user input value and return cart prepared value + * + * @param string $optionValue + * @param array $productOptionValues Values for product option + * @return string|null + */ + public function parseOptionValue($optionValue, $productOptionValues) + { + $timestamp = strtotime($optionValue); + if ($timestamp === false || $timestamp == -1) { + return null; + } + + $date = new Zend_Date($timestamp); + return $date->toString(Varien_date::DATETIME_INTERNAL_FORMAT); + } + + /** + * Prepare option value for info buy request + * + * @param string $optionValue + * @return mixed + */ + public function prepareOptionValueForRequest($optionValue) + { +// return array('date_internal' => $optionValue); + $quoteItem = $this->getQuoteItem(); + $infoBuyRequest = $quoteItem->getOptionByCode('info_buyRequest'); + try { + $value = unserialize($infoBuyRequest->getValue()); + if (is_array($value) && isset($value['options']) && isset($value['options'][$this->getOption()->getId()])) { + return $value['options'][$this->getOption()->getId()]; + } else { + return array('date_internal' => $optionValue); + } + } catch (Exception $e) { + return array('date_internal' => $optionValue); + } + } + + /** + * Use Calendar on frontend or not + * + * @return boolean + */ + public function useCalendar() + { + return (bool)$this->getConfigData('use_calendar'); + } + + /** + * Time Format + * + * @return boolean + */ + public function is24hTimeFormat() + { + return (bool)($this->getConfigData('time_format') == '24h'); + } + + /** + * Year range start + * + * @return mixed + */ + public function getYearStart() + { + $_range = explode(',', $this->getConfigData('year_range')); + if (isset($_range[0]) && !empty($_range[0])) { + return $_range[0]; + } else { + return date('Y'); + } + } + + /** + * Year range end + * + * @return mixed + */ + public function getYearEnd() + { + $_range = explode(',', $this->getConfigData('year_range')); + if (isset($_range[1]) && !empty($_range[1])) { + return $_range[1]; + } else { + return date('Y'); + } + } + + /** + * Save internal value of option in infoBuy_request + * + * @param string $internalValue Datetime value in internal format + * @return Mage_Catalog_Model_Product_Option_Type_Date + */ + protected function _setInternalInRequest($internalValue) + { + $requestOptions = $this->getRequest()->getOptions(); + if (!isset($requestOptions[$this->getOption()->getId()])) { + $requestOptions[$this->getOption()->getId()] = array(); + } + $requestOptions[$this->getOption()->getId()]['date_internal'] = $internalValue; + $this->getRequest()->setOptions($requestOptions); + } + + /** + * Does option have date? + * + * @return boolean + */ + protected function _dateExists() + { + return in_array($this->getOption()->getType(), array( + Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE, + Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE_TIME + )); + } + + /** + * Does option have time? + * + * @return boolean + */ + protected function _timeExists() + { + return in_array($this->getOption()->getType(), array( + Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE_TIME, + Mage_Catalog_Model_Product_Option::OPTION_TYPE_TIME + )); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php new file mode 100644 index 0000000000..53dd268bc0 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Default.php @@ -0,0 +1,320 @@ + + */ +class Mage_Catalog_Model_Product_Option_Type_Default extends Varien_Object +{ + /** + * Option Instance + * + * @var Mage_Catalog_Model_Product_Option + */ + protected $_option; + + /** + * Product Instance + * + * @var Mage_Catalog_Model_Product + */ + protected $_product; + + + + /** + * description + * + * @var mixed + */ + protected $_productOptions = array(); + + /** + * Option Instance setter + * + * @param Mage_Catalog_Model_Product_Option $option + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function setOption($option) + { + $this->_option = $option; + return $this; + } + + /** + * Option Instance getter + * + * @throws Mage_Core_Exception + * @return Mage_Catalog_Model_Product_Option + */ + public function getOption() + { + if ($this->_option instanceof Mage_Catalog_Model_Product_Option) { + return $this->_option; + } + Mage::throwException(Mage::helper('catalog')->__('Wrong option instance type in options group')); + } + + /** + * Product Instance setter + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function setProduct($product) + { + $this->_product = $product; + return $this; + } + + /** + * Product Instance getter + * + * @throws Mage_Core_Exception + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + if ($this->_product instanceof Mage_Catalog_Model_Product) { + return $this->_product; + } + Mage::throwException(Mage::helper('catalog')->__('Wrong product instance type in options group')); + } + + /** + * Getter for Quote Item Option + * + * @return Mage_Sales_Model_Quote_Item_Option + */ + public function getQuoteItemOption() + { + if ($this->_getData('quote_item_option') instanceof Mage_Sales_Model_Quote_Item_Option) { + return $this->_getData('quote_item_option'); + } + Mage::throwException(Mage::helper('catalog')->__('Wrong quote item option instance in options group')); + } + + /** + * Getter for Quote Item + * + * @return Mage_Sales_Model_Quote_Item + */ + public function getQuoteItem() + { + if ($this->_getData('quote_item') instanceof Mage_Sales_Model_Quote_Item) { + return $this->_getData('quote_item'); + } + Mage::throwException(Mage::helper('catalog')->__('Wrong quote item instance in options group')); + } + + /** + * Getter for Buy Request + * + * @return Varien_Object + */ + public function getRequest() + { + if ($this->_getData('request') instanceof Varien_Object) { + return $this->_getData('request'); + } + Mage::throwException(Mage::helper('catalog')->__('Wrong BuyRequest instance in options group')); + } + + /** + * Store Config value + * + * @param string $key Config value key + * @return string + */ + public function getConfigData($key) + { + return Mage::getStoreConfig('catalog/custom_options/' . $key); + } + + /** + * Validate user input for option + * + * @throws Mage_Core_Exception + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function validateUserValue($values) + { + Mage::getSingleton('checkout/session')->setUseNotice(false); + + $this->setIsValid(false); + + $option = $this->getOption(); + if (!isset($values[$option->getId()]) && $option->getIsRequire() && !$this->getProduct()->getSkipCheckRequiredOption()) { + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } elseif (isset($values[$option->getId()])) { + $this->setUserValue($values[$option->getId()]); + $this->setIsValid(true); + } + return $this; + } + + /** + * Prepare option value for cart + * + * @throws Mage_Core_Exception + * @return mixed Prepared option value + */ + public function prepareForCart() + { + if ($this->getIsValid()) { + return $this->getUserValue(); + } + Mage::throwException(Mage::helper('catalog')->__('Option validation failed to add product to cart')); + } + + /** + * Return formatted option value for quote option + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getFormattedOptionValue($optionValue) + { + return $optionValue; + } + + /** + * Return formatted option value ready to edit, ready to parse + * (ex: Admin re-order, see Mage_Adminhtml_Model_Sales_Order_Create) + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getEditableOptionValue($optionValue) + { + return $optionValue; + } + + /** + * Parse user input value and return cart prepared value, i.e. "one, two" => "1,2" + * + * @param string $optionValue + * @param array $productOptionValues Values for product option + * @return string|null + */ + public function parseOptionValue($optionValue, $productOptionValues) + { + return $optionValue; + } + + /** + * Prepare option value for info buy request + * + * @param string $optionValue + * @return mixed + */ + public function prepareOptionValueForRequest($optionValue) + { + return $optionValue; + } + + /** + * Return Price for selected option + * + * @param string $optionValue Prepared for cart option value + * @param float $basePrice For percent price type + * @return float + */ + public function getOptionPrice($optionValue, $basePrice) + { + $option = $this->getOption(); + + return $this->_getChargableOptionPrice( + $option->getPrice(), + $option->getPriceType() == 'percent', + $basePrice + ); + } + + /** + * Return SKU for selected option + * + * @param string $optionValue Prepared for cart option value + * @param string $skuDelimiter Delimiter for Sku parts + * @return string + */ + public function getOptionSku($optionValue, $skuDelimiter) + { + return $this->getOption()->getSku(); + } + + /** + * Return value => key all product options (using for parsing) + * + * @return array Array of Product custom options, reversing option values and option ids + */ + public function getProductOptions() + { + if (!isset($this->_productOptions[$this->getProduct()->getId()])) { + foreach ($this->getProduct()->getOptions() as $_option) { + /* @var $option Mage_Catalog_Model_Product_Option */ + $this->_productOptions[$this->getProduct()->getId()][$_option->getTitle()] = array('option_id' => $_option->getId()); + if ($_option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { + $optionValues = array(); + foreach ($_option->getValues() as $_value) { + /* @var $value Mage_Catalog_Model_Product_Option_Value */ + $optionValues[$_value->getTitle()] = $_value->getId(); + } + $this->_productOptions[$this->getProduct()->getId()][$_option->getTitle()]['values'] = $optionValues; + } else { + $this->_productOptions[$this->getProduct()->getId()][$_option->getTitle()]['values'] = array(); + } + } + } + if (isset($this->_productOptions[$this->getProduct()->getId()])) { + return $this->_productOptions[$this->getProduct()->getId()]; + } + return array(); + } + + /** + * Return final chargable price for option + * + * @param float $price Price of option + * @param boolean $isPercent Price type - percent or fixed + * @param float $basePrice For percent price type + * @return float + */ + protected function _getChargableOptionPrice($price, $isPercent, $basePrice) + { + if($isPercent) { + return ($basePrice * $price / 100); + } else { + return $price; + } + } + +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php new file mode 100644 index 0000000000..a9ecc21f0a --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php @@ -0,0 +1,443 @@ + + */ +class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Product_Option_Type_Default +{ + /** + * Validate user input for option + * + * @throws Mage_Core_Exception + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function validateUserValue($values) + { + Mage::getSingleton('checkout/session')->setUseNotice(false); + + $this->setIsValid(true); + $option = $this->getOption(); + + // Set option value from request (Admin/Front reorders) + if (isset($values[$option->getId()]) && is_array($values[$option->getId()])) { + if (isset($values[$option->getId()]['order_path'])) { + $orderFileFullPath = Mage::getBaseDir() . $values[$option->getId()]['order_path']; + } else { + $this->setUserValue(null); + return $this; + } + + $ok = is_file($orderFileFullPath) && is_readable($orderFileFullPath) + && isset($values[$option->getId()]['secret_key']) + && substr(md5(file_get_contents($orderFileFullPath)), 0, 20) == $values[$option->getId()]['secret_key']; + + $this->setUserValue($ok ? $values[$option->getId()] : null); + return $this; + } elseif ($this->getProduct()->getSkipCheckRequiredOption()) { + $this->setUserValue(null); + return $this; + } + + /** + * Upload init + */ + $upload = new Zend_File_Transfer_Adapter_Http(); + $file = 'options_' . $option->getId() . '_file'; + + try { + $runValidation = $option->getIsRequire() || $upload->isUploaded($file); + if (!$runValidation) { + $this->setUserValue(null); + return $this; + } + + $fileInfo = $upload->getFileInfo($file); + $fileInfo = $fileInfo[$file]; + + } catch (Exception $e) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__("Files upload failed")); + } + + /** + * Option Validations + */ + + // Image dimensions + $_dimentions = array(); + if ($option->getImageSizeX() > 0) { + $_dimentions['maxwidth'] = $option->getImageSizeX(); + } + if ($option->getImageSizeY() > 0) { + $_dimentions['maxheight'] = $option->getImageSizeY(); + } + if (count($_dimentions) > 0) { + $upload->addValidator('ImageSize', false, $_dimentions); + } + + // File extension + $_allowed = $this->_parseExtensionsString($option->getFileExtension()); + if ($_allowed !== null) { + $upload->addValidator('Extension', false, $_allowed); + } else { + $_forbidden = $this->_parseExtensionsString($this->getConfigData('forbidden_extensions')); + if ($_forbidden !== null) { + $upload->addValidator('ExcludeExtension', false, $_forbidden); + } + } + + /** + * Upload process + */ + + $this->_initFilesystem(); + + if ($upload->isUploaded($file) && $upload->isValid($file)) { + + $extension = pathinfo(strtolower($fileInfo['name']), PATHINFO_EXTENSION); + + $fileName = Varien_File_Uploader::getCorrectFileName($fileInfo['name']); + $dispersion = Varien_File_Uploader::getDispretionPath($fileName); + + $filePath = $dispersion; + $destination = $this->getQuoteTargetDir() . $filePath; + $this->_createWriteableDir($destination); + $upload->setDestination($destination); + + $fileHash = md5(file_get_contents($fileInfo['tmp_name'])); + $filePath .= DS . $fileHash . '.' . $extension; + + $fileFullPath = $this->getQuoteTargetDir() . $filePath; + + $upload->addFilter('Rename', array( + 'target' => $fileFullPath, + 'overwrite' => true + )); + if (!$upload->receive()) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__("File upload failed")); + } + + $_imageSize = @getimagesize($fileFullPath); + if (is_array($_imageSize) && count($_imageSize) > 0) { + $_width = $_imageSize[0]; + $_height = $_imageSize[1]; + } else { + $_width = 0; + $_height = 0; + } + + $this->setUserValue(array( + 'type' => $fileInfo['type'], + 'title' => $fileInfo['name'], + 'quote_path' => $this->getQuoteTargetDir(true) . $filePath, + 'order_path' => $this->getOrderTargetDir(true) . $filePath, + 'fullpath' => $fileFullPath, + 'size' => $fileInfo['size'], + 'width' => $_width, + 'height' => $_height, + 'secret_key' => substr($fileHash, 0, 20) + )); + + } elseif ($upload->getErrors()) { + $errors = array(); + foreach ($upload->getErrors() as $errorCode) { + if ($errorCode == Zend_Validate_File_ExcludeExtension::FALSE_EXTENSION) { + $errors[] = Mage::helper('catalog')->__("The file '%s' for '%s' has an invalid extension", + $fileInfo['name'], + $option->getTitle() + ); + } elseif ($errorCode == Zend_Validate_File_Extension::FALSE_EXTENSION) { + $errors[] = Mage::helper('catalog')->__("The file '%s' for '%s' has an invalid extension", + $fileInfo['name'], + $option->getTitle() + ); + } elseif ($errorCode == Zend_Validate_File_ImageSize::WIDTH_TOO_BIG + || $errorCode == Zend_Validate_File_ImageSize::WIDTH_TOO_BIG) + { + $errors[] = Mage::helper('catalog')->__("Maximum allowed image size for '%s' is %sx%s px.", + $option->getTitle(), + $option->getImageSizeX(), + $option->getImageSizeY() + ); + } + } + if (count($errors) > 0) { + $this->setIsValid(false); + Mage::throwException( implode("\n", $errors) ); + } + } else { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } + return $this; + } + + /** + * Prepare option value for cart + * + * @return mixed Prepared option value + */ + public function prepareForCart() + { + if ($this->getIsValid() && $this->getUserValue() !== null) { + $value = $this->getUserValue(); + // Save option in request, because we have no $_FILES['options'] + $requestOptions = $this->getRequest()->getOptions(); + $requestOptions[$this->getOption()->getId()] = $value; + $this->getRequest()->setOptions($requestOptions); + return serialize($value); + } else { + return null; + } + } + + /** + * Return formatted option value for quote option + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getFormattedOptionValue($optionValue) + { + try { + $value = unserialize($optionValue); + if ($value !== false) { + if ($value['width'] > 0 && $value['height'] > 0) { + $sizes = $value['width'] . ' x ' . $value['height'] . ' ' . Mage::helper('catalog')->__('px.'); + } else { + $sizes = ''; + } + $result = sprintf('%s %s', + $this->_getOptionDownloadUrl($value['secret_key']), + Mage::helper('core')->htmlEscape($value['title']), + $sizes + ); + return $result; + } + + throw new Exception(); + + } catch (Exception $e) { + return $optionValue; + } + } + + /** + * Return formatted option value ready to edit, ready to parse + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getEditableOptionValue($optionValue) + { + try { + $value = unserialize($optionValue); + if ($value !== false) { + $result = sprintf('%s [%d]', + Mage::helper('core')->htmlEscape($value['title']), + $this->getQuoteItemOption()->getId() + ); + return $result; + } + + throw new Exception(); + + } catch (Exception $e) { + return $optionValue; + } + } + + /** + * Parse user input value and return cart prepared value + * + * @param string $optionValue + * @param array $productOptionValues Values for product option + * @return string|null + */ + public function parseOptionValue($optionValue, $productOptionValues) + { + // search quote item option Id in option value + if (preg_match('/\[([0-9]+)\]/', $optionValue, $matches)) { + $quoteItemOptionId = $matches[1]; + $option = Mage::getModel('sales/quote_item_option')->load($quoteItemOptionId); + try { + unserialize($option->getValue()); + return $option->getValue(); + } catch (Exception $e) { + return null; + } + } else { + return null; + } + } + + /** + * Prepare option value for info buy request + * + * @param string $optionValue + * @return mixed + */ + public function prepareOptionValueForRequest($optionValue) + { + try { + $result = unserialize($optionValue); + return $result; + } catch (Exception $e) { + return null; + } + } + + /** + * Quote item to order item copy process + * + * @return Mage_Catalog_Model_Product_Option_Type_File + */ + public function copyQuoteToOrder() + { + $quoteOption = $this->getQuoteItemOption(); + try { + $value = unserialize($quoteOption->getValue()); + if (!isset($value['quote_path'])) { + throw new Exception(); + } + $quoteFileFullPath = Mage::getBaseDir() . $value['quote_path']; + if (!is_file($quoteFileFullPath) || !is_readable($quoteFileFullPath)) { + throw new Exception(); + } + $orderFileFullPath = Mage::getBaseDir() . $value['order_path']; + $dir = pathinfo($orderFileFullPath, PATHINFO_DIRNAME); + $this->_createWriteableDir($dir); + @copy($quoteFileFullPath, $orderFileFullPath); + } catch (Exception $e) { + return $this; + } + return $this; + } + + /** + * Main Destination directory + * + * @param boolean $relative If true - returns relative path to the webroot + * @return string + */ + public function getTargetDir($relative = false) + { + $fullPath = Mage::getBaseDir('media') . DS . 'custom_options'; + return $relative ? str_replace(Mage::getBaseDir(), '', $fullPath) : $fullPath; + } + + /** + * Quote items destination directory + * + * @param boolean $relative If true - returns relative path to the webroot + * @return string + */ + public function getQuoteTargetDir($relative = false) + { + return $this->getTargetDir($relative) . DS . 'quote'; + } + + /** + * Order items destination directory + * + * @param boolean $relative If true - returns relative path to the webroot + * @return string + */ + public function getOrderTargetDir($relative = false) + { + return $this->getTargetDir($relative) . DS . 'order'; + } + + /** + * Directory structure initializing + */ + protected function _initFilesystem() + { + $this->_createWriteableDir($this->getTargetDir()); + $this->_createWriteableDir($this->getQuoteTargetDir()); + $this->_createWriteableDir($this->getOrderTargetDir()); + + // Directory listing and hotlink secure + $io = new Varien_Io_File(); + $io->cd($this->getTargetDir()); + if (!$io->fileExists($this->getTargetDir() . DS . '.htaccess')) { + $io->streamOpen($this->getTargetDir() . DS . '.htaccess'); + $io->streamLock(true); + $io->streamWrite("Order deny,allow\nDeny from all"); + $io->streamUnlock(); + $io->streamClose(); + } + } + + /** + * Create Writeable directory if it doesn't exist + * + * @param string Absolute directory path + * @return void + */ + protected function _createWriteableDir($path) + { + $io = new Varien_Io_File(); + if (!$io->isWriteable($path) && !$io->mkdir($path, 0777, true)) { + Mage::throwException(Mage::helper('catalog')->__("Cannot create writeable directory '%s'", $path)); + } + } + + /** + * Return URL for option file download + * + * @return string + */ + protected function _getOptionDownloadUrl($sekretKey) + { + return Mage::getUrl('sales/download/downloadCustomOption', array( + 'id' => $this->getQuoteItemOption()->getId(), + 'key' => $sekretKey + )); + } + + /** + * Parse file extensions string with various separators + * + * @param string $extensions String to parse + * @return array|null + */ + protected function _parseExtensionsString($extensions) + { + preg_match_all('/[a-z]+/si', strtolower($extensions), $matches); + if (isset($matches[0]) && is_array($matches[0]) && count($matches[0]) > 0) { + return $matches[0]; + } + return null; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Select.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Select.php new file mode 100644 index 0000000000..92b1a43b08 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Select.php @@ -0,0 +1,226 @@ + + */ +class Mage_Catalog_Model_Product_Option_Type_Select extends Mage_Catalog_Model_Product_Option_Type_Default +{ + /** + * Validate user input for option + * + * @throws Mage_Core_Exception + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function validateUserValue($values) + { + parent::validateUserValue($values); + + $option = $this->getOption(); + $value = $this->getUserValue(); + + if (empty($value) && $option->getIsRequire() && !$this->getProduct()->getSkipCheckRequiredOption()) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } + if (!$this->_isSingleSelection()) { + $valuesCollection = $option->getOptionValuesByOptionId($value, $this->getProduct()->getStoreId()) + ->load(); + if ($valuesCollection->count() != count($value)) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } + } + return $this; + } + + /** + * Prepare option value for cart + * + * @throws Mage_Core_Exception + * @return mixed Prepared option value + */ + public function prepareForCart() + { + if ($this->getIsValid()) { + return is_array($this->getUserValue()) ? implode(',', $this->getUserValue()) : $this->getUserValue(); + } + Mage::throwException(Mage::helper('catalog')->__('Option validation failed to add product to cart')); + } + + /** + * Return formatted option value for quote option + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getFormattedOptionValue($optionValue) + { + $result = $this->getEditableOptionValue($optionValue); + return Mage::helper('core')->htmlEscape($result); + } + + /** + * Return formatted option value ready to edit, ready to parse + * + * @param string $optionValue Prepared for cart option value + * @return string + */ + public function getEditableOptionValue($optionValue) + { + $option = $this->getOption(); + $result = ''; + if (!$this->_isSingleSelection()) { + foreach (explode(',', $optionValue) as $_value) { + $result .= $option->getValueById($_value)->getTitle() . ', '; + } + $result = Mage::helper('core/string')->substr($result, 0, -2); + } elseif ($this->_isSingleSelection()) { + $result = $option->getValueById($optionValue)->getTitle(); + } else { + $result = $optionValue; + } + return $result; + } + + /** + * Parse user input value and return cart prepared value, i.e. "one, two" => "1,2" + * + * @param string $optionValue + * @param array $productOptionValues Values for product option + * @return string|null + */ + public function parseOptionValue($optionValue, $productOptionValues) + { + $_values = array(); + if (!$this->_isSingleSelection()) { + foreach (explode(',', $optionValue) as $_value) { + $_value = trim($_value); + if (array_key_exists($_value, $productOptionValues)) { + $_values[] = $productOptionValues[$_value]; + } + } + } elseif ($this->_isSingleSelection() && array_key_exists($optionValue, $productOptionValues)) { + $_values[] = $productOptionValues[$optionValue]; + } + if (count($_values)) { + return implode(',', $_values); + } else { + return null; + } + } + + /** + * Prepare option value for info buy request + * + * @param string $optionValue + * @return mixed + */ + public function prepareOptionValueForRequest($optionValue) + { + if (!$this->_isSingleSelection()) { + return explode(',', $optionValue); + } + return $optionValue; + } + + /** + * Return Price for selected option + * + * @param string $optionValue Prepared for cart option value + * @return float + */ + public function getOptionPrice($optionValue, $basePrice) + { + $option = $this->getOption(); + $result = 0; + + if (!$this->_isSingleSelection()) { + foreach(explode(',', $optionValue) as $value) { + $result += $this->_getChargableOptionPrice( + $option->getValueById($value)->getPrice(), + $option->getValueById($value)->getPriceType() == 'percent', + $basePrice + ); + } + } elseif ($this->_isSingleSelection()) { + $result = $this->_getChargableOptionPrice( + $option->getValueById($optionValue)->getPrice(), + $option->getValueById($optionValue)->getPriceType() == 'percent', + $basePrice + ); + } + + return $result; + } + + /** + * Return SKU for selected option + * + * @param string $optionValue Prepared for cart option value + * @param string $skuDelimiter Delimiter for Sku parts + * @return string + */ + public function getOptionSku($optionValue, $skuDelimiter) + { + $option = $this->getOption(); + + if (!$this->_isSingleSelection()) { + $skus = array(); + foreach(explode(',', $optionValue) as $value) { + if ($optionSku = $option->getValueById($value)->getSku()) { + $skus[] = $optionSku; + } + } + $result = implode($skuDelimiter, $skus); + } elseif ($this->_isSingleSelection()) { + $result = $option->getValueById($optionValue)->getSku(); + } else { + $result = parent::getOptionSku($optionValue, $skuDelimiter); + } + + return $result; + } + + /** + * Check if option has single or multiple values selection + * + * @return boolean + */ + protected function _isSingleSelection() + { + $_single = array( + Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN, + Mage_Catalog_Model_Product_Option::OPTION_TYPE_RADIO + ); + return in_array($this->getOption()->getType(), $_single); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Type/Text.php b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Text.php new file mode 100644 index 0000000000..af73aa0746 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Type/Text.php @@ -0,0 +1,85 @@ + + */ +class Mage_Catalog_Model_Product_Option_Type_Text extends Mage_Catalog_Model_Product_Option_Type_Default +{ + /** + * Validate user input for option + * + * @throws Mage_Core_Exception + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return Mage_Catalog_Model_Product_Option_Type_Default + */ + public function validateUserValue($values) + { + parent::validateUserValue($values); + + $option = $this->getOption(); + $value = trim($this->getUserValue()); + if (strlen($value) == 0 && $option->getIsRequire() && !$this->getProduct()->getSkipCheckRequiredOption()) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s)')); + } + if (strlen($value) > $option->getMaxCharacters() && $option->getMaxCharacters() > 0) { + $this->setIsValid(false); + Mage::throwException(Mage::helper('catalog')->__('Length of text is too long')); + } + $this->setUserValue($value); + return $this; + } + + /** + * Prepare option value for cart + * + * @return mixed Prepared option value + */ + public function prepareForCart() + { + if ($this->getIsValid() && strlen($this->getUserValue()) > 0) { + return $this->getUserValue(); + } else { + return null; + } + } + + /** + * Return formatted option value for quote option + * + * @param string $value Prepared for cart option value + * @return string + */ + public function getFormattedOptionValue($value) + { + return Mage::helper('core')->htmlEscape($value); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Value.php b/app/code/core/Mage/Catalog/Model/Product/Option/Value.php index 1acf26ab38..dff61c9084 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Option/Value.php +++ b/app/code/core/Mage/Catalog/Model/Product/Option/Value.php @@ -1,203 +1,209 @@ - - */ -class Mage_Catalog_Model_Product_Option_Value extends Mage_Core_Model_Abstract -{ - protected $_values = array(); - - protected $_product; - - protected $_option; - - protected function _construct() - { - $this->_init('catalog/product_option_value'); - } - - public function addValue($value) - { - $this->_values[] = $value; - return $this; - } - - public function getValues() - { - return $this->_values; - } - - public function setValues($values) - { - $this->_values = $values; - return $this; - } - - public function unsetValues() - { - $this->_values = array(); - return $this; - } - - public function setOption(Mage_Catalog_Model_Product_Option $option) - { - $this->_option = $option; - return $this; - } - - /** - * Enter description here... - * - * @return Mage_Catalog_Model_Product_Option - */ - public function getOption() - { - return $this->_option; - } - - public function setProduct($product) - { - $this->_product = $product; - return $this; - } - - public function getProduct() - { - if (is_null($this->_product)) { - $this->_product = $this->getOption()->getProduct(); - } - return $this->_product; - } - - public function saveValues() - { - foreach ($this->getValues() as $value) { - $this->setData($value) - ->setData('option_id', $this->getOption()->getId()) - ->setData('store_id', $this->getOption()->getStoreId()); - - if ($this->getData('option_type_id') == '-1') {//change to 0 - $this->unsetData('option_type_id'); - } else { - $this->setId($this->getData('option_type_id')); - } - - if ($this->getData('is_delete') == '1') { - if ($this->getId()) { - $this->deleteValues($this->getId()); - $this->delete(); - } - } else { - $this->save(); - } - }//eof foreach() - return $this; - } - - /** - * Return price. If $flag is true and price is percent - * return converted percent to price - * - * @param bool $flag - * @return decimal - */ - public function getPrice($flag=false) - { - if ($flag && $this->getPriceType() == 'percent') { - $basePrice = $this->getOption()->getProduct()->getFinalPrice(); - $price = $basePrice*($this->_getData('price')/100); - return $price; - } - return $this->_getData('price'); - } - - /** - * Enter description here... - * - * @param Mage_Catalog_Model_Product_Option $option - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Option_Value_Collection - */ - public function getValuesCollection(Mage_Catalog_Model_Product_Option $option) - { - $collection = Mage::getResourceModel('catalog/product_option_value_collection') - ->addFieldToFilter('option_id', $option->getId()) - ->getValues($option->getStoreId()); - - return $collection; - } - - public function getValuesByOption($optionIds, $option_id, $store_id) - { - $collection = Mage::getResourceModel('catalog/product_option_value_collection') - ->addFieldToFilter('option_id', $option_id) - ->getValuesByOption($optionIds, $store_id); - - return $collection; - } - - public function deleteValue($option_id) - { - $this->getResource()->deleteValue($option_id); - return $this; - } - - public function deleteValues($option_type_id) - { - $this->getResource()->deleteValues($option_type_id); - return $this; - } - - /** - * Prepare array of option values for duplicate - * - * @return array - */ - public function prepareValueForDuplicate() - { - $this->setOptionId(null); - $this->setOptionTypeId(null); - - return $this->__toArray(); - } - - /** - * Duplicate product options value - * - * @param int $oldOptionId - * @param int $newOptionId - * @return Mage_Catalog_Model_Product_Option_Value - */ - public function duplicate($oldOptionId, $newOptionId) - { - $this->getResource()->duplicate($this, $oldOptionId, $newOptionId); - return $this; - } + + */ +class Mage_Catalog_Model_Product_Option_Value extends Mage_Core_Model_Abstract +{ + protected $_values = array(); + + protected $_product; + + protected $_option; + + protected function _construct() + { + $this->_init('catalog/product_option_value'); + } + + public function addValue($value) + { + $this->_values[] = $value; + return $this; + } + + public function getValues() + { + return $this->_values; + } + + public function setValues($values) + { + $this->_values = $values; + return $this; + } + + public function unsetValues() + { + $this->_values = array(); + return $this; + } + + public function setOption(Mage_Catalog_Model_Product_Option $option) + { + $this->_option = $option; + return $this; + } + + public function unsetOption() + { + $this->_option = null; + return $this; + } + + /** + * Enter description here... + * + * @return Mage_Catalog_Model_Product_Option + */ + public function getOption() + { + return $this->_option; + } + + public function setProduct($product) + { + $this->_product = $product; + return $this; + } + + public function getProduct() + { + if (is_null($this->_product)) { + $this->_product = $this->getOption()->getProduct(); + } + return $this->_product; + } + + public function saveValues() + { + foreach ($this->getValues() as $value) { + $this->setData($value) + ->setData('option_id', $this->getOption()->getId()) + ->setData('store_id', $this->getOption()->getStoreId()); + + if ($this->getData('option_type_id') == '-1') {//change to 0 + $this->unsetData('option_type_id'); + } else { + $this->setId($this->getData('option_type_id')); + } + + if ($this->getData('is_delete') == '1') { + if ($this->getId()) { + $this->deleteValues($this->getId()); + $this->delete(); + } + } else { + $this->save(); + } + }//eof foreach() + return $this; + } + + /** + * Return price. If $flag is true and price is percent + * return converted percent to price + * + * @param bool $flag + * @return decimal + */ + public function getPrice($flag=false) + { + if ($flag && $this->getPriceType() == 'percent') { + $basePrice = $this->getOption()->getProduct()->getFinalPrice(); + $price = $basePrice*($this->_getData('price')/100); + return $price; + } + return $this->_getData('price'); + } + + /** + * Enter description here... + * + * @param Mage_Catalog_Model_Product_Option $option + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Option_Value_Collection + */ + public function getValuesCollection(Mage_Catalog_Model_Product_Option $option) + { + $collection = Mage::getResourceModel('catalog/product_option_value_collection') + ->addFieldToFilter('option_id', $option->getId()) + ->getValues($option->getStoreId()); + + return $collection; + } + + public function getValuesByOption($optionIds, $option_id, $store_id) + { + $collection = Mage::getResourceModel('catalog/product_option_value_collection') + ->addFieldToFilter('option_id', $option_id) + ->getValuesByOption($optionIds, $store_id); + + return $collection; + } + + public function deleteValue($option_id) + { + $this->getResource()->deleteValue($option_id); + return $this; + } + + public function deleteValues($option_type_id) + { + $this->getResource()->deleteValues($option_type_id); + return $this; + } + + /** + * Prepare array of option values for duplicate + * + * @return array + */ + public function prepareValueForDuplicate() + { + $this->setOptionId(null); + $this->setOptionTypeId(null); + + return $this->__toArray(); + } + + /** + * Duplicate product options value + * + * @param int $oldOptionId + * @param int $newOptionId + * @return Mage_Catalog_Model_Product_Option_Value + */ + public function duplicate($oldOptionId, $newOptionId) + { + $this->getResource()->duplicate($this, $oldOptionId, $newOptionId); + return $this; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Status.php b/app/code/core/Mage/Catalog/Model/Product/Status.php index 672e00a59b..edeb8fef4f 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Status.php +++ b/app/code/core/Mage/Catalog/Model/Product/Status.php @@ -1,136 +1,299 @@ - - */ -class Mage_Catalog_Model_Product_Status extends Mage_Core_Model_Abstract -{ - protected function _construct() - { - $this->_init('catalog/product_status'); - } - - const STATUS_ENABLED = 1; - const STATUS_DISABLED = 2; - - public function addVisibleFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) - { - //$collection->addAttributeToFilter('status', array('in'=>$this->getVisibleStatusIds())); - return $this; - } - - public function addSaleableFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) - { - //$collection->addAttributeToFilter('status', array('in'=>$this->getSaleableStatusIds())); - return $this; - } - - public function getVisibleStatusIds() - { - return array(self::STATUS_ENABLED); - } - - public function getSaleableStatusIds() - { - return array(self::STATUS_ENABLED); - } - - static public function getOptionArray() - { - return array( - self::STATUS_ENABLED => Mage::helper('catalog')->__('Enabled'), - self::STATUS_DISABLED => Mage::helper('catalog')->__('Disabled') - ); - } - - static public function getAllOption() - { - $options = self::getOptionArray(); - array_unshift($options, array('value'=>'', 'label'=>'')); - return $options; - } - - static public function getAllOptions() - { - $res = array(); - $res[] = array('value'=>'', 'label'=> Mage::helper('catalog')->__('-- Please Select --')); - foreach (self::getOptionArray() as $index => $value) { - $res[] = array( - 'value' => $index, - 'label' => $value - ); - } - return $res; - } - - static public function getOptionText($optionId) - { - $options = self::getOptionArray(); - return isset($options[$optionId]) ? $options[$optionId] : null; - } - - /** - * Update status value for product - * - * @param int $productId - * @param int $storeId - * @param int $value - * @return Mage_Catalog_Model_Product_Status - */ - public function updateProductStatus($productId, $storeId, $value) - { - $this->_getResource()->updateProductStatus($productId, $storeId, $value); - Mage::getResourceModel('catalog/category')->refreshProductIndex( - array(), - array($productId), - $storeId ? array($storeId) : array() - ); - Mage::dispatchEvent('catalog_product_status_update', array( - 'product_id' => $productId, - 'store_id' => $storeId, - 'status' => $value - )); - return $this; - } - - /** - * Retrieve Product(s) status for store - * Return array where key is product, value - status - * - * @param int|array $productIds - * @param int $storeId - * @return array - */ - public function getProductStatus($productIds, $storeId = null) - { - return $this->getResource()->getProductStatus($productIds, $storeId); - } -} \ No newline at end of file + + */ +class Mage_Catalog_Model_Product_Status extends Mage_Core_Model_Abstract +{ + const STATUS_ENABLED = 1; + const STATUS_DISABLED = 2; + + /** + * Initialize resource model + * + */ + protected function _construct() + { + $this->_init('catalog/product_status'); + } + + /** + * Retrieve resource model wraper + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status + */ + protected function _getResource() + { + return parent::_getResource(); + } + + /** + * Retrieve Product Attribute by code + * + * @param string $attributeCode + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + public function getProductAttribute($attributeCode) + { + return $this->_getResource()->getProductAttribute($attributeCode); + } + + /** + * Add visible filter to Product Collection + * + * @deprecated remove on new builds + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @return Mage_Catalog_Model_Product_Status + */ + public function addVisibleFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) + { + //$collection->addAttributeToFilter('status', array('in'=>$this->getVisibleStatusIds())); + return $this; + } + + /** + * Add saleable filter to Product Collection + * + * @deprecated remove on new builds + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @return Mage_Catalog_Model_Product_Status + */ + public function addSaleableFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) + { + //$collection->addAttributeToFilter('status', array('in'=>$this->getSaleableStatusIds())); + return $this; + } + + /** + * Retrieve Visible Status Ids + * + * @return array + */ + public function getVisibleStatusIds() + { + return array(self::STATUS_ENABLED); + } + + /** + * Retrieve Saleable Status Ids + * Default Product Enable status + * + * @return array + */ + public function getSaleableStatusIds() + { + return array(self::STATUS_ENABLED); + } + + /** + * Retrieve option array + * + * @return array + */ + static public function getOptionArray() + { + return array( + self::STATUS_ENABLED => Mage::helper('catalog')->__('Enabled'), + self::STATUS_DISABLED => Mage::helper('catalog')->__('Disabled') + ); + } + + /** + * Retrieve option array with empty value + * + * @return array + */ + static public function getAllOption() + { + $options = self::getOptionArray(); + array_unshift($options, array('value'=>'', 'label'=>'')); + return $options; + } + + /** + * Retrieve option array with empty value + * + * @return array + */ + static public function getAllOptions() + { + $res = array( + array( + 'value' => '', + 'label' => Mage::helper('catalog')->__('-- Please Select --') + ) + ); + foreach (self::getOptionArray() as $index => $value) { + $res[] = array( + 'value' => $index, + 'label' => $value + ); + } + return $res; + } + + /** + * Retrieve option text by option value + * + * @param string $optionId + * @return string + */ + static public function getOptionText($optionId) + { + $options = self::getOptionArray(); + return isset($options[$optionId]) ? $options[$optionId] : null; + } + + /** + * Update status value for product + * + * @param int $productId + * @param int $storeId + * @param int $value + * @return Mage_Catalog_Model_Product_Status + */ + public function updateProductStatus($productId, $storeId, $value) + { + $stores = array(); + if ($storeId != 0) { + $attribute = $this->getProductAttribute('status'); + if ($attribute->getIsGlobal() == Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE) { + $stores[] = $storeId; + } + elseif ($attribute->getIsGlobal() == Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE) { + $website = Mage::app()->getStore($storeId)->getWebsite(); + foreach ($website->getStores() as $store) { + $stores[] = $store->getId(); + } + } + else { + $stores[] = 0; + } + } + else { + $stores[] = $storeId; + } + + foreach ($stores as $storeId) { + $this->_getResource()->updateProductStatus($productId, $storeId, $value); + Mage::getResourceModel('catalog/category')->refreshProductIndex( + array(), + array($productId), + $storeId ? array($storeId) : array() + ); + Mage::dispatchEvent('catalog_product_status_update', array( + 'product_id' => $productId, + 'store_id' => $storeId, + 'status' => $value + )); + } + return $this; + } + + /** + * Retrieve Product(s) status for store + * Return array where key is product, value - status + * + * @param int|array $productIds + * @param int $storeId + * @return array + */ + public function getProductStatus($productIds, $storeId = null) + { + return $this->getResource()->getProductStatus($productIds, $storeId); + } + + /** + * ---------------- Eav Source methods for Flat data ----------------------- + */ + + /** + * Retrieve Column(s) for Flat + * + * @return array + */ + public function getFlatColums() + { + return array(); + } + + /** + * Retrieve Indexes for Flat + * + * @return array + */ + public function getFlatIndexes() + { + return array(); + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return null; + } + + /** + * Add Value Sort To Collection Select + * + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @param string $dir direction + * @return Mage_Eav_Model_Entity_Attribute_Source_Abstract + */ + public function addValueSortToCollection($collection, $dir = 'asc') { + $valueTable1 = $this->getAttribute()->getAttributeCode() . '_t1'; + $valueTable2 = $this->getAttribute()->getAttributeCode() . '_t2'; + $collection->getSelect() + ->joinLeft( + array($valueTable1 => $this->getAttribute()->getBackend()->getTable()), + "`e`.`entity_id`=`{$valueTable1}`.`entity_id`" + . " AND `{$valueTable1}`.`attribute_id`='{$this->getAttribute()->getId()}'" + . " AND `{$valueTable1}`.`store_id`='0'", + array()) + ->joinLeft( + array($valueTable2 => $this->getAttribute()->getBackend()->getTable()), + "`e`.`entity_id`=`{$valueTable2}`.`entity_id`" + . " AND `{$valueTable2}`.`attribute_id`='{$this->getAttribute()->getId()}'" + . " AND `{$valueTable2}`.`store_id`='{$collection->getStoreId()}'", + array() + ); + $valueExpr = new Zend_Db_Expr("IFNULL(`{$valueTable2}`.`value`, `{$valueTable1}`.`value`)"); + $collection->getSelect()->order($valueExpr . ' ' . $dir); + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Type.php b/app/code/core/Mage/Catalog/Model/Product/Type.php index f25068b115..c7a075090b 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type.php @@ -54,9 +54,10 @@ class Mage_Catalog_Model_Product_Type * Product type instance factory * * @param Mage_Catalog_Model_Product $product + * @param bool $singleton * @return Mage_Catalog_Model_Product_Type_Abstract */ - public static function factory($product) + public static function factory($product, $singleton = false) { $types = self::getTypes(); @@ -66,8 +67,13 @@ public static function factory($product) $typeModelName = self::DEFAULT_TYPE_MODEL; } - $typeModel = Mage::getModel($typeModelName); - $typeModel->setProduct($product); + if ($singleton === true) { + $typeModel = Mage::getSingleton($typeModelName); + } + else { + $typeModel = Mage::getModel($typeModelName); + $typeModel->setProduct($product); + } $typeModel->setConfig($types[$product->getTypeId()]); return $typeModel; } @@ -118,10 +124,10 @@ static public function getAllOptions() $res = array(); $res[] = array('value'=>'', 'label'=>''); foreach (self::getOptionArray() as $index => $value) { - $res[] = array( - 'value' => $index, - 'label' => $value - ); + $res[] = array( + 'value' => $index, + 'label' => $value + ); } return $res; } @@ -130,10 +136,10 @@ static public function getOptions() { $res = array(); foreach (self::getOptionArray() as $index => $value) { - $res[] = array( - 'value' => $index, - 'label' => $value - ); + $res[] = array( + 'value' => $index, + 'label' => $value + ); } return $res; } diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php b/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php index 9db830a901..7d673629f3 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php @@ -1,624 +1,652 @@ - - */ -abstract class Mage_Catalog_Model_Product_Type_Abstract -{ - /** - * Product model instance - * - * @var Mage_Catalog_Model_Product - */ - protected $_product; - protected $_typeId; - protected $_setAttributes; - protected $_editableAttributes; - protected $_isComposite = false; - protected $_storeFilter = null; - - const CALCULATE_CHILD = 0; - const CALCULATE_PARENT = 1; - - /** - * values for shipment type (invoice etc) - * - */ - const SHIPMENT_SEPARATELY = 1; - const SHIPMENT_TOGETHER = 0; - - /** - * Specify type instance product - * - * @param Mage_Catalog_Model_Product $product - * @return Mage_Catalog_Model_Product_Type_Abstract - */ - public function setProduct($product) - { - $this->_product = $product; - return $this; - } - - /** - * Specify type identifier - * - * @param string $typeId - * @return Mage_Catalog_Model_Product_Type_Abstract - */ - public function setTypeId($typeId) - { - $this->_typeId = $typeId; - return $this; - } - - /** - * Retrieve catalog product object - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - return $this->_product; - } - - /** - * Return relation info about used products for specific type instance - * - * @return Varien_Object Object with information data - */ - public function getRelationInfo() - { - return new Varien_Object(); - } - - /** - * Retrieve Required children ids - * Return grouped array, ex array( - * group => array(ids) - * ) - * - * @param int $parentId - * @param bool $required - * @return array - */ - public function getChildrenIds($parentId, $required = true) - { - return array(); - } - - /** - * Retrieve parent ids array by requered child - * - * @param int $childId - * @return array - */ - public function getParentIdsByChild($childId) - { - return array(); - } - - /** - * Get array of product set attributes - * - * @return array - */ - public function getSetAttributes() - { - if (is_null($this->_setAttributes)) { - $attributes = $this->getProduct()->getResource() - ->loadAllAttributes($this->getProduct()) - ->getAttributesByCode(); - $this->_setAttributes = array(); - foreach ($attributes as $attribute) { - if ($attribute->isInSet($this->getProduct()->getAttributeSetId())) { - $attribute->setDataObject($this->getProduct()); - $this->_setAttributes[$attribute->getAttributeCode()] = $attribute; - } - } - - uasort($this->_setAttributes, array($this, 'attributesCompare')); - } - return $this->_setAttributes; - } - - public function attributesCompare($attribute1, $attribute2) - { - $sortPath = 'attribute_set_info/' . $this->getProduct()->getAttributeSetId() . '/sort'; - $groupSortPath = 'attribute_set_info/' . $this->getProduct()->getAttributeSetId() . '/group_sort'; - - $sort1 = ($attribute1->getData($groupSortPath) * 1000) + ($attribute1->getData($sortPath) * 0.0001); - $sort2 = ($attribute2->getData($groupSortPath) * 1000) + ($attribute2->getData($sortPath) * 0.0001); - - if ($sort1 > $sort2) { - return 1; - } elseif ($sort1 < $sort2) { - return -1; - } - - return 0; - } - - /** - * Retrieve product type attributes - * - * @return array - */ - public function getEditableAttributes() - { - if (is_null($this->_editableAttributes)) { - $this->_editableAttributes = array(); - foreach ($this->getSetAttributes() as $attributeCode => $attribute) { - if (!is_array($attribute->getApplyTo()) - || count($attribute->getApplyTo())==0 - || in_array($this->getProduct()->getTypeId(), $attribute->getApplyTo())) { - $this->_editableAttributes[$attributeCode] = $attribute; - } - } - } - return $this->_editableAttributes; - } - - /** - * Retrieve product attribute by identifier - * - * @param int $attributeId - * @return Mage_Eav_Model_Entity_Attribute_Abstract - */ - public function getAttributeById($attributeId) - { - foreach ($this->getSetAttributes() as $attribute) { - if ($attribute->getId() == $attributeId) { - return $attribute; - } - } - return null; - } - - /** - * Check is virtual product - * - * @return bool - */ - public function isVirtual() - { - return false; - } - - /** - * Check is product available for sale - * - * @return bool - */ - public function isSalable() - { - $salable = $this->getProduct()->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_ENABLED; - if ($salable && $this->getProduct()->hasData('is_salable')) { - $salable = $this->getProduct()->getData('is_salable'); - } - elseif ($salable && $this->isComposite()) { - $salable = null; - } - - return $salable; - } - - /** - * Initialize product(s) for add to cart process - * - * @param Varien_Object $buyRequest - * @return array|string - */ - public function prepareForCart(Varien_Object $buyRequest) - { - $product = $this->getProduct(); - /* @var Mage_Catalog_Model_Product $product */ - - // try to add custom options - $options = $this->_prepareOptionsForCart($buyRequest->getOptions()); - if (is_string($options)) { - return $options; - } - // try to found super product configuration - // (if product was buying within grouped product) - $superProductConfig = $buyRequest->getSuperProductConfig(); - if (!empty($superProductConfig['product_id']) - && !empty($superProductConfig['product_type'])) { - $superProductId = (int) $superProductConfig['product_id']; - if ($superProductId) { - if (!$superProduct = Mage::registry('used_super_product_'.$superProductId)) { - $superProduct = Mage::getModel('catalog/product')->load($superProductId); - Mage::register('used_super_product_'.$superProductId, $superProduct); - } - if ($superProduct->getId()) { - $assocProductIds = $superProduct->getTypeInstance()->getAssociatedProductIds(); - if (in_array($product->getId(), $assocProductIds)) { - $productType = $superProductConfig['product_type']; - $product->addCustomOption('product_type', $productType, $superProduct); - - $buyRequest->setData('super_product_config', array( - 'product_type' => $productType, - 'product_id' => $superProduct->getId() - ) - ); - } - } - } - } - - $product->addCustomOption('info_buyRequest', serialize($buyRequest->getData())); - - if ($options) { - $optionIds = array_keys($options); - $product->addCustomOption('option_ids', implode(',', $optionIds)); - foreach ($options as $optionId => $optionValue) { - $product->addCustomOption('option_'.$optionId, $optionValue); - } - } - // set quantity in cart - $product->setCartQty($buyRequest->getQty()); - - return array($product); - } - - /** - * Check custom defined options for product - * - * @param array $options - * @return array || string - */ - protected function _prepareOptionsForCart($options) - { - $newOptions = array(); - - foreach ($this->getProduct()->getOptions() as $_option) { - /* @var $_option Mage_Catalog_Model_Product_Option */ - if (!isset($options[$_option->getId()]) && $_option->getIsRequire() && !$this->getProduct()->getSkipCheckRequiredOption()) { - return Mage::helper('catalog')->__('Please specify the product required option(s)'); - } - if (!isset($options[$_option->getId()])) { - continue; - } - if ($_option->getGroupByType($_option->getType()) == Mage_Catalog_Model_Product_Option::OPTION_GROUP_TEXT) { - $options[$_option->getId()] = trim($options[$_option->getId()]); - if (strlen($options[$_option->getId()]) == 0 && $_option->getIsRequire()) { - return Mage::helper('catalog')->__('Please specify the product required option(s)'); - } - if (strlen($options[$_option->getId()]) > $_option->getMaxCharacters() && $_option->getMaxCharacters() > 0) { - return Mage::helper('catalog')->__('Length of text is too long'); - } - if (strlen($options[$_option->getId()]) == 0) continue; - } - if ($_option->getGroupByType($_option->getType()) == Mage_Catalog_Model_Product_Option::OPTION_GROUP_FILE) { - - } - if ($_option->getGroupByType($_option->getType()) == Mage_Catalog_Model_Product_Option::OPTION_GROUP_DATE) { - - } - - if ($_option->getGroupbyType($_option->getType()) == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - if (($_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN - || $_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_RADIO) - && strlen($options[$_option->getId()])== 0) { - continue; - } - $valuesCollection = $_option->getOptionValuesByOptionId( - $options[$_option->getId()], $this->getProduct()->getStoreId() - )->load(); - - if ($valuesCollection->count() != count($options[$_option->getId()])) { - return Mage::helper('catalog')->__('Please specify the product required option(s)'); - } - } - if (is_array($options[$_option->getId()])) { - $options[$_option->getId()] = implode(',', $options[$_option->getId()]); - } - $newOptions[$_option->getId()] = $options[$_option->getId()]; - } - - return $newOptions; - } - - /** - * Check if product can be bought - * - * @return Mage_Catalog_Model_Product_Type_Abstract - * @throws Mage_Core_Exception - */ - public function checkProductBuyState() - { - if (!$this->getProduct()->getSkipCheckRequiredOption()) { - foreach ($this->getProduct()->getOptions() as $option) { - if ($option->getIsRequire() && (!$this->getProduct()->getCustomOption('option_'.$option->getId()) - || strlen($this->getProduct()->getCustomOption('option_'.$option->getId())->getValue()) == 0)) { - Mage::throwException( - Mage::helper('catalog')->__('Product has required options') - ); - break; - } - } - } - - return $this; - } - - /** - * Prepare additional options/information for order item which will be - * created from this product - * - * @return attay - */ - public function getOrderOptions() - { - $optionArr = array(); - if ($info = $this->getProduct()->getCustomOption('info_buyRequest')) { - $optionArr['info_buyRequest'] = unserialize($info->getValue()); - } - - if ($optionIds = $this->getProduct()->getCustomOption('option_ids')) { - foreach (explode(',', $optionIds->getValue()) as $optionId) { - if ($option = $this->getProduct()->getOptionById($optionId)) { - $formatedValue = ''; - $optionGroup = $option->getGroupByType($option->getType()); - $optionValue = $this->getProduct()->getCustomOption('option_'.$option->getId())->getValue(); - if ($option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - foreach (explode(',', $optionValue) as $value) { - $formatedValue .= $option->getValueById($value)->getTitle() . ', '; - } - $formatedValue = Mage::helper('core/string')->substr($formatedValue, 0, -2); - } elseif ($optionGroup == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $formatedValue = $option->getValueById($optionValue)->getTitle(); - } else { - $formatedValue = $optionValue; - } - $optionArr['options'][] = array( - 'label' => $option->getTitle(), - 'value' => $formatedValue, - 'option_id' => $option->getId(), - 'option_value' => $optionValue - ); - } - } - } - - if ($productTypeConfig = $this->getProduct()->getCustomOption('product_type')) { - $optionArr['super_product_config'] = array( - 'product_code' => $productTypeConfig->getCode(), - 'product_type' => $productTypeConfig->getValue(), - 'product_id' => $productTypeConfig->getProductId() - ); - } - - return $optionArr; - } - - /** - * Save type related data - * - * @return Mage_Catalog_Model_Product_Type_Abstract - */ - public function save() - { - return $this; - } - - /** - * Before save type related data - * - * @return unknown - */ - public function beforeSave() - { - $this->getProduct()->canAffectOptions(true); - return $this; - } - - /** - * Check if product is composite (grouped, configurable, etc) - * - * @return bool - */ - public function isComposite() - { - return $this->_isComposite; - } - - /** - * Setting specified product type variables - * - * @param array $config - * @return Mage_Catalog_Model_Product_Type_Abstract - */ - public function setConfig($config) - { - if (isset($config['composite'])) { - $this->_isComposite = (bool) $config['composite']; - } - return $this; - } - - /** - * Default action to get sku of product - * - * @return string - */ - public function getSku() - { - $skuDelimiter = '-'; - $sku = $this->getProduct()->getData('sku'); - if ($optionIds = $this->getProduct()->getCustomOption('option_ids')) { - $optionIds = split(',', $optionIds->getValue()); - foreach ($optionIds as $optionId) { - $productOption = $this->getProduct()->getOptionById($optionId); - if ($productOption = $this->getProduct()->getOptionById($optionId)) { - $optionValue = $this->getProduct()->getCustomOption('option_' . $optionId)->getValue(); - - if ($productOption->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $productOption->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - foreach(split(',', $optionValue) as $value) { - if ($optionSku = $productOption->getValueById($value)->getSku()) { - $sku .= $skuDelimiter . $optionSku; - } - } - $optionSku = null; - } - elseif ($productOption->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $optionSku = $productOption->getValueById($optionValue)->getSku(); - } - else { - $optionSku = $productOption->getSku(); - } - - if (!empty($optionSku)) { - $sku .= $skuDelimiter . $optionSku; - } - } - } - } - return $sku; - } - - /** - * Default action to get weight of product - * - * @return decimal - */ - public function getWeight() - { - return $this->getProduct()->getData('weight'); - } - - /** - * Return true if product has options - * - * @return bool - */ - public function hasOptions() - { - if ($this->getProduct()->getHasOptions()) { - return true; - } - return false; - } - - /** - * Method is needed for specific actions to change given quote options values - * according current product type logic - * Example: the cataloginventory validation of decimal qty can change qty to int, - * so need to change quote item qty option value too. - * - * @param array $options - * @param Varien_Object $option - * @param mixed $value - * - * @return object Mage_Catalog_Model_Product_Type_Abstract - */ - public function updateQtyOption($options, Varien_Object $option, $value) - { - return $this; - } - - /** - * Check if product has required options - * - * @return bool - */ - public function hasRequiredOptions() - { - if ($this->getProduct()->getRequiredOptions()) { - return true; - } - return false; - } - - /** - * Retrive store filter for associated products - * - * @return int|Mage_Core_Model_Store - */ - public function getStoreFilter() - { - return $this->_storeFilter; - } - - /** - * Set store filter for associated products - * - * @param $store int|Mage_Core_Model_Store - * @return Mage_Catalog_Model_Product_Type_Configurable - */ - public function setStoreFilter($store=null) - { - $this->_storeFilter = $store; - return $this; - } - - /** - * Allow for updates of chidren qty's - * (applicable for complicated product types. As default returns false) - * - * @return boolean false - */ - public function getForceChildItemQtyChanges() - { - return false; - } - - /** - * Prepare Quote Item Quantity - * - * @param mixed $qty - * @return float - */ - public function prepareQuoteItemQty($qty) - { - return floatval($qty); - } - - /** - * Implementation of product specify logic of which product needs to be assigned to option. - * For example if product which was added to option already removed from catalog. - * - * @param Mage_Catalog_Model_Product $optionProduct - * @param Mage_Sales_Model_Quote_Item_Option $option - * @return Mage_Catalog_Model_Product_Type_Abstract - */ - public function assignProductToOption($optionProduct, $option) - { - if ($optionProduct) { - $option->setProduct($optionProduct); - } else { - $option->setProduct($this->getProduct()); - } - - return $this; - } -} + + */ +abstract class Mage_Catalog_Model_Product_Type_Abstract +{ + /** + * Product model instance + * + * @deprecated if use as singleton + * @var Mage_Catalog_Model_Product + */ + protected $_product; + + /** + * Product type instance id + * + * @var string + */ + protected $_typeId; + + /** + * @deprecated + * + * @var array + */ + protected $_setAttributes; + + /** + * @deprecated + * + * @var array + */ + protected $_editableAttributes; + + /** + * Is a compotite product type + * + * @var bool + */ + protected $_isComposite = false; + + /** + * @deprecated + * + * @var int + */ + protected $_storeFilter = null; + + const CALCULATE_CHILD = 0; + const CALCULATE_PARENT = 1; + + /** + * values for shipment type (invoice etc) + * + */ + const SHIPMENT_SEPARATELY = 1; + const SHIPMENT_TOGETHER = 0; + + /** + * Specify type instance product + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function setProduct($product) + { + $this->_product = $product; + return $this; + } + + /** + * Specify type identifier + * + * @param string $typeId + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function setTypeId($typeId) + { + $this->_typeId = $typeId; + return $this; + } + + /** + * Retrieve catalog product object + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product + */ + public function getProduct($product = null) + { + if (is_object($product)) { + return $product; + } + return $this->_product; + } + + /** + * Return relation info about used products for specific type instance + * + * @return Varien_Object Object with information data + */ + public function getRelationInfo() + { + return new Varien_Object(); + } + + /** + * Retrieve Required children ids + * Return grouped array, ex array( + * group => array(ids) + * ) + * + * @param int $parentId + * @param bool $required + * @return array + */ + public function getChildrenIds($parentId, $required = true) + { + return array(); + } + + /** + * Retrieve parent ids array by requered child + * + * @param int $childId + * @return array + */ + public function getParentIdsByChild($childId) + { + return array(); + } + + /** + * Get array of product set attributes + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getSetAttributes($product = null) + { + $cacheKey = '_cache_set_attributes'; + if (!$this->getProduct($product)->hasData($cacheKey)) { + $attributes = $this->getProduct($product)->getResource() + ->loadAllAttributes($this->getProduct($product)) + ->getAttributesByCode(); + $setAttributes = array(); + $attributeSetId = $this->getProduct($product)->getAttributeSetId(); + foreach ($attributes as $attribute) { + if ($attribute->isInSet($attributeSetId)) { + $attribute->setGroupSortPath($attribute->getData( + "attribute_set_info/{$attributeSetId}/group_sort" + )); + $attribute->setSortPath($attribute->getData( + "attribute_set_info/{$attributeSetId}/sort" + )); + $setAttributes[$attribute->getAttributeCode()] = $attribute; + } + } + + uasort($setAttributes, array($this, 'attributesCompare')); + $this->getProduct($product)->setData($cacheKey, $setAttributes); + } + return $this->getProduct($product)->getData($cacheKey); + } + + /** + * Compare attribues sorting + * + * @param Mage_Catalog_Model_Entity_Attribute $attribute1 + * @param Mage_Catalog_Model_Entity_Attribute $attribute2 + * @return int + */ + public function attributesCompare($attribute1, $attribute2) + { + $sort1 = ($attribute1->getGroupSortPath() * 1000) + ($attribute1->getSortPath() * 0.0001); + $sort2 = ($attribute2->getGroupSortPath() * 1000) + ($attribute2->getSortPath() * 0.0001); + + if ($sort1 > $sort2) { + return 1; + } elseif ($sort1 < $sort2) { + return -1; + } + + return 0; + } + + /** + * Retrieve product type attributes + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getEditableAttributes($product = null) + { + $cacheKey = '_cache_editable_attributes'; + if (!$this->getProduct($product)->hasData($cacheKey)) { + $editableAttributes = array(); + foreach ($this->getSetAttributes($product) as $attributeCode => $attribute) { + if (!is_array($attribute->getApplyTo()) + || count($attribute->getApplyTo())==0 + || in_array($this->getProduct($product)->getTypeId(), $attribute->getApplyTo())) { + $editableAttributes[$attributeCode] = $attribute; + } + } + $this->getProduct($product)->setData($cacheKey, $editableAttributes); + } + return $this->getProduct($product)->getData($cacheKey); + } + + /** + * Retrieve product attribute by identifier + * + * @param int $attributeId + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + public function getAttributeById($attributeId, $product = null) + { + foreach ($this->getSetAttributes($product) as $attribute) { + if ($attribute->getId() == $attributeId) { + return $attribute; + } + } + return null; + } + + /** + * Check is virtual product + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isVirtual($product = null) + { + return false; + } + + /** + * Check is product available for sale + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isSalable($product = null) + { + $salable = $this->getProduct($product)->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_ENABLED; + if ($salable && $this->getProduct($product)->hasData('is_salable')) { + $salable = $this->getProduct($product)->getData('is_salable'); + } + elseif ($salable && $this->isComposite()) { + $salable = null; + } + + return $salable; + } + + /** + * Initialize product(s) for add to cart process + * + * @param Varien_Object $buyRequest + * @param Mage_Catalog_Model_Product $product + * @return array|string + */ + public function prepareForCart(Varien_Object $buyRequest, $product = null) + { + $product = $this->getProduct($product); + /* @var Mage_Catalog_Model_Product $product */ + // try to add custom options + try { + $options = $this->_prepareOptionsForCart($buyRequest, $product); + } catch (Mage_Core_Exception $e) { + return $e->getMessage(); + } + + if (is_string($options)) { + return $options; + } + // try to found super product configuration + // (if product was buying within grouped product) + $superProductConfig = $buyRequest->getSuperProductConfig(); + if (!empty($superProductConfig['product_id']) + && !empty($superProductConfig['product_type'])) { + $superProductId = (int) $superProductConfig['product_id']; + if ($superProductId) { + if (!$superProduct = Mage::registry('used_super_product_'.$superProductId)) { + $superProduct = Mage::getModel('catalog/product')->load($superProductId); + Mage::register('used_super_product_'.$superProductId, $superProduct); + } + if ($superProduct->getId()) { + $assocProductIds = $superProduct->getTypeInstance(true)->getAssociatedProductIds($superProduct); + if (in_array($product->getId(), $assocProductIds)) { + $productType = $superProductConfig['product_type']; + $product->addCustomOption('product_type', $productType, $superProduct); + + $buyRequest->setData('super_product_config', array( + 'product_type' => $productType, + 'product_id' => $superProduct->getId() + ) + ); + } + } + } + } + + $product->addCustomOption('info_buyRequest', serialize($buyRequest->getData())); + + if ($options) { + $optionIds = array_keys($options); + $product->addCustomOption('option_ids', implode(',', $optionIds)); + foreach ($options as $optionId => $optionValue) { + $product->addCustomOption('option_'.$optionId, $optionValue); + } + } + // set quantity in cart + $product->setCartQty($buyRequest->getQty()); + + return array($product); + } + + /** + * Retrieve message for specify option(s) + * + * @return string + */ + public function getSpecifyOptionMessage() + { + return Mage::helper('catalog')->__('Please specify the product required option(s)'); + } + + /** + * Check custom defined options for product + * + * @param Varien_Object $buyRequest + * @param Mage_Catalog_Model_Product $product + * @return array || string + */ + protected function _prepareOptionsForCart(Varien_Object $buyRequest, $product = null) + { + $newOptions = array(); + foreach ($this->getProduct($product)->getOptions() as $_option) { + /* @var $_option Mage_Catalog_Model_Product_Option */ + $group = $_option->groupFactory($_option->getType()) + ->setOption($_option) + ->setProduct($this->getProduct($product)) + ->setRequest($buyRequest) + ->validateUserValue($buyRequest->getOptions()); + + $preparedValue = $group->prepareForCart(); + if ($preparedValue !== null) { + $newOptions[$_option->getId()] = $preparedValue; + } + } + return $newOptions; + } + + /** + * Check if product can be bought + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Abstract + * @throws Mage_Core_Exception + */ + public function checkProductBuyState($product = null) + { + if (!$this->getProduct($product)->getSkipCheckRequiredOption()) { + foreach ($this->getProduct($product)->getOptions() as $option) { + if ($option->getIsRequire() && (!$this->getProduct($product)->getCustomOption('option_'.$option->getId()) + || strlen($this->getProduct($product)->getCustomOption('option_'.$option->getId())->getValue()) == 0)) { + Mage::throwException( + Mage::helper('catalog')->__('Product has required options') + ); + break; + } + } + } + + return $this; + } + + /** + * Prepare additional options/information for order item which will be + * created from this product + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getOrderOptions($product = null) + { + $optionArr = array(); + if ($info = $this->getProduct($product)->getCustomOption('info_buyRequest')) { + $optionArr['info_buyRequest'] = unserialize($info->getValue()); + } + + if ($optionIds = $this->getProduct($product)->getCustomOption('option_ids')) { + foreach (explode(',', $optionIds->getValue()) as $optionId) { + if ($option = $this->getProduct($product)->getOptionById($optionId)) { + + $quoteItemOption = $this->getProduct($product)->getCustomOption('option_'.$option->getId()); + + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setProduct($this->getProduct()) + ->setQuoteItemOption($quoteItemOption); + + $optionArr['options'][] = array( + 'label' => $option->getTitle(), + 'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()), + 'option_id' => $option->getId(), + 'option_value' => $quoteItemOption->getValue() + ); + } + } + } + + if ($productTypeConfig = $this->getProduct($product)->getCustomOption('product_type')) { + $optionArr['super_product_config'] = array( + 'product_code' => $productTypeConfig->getCode(), + 'product_type' => $productTypeConfig->getValue(), + 'product_id' => $productTypeConfig->getProductId() + ); + } + + return $optionArr; + } + + /** + * Save type related data + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function save($product = null) + { + return $this; + } + + /** + * Before save type related data + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function beforeSave($product = null) + { + $this->getProduct($product)->canAffectOptions(true); + return $this; + } + + /** + * Check if product is composite (grouped, configurable, etc) + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isComposite($product = null) + { + return $this->_isComposite; + } + + /** + * Default action to get sku of product + * + * @param Mage_Catalog_Model_Product $product + * @return string + */ + public function getSku($product = null) + { + $skuDelimiter = '-'; + $sku = $this->getProduct($product)->getData('sku'); + if ($optionIds = $this->getProduct($product)->getCustomOption('option_ids')) { + foreach (explode(',', $optionIds->getValue()) as $optionId) { + if ($option = $this->getProduct($product)->getOptionById($optionId)) { + + $quoteItemOption = $this->getProduct($product)->getCustomOption('option_'.$optionId); + + $group = $option->groupFactory($option->getType()) + ->setOption($option); + + if ($optionSku = $group->getOptionSku($quoteItemOption->getValue(), $skuDelimiter)) { + $sku .= $skuDelimiter . $optionSku; + } + } + } + } + return $sku; + } + + /** + * Default action to get weight of product + * + * @param Mage_Catalog_Model_Product $product + * @return decimal + */ + public function getWeight($product = null) + { + return $this->getProduct($product)->getData('weight'); + } + + /** + * Return true if product has options + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function hasOptions($product = null) + { + if ($this->getProduct($product)->getHasOptions()) { + return true; + } + return false; + } + + /** + * Method is needed for specific actions to change given quote options values + * according current product type logic + * Example: the cataloginventory validation of decimal qty can change qty to int, + * so need to change quote item qty option value too. + * + * @param array $options + * @param Varien_Object $option + * @param mixed $value + * + * @return object Mage_Catalog_Model_Product_Type_Abstract + */ + public function updateQtyOption($options, Varien_Object $option, $value, $product = null) + { + return $this; + } + + /** + * Check if product has required options + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function hasRequiredOptions($product = null) + { + if ($this->getProduct($product)->getRequiredOptions()) { + return true; + } + return false; + } + + /** + * Retrive store filter for associated products + * + * @return int|Mage_Core_Model_Store + */ + public function getStoreFilter($product = null) + { + $cacheKey = '_cache_instance_store_filter'; + return $this->getProduct($product)->getData($cacheKey); + } + + /** + * Set store filter for associated products + * + * @param $store int|Mage_Core_Model_Store + * @return Mage_Catalog_Model_Product_Type_Configurable + */ + public function setStoreFilter($store=null, $product = null) + { + $cacheKey = '_cache_instance_store_filter'; + $this->getProduct($product)->setData($cacheKey, $store); + return $this; + } + + /** + * Allow for updates of chidren qty's + * (applicable for complicated product types. As default returns false) + * + * @return boolean false + */ + public function getForceChildItemQtyChanges($product = null) + { + return false; + } + + /** + * Prepare Quote Item Quantity + * + * @param mixed $qty + * @return float + */ + public function prepareQuoteItemQty($qty, $product = null) + { + return floatval($qty); + } + + /** + * Implementation of product specify logic of which product needs to be assigned to option. + * For example if product which was added to option already removed from catalog. + * + * @param Mage_Catalog_Model_Product $optionProduct + * @param Mage_Sales_Model_Quote_Item_Option $option + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function assignProductToOption($optionProduct, $option, $product = null) + { + if ($optionProduct) { + $option->setProduct($optionProduct); + } else { + $option->setProduct($this->getProduct($product)); + } + + return $this; + } + + /** + * Setting specified product type variables + * + * @param array $config + * @return Mage_Catalog_Model_Product_Type_Abstract + */ + public function setConfig($config) + { + if (isset($config['composite'])) { + $this->_isComposite = (bool) $config['composite']; + } + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php new file mode 100644 index 0000000000..8fa4493970 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Catalog_Model_Product_Type_Api_V2 extends Mage_Catalog_Model_Product_Type_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php index ef426a860f..a4f42629c0 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php @@ -36,18 +36,54 @@ class Mage_Catalog_Model_Product_Type_Configurable extends Mage_Catalog_Model_Product_Type_Abstract { const TYPE_CODE = 'configurable'; + + /** + * Cache key for Used Product Attribute Ids + * + * @var string + */ + protected $_usedProductAttributeIds = '_cache_instance_used_product_attribute_ids'; + + /** + * Cache key for Used Product Attributes + * + * @var string + */ + protected $_usedProductAttributes = '_cache_instance_used_product_attributes'; + /** - * Attributes which used for configurable product + * Cache key for Used Attributes * - * @var array + * @var string */ - protected $_usedProductAttributeIds = null; - protected $_usedProductAttributes = null; - protected $_usedAttributes = null; - protected $_configurableAttributes = null; - protected $_usedProductIds = null; - protected $_usedProducts = null; + protected $_usedAttributes = '_cache_instance_used_attributes'; + /** + * Cache key for configurable attributes + * + * @var string + */ + protected $_configurableAttributes = '_cache_instance_configurable_attributes'; + + /** + * Cache key for Used product ids + * + * @var string + */ + protected $_usedProductIds = '_cache_instance_product_ids'; + + /** + * Cache key for used products + * + * @var string + */ + protected $_usedProducts = '_cache_instance_products'; + + /** + * Product is composite + * + * @var bool + */ protected $_isComposite = true; /** @@ -95,15 +131,16 @@ public function getParentIdsByChild($childId) /** * Retrieve product type attributes * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getEditableAttributes() + public function getEditableAttributes($product = null) { if (is_null($this->_editableAttributes)) { - $this->_editableAttributes = parent::getEditableAttributes(); + $this->_editableAttributes = parent::getEditableAttributes($product); foreach ($this->_editableAttributes as $index => $attribute) { - if ($this->getUsedProductAttributeIds() - && in_array($attribute->getAttributeId(), $this->getUsedProductAttributeIds())) { + if ($this->getUsedProductAttributeIds($product) + && in_array($attribute->getAttributeId(), $this->getUsedProductAttributeIds($product))) { unset($this->_editableAttributes[$index]); } } @@ -131,79 +168,95 @@ public function canUseAttribute(Mage_Eav_Model_Entity_Attribute $attribute) * Declare attribute identifiers used for asign subproducts * * @param array $ids + * @param Mage_Catalog_Model_Product $product * @return Mage_Catalog_Model_Product_Type_Configurable */ - public function setUsedProductAttributeIds($ids) + public function setUsedProductAttributeIds($ids, $product = null) { - $this->_usedProductAttributes = array(); - $this->_configurableAttributes= array(); + $usedProductAttributes = array(); + $configurableAttributes = array(); foreach ($ids as $attributeId) { - $this->_usedProductAttributes[] = $this->getAttributeById($attributeId); - $this->_configurableAttributes[]= Mage::getModel('catalog/product_type_configurable_attribute') + $usedProductAttributes[] = $this->getAttributeById($attributeId); + $configurableAttributes[] = Mage::getModel('catalog/product_type_configurable_attribute') ->setProductAttribute($this->getAttributeById($attributeId)); } - $this->_usedProductAttributeIds = $ids; + $this->getProduct($product)->setData($this->_usedProductAttributes, $usedProductAttributes); + $this->getProduct($product)->setData($this->_usedProductAttributeIds, $ids); + $this->getProduct($product)->setData($this->_configurableAttributes, $configurableAttributes); + return $this; } /** * Retrieve identifiers of used product attributes * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getUsedProductAttributeIds() + public function getUsedProductAttributeIds($product = null) { - if (is_null($this->_usedProductAttributeIds)) { - $this->_usedProductAttributeIds = array(); - foreach ($this->getUsedProductAttributes() as $attribute) { - $this->_usedProductAttributeIds[] = $attribute->getId(); + if (!$this->getProduct($product)->hasData($this->_usedProductAttributeIds)) { + $usedProductAttributeIds = array(); + foreach ($this->getUsedProductAttributes($product) as $attribute) { + $usedProductAttributeIds[] = $attribute->getId(); } + $this->getProduct($product)->setData($this->_usedProductAttributeIds, $usedProductAttributeIds); } - return $this->_usedProductAttributeIds; + return $this->getProduct($product)->getData($this->_usedProductAttributeIds); } /** * Retrieve used product attributes * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getUsedProductAttributes() + public function getUsedProductAttributes($product = null) { - if (is_null($this->_usedProductAttributes)) { - $this->_usedProductAttributes = array(); - $this->_usedAttributes = array(); - foreach ($this->getConfigurableAttributes() as $attribute) { + if (!$this->getProduct($product)->hasData($this->_usedProductAttributes)) { + $usedProductAttributes = array(); + $usedAttributes = array(); + foreach ($this->getConfigurableAttributes($product) as $attribute) { $id = $attribute->getProductAttribute()->getId(); - $this->_usedProductAttributes[$id] = $attribute->getProductAttribute(); - $this->_usedAttributes[$id] = $attribute; + $usedProductAttributes[$id] = $attribute->getProductAttribute(); + $usedAttributes[$id] = $attribute; } + $this->getProduct($product)->setData($this->_usedAttributes, $usedAttributes); + $this->getProduct($product)->setData($this->_usedProductAttributes, $usedProductAttributes); } - return $this->_usedProductAttributes; + return $this->getProduct($product)->getData($this->_usedProductAttributes); } /** * Retrieve configurable attrbutes data * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getConfigurableAttributes() + public function getConfigurableAttributes($product = null) { Varien_Profiler::start('CONFIGURABLE:'.__METHOD__); - if (is_null($this->_configurableAttributes)) { - $this->_configurableAttributes = $this->getConfigurableAttributeCollection() + if (!$this->getProduct($product)->hasData($this->_configurableAttributes)) { + $configurableAttributes = $this->getConfigurableAttributeCollection($product) ->orderByPosition() ->load(); - + $this->getProduct($product)->setData($this->_configurableAttributes, $configurableAttributes); } Varien_Profiler::stop('CONFIGURABLE:'.__METHOD__); - return $this->_configurableAttributes; + return $this->getProduct($product)->getData($this->_configurableAttributes); } - public function getConfigurableAttributesAsArray() + /** + * Retrieve Configurable Attributes as array + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getConfigurableAttributesAsArray($product = null) { $res = array(); - foreach ($this->getConfigurableAttributes() as $attribute) { + foreach ($this->getConfigurableAttributes($product) as $attribute) { $label = $attribute->getLabel() ? $attribute->getLabel() : $attribute->getProductAttribute()->getFrontend()->getLabel(); $res[] = array( 'id' => $attribute->getId(), @@ -218,122 +271,146 @@ public function getConfigurableAttributesAsArray() return $res; } - public function getConfigurableAttributeCollection() + /** + * Retrieve configurable atrribute collection + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection + */ + public function getConfigurableAttributeCollection($product = null) { return Mage::getResourceModel('catalog/product_type_configurable_attribute_collection') - ->setProductFilter($this->getProduct()); + ->setProductFilter($this->getProduct($product)); } /** * Retrieve subproducts identifiers * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getUsedProductIds() + public function getUsedProductIds($product = null) { - if (is_null($this->_usedProductIds)) { - $this->_usedProductIds = array(); - foreach ($this->getUsedProducts() as $product) { - $this->_usedProductIds[] = $product->getId(); + if (!$this->getProduct($product)->hasData($this->_usedProductIds)) { + $usedProductIds = array(); + foreach ($this->getUsedProducts(null, $product) as $product) { + $usedProductIds[] = $product->getId(); } + $this->getProduct($product)->setData($this->_usedProductIds, $usedProductIds); } - return $this->_usedProductIds; + return $this->getProduct($product)->getData($this->_usedProductIds); } /** * Retrieve array of "subproducts" * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getUsedProducts($requiredAttributeIds=null) + public function getUsedProducts($requiredAttributeIds = null, $product = null) { Varien_Profiler::start('CONFIGURABLE:'.__METHOD__); - if (is_null($this->_usedProducts)) { - if (is_null($requiredAttributeIds) && is_null($this->_configurableAttributes)) { + if (!$this->getProduct($product)->hasData($this->_usedProducts)) { + if (is_null($requiredAttributeIds) + and is_null($this->getProduct($product)->getData($this->_configurableAttributes))) { // If used products load before attributes, we will load attributes. - $this->getConfigurableAttributes(); + $this->getConfigurableAttributes($product); // After attributes loading products loaded too. - return $this->_usedProducts; + Varien_Profiler::stop('CONFIGURABLE:'.__METHOD__); + return $this->getProduct($product)->getData($this->_usedProducts); } - $this->_usedProducts = array(); - $collection = $this->getUsedProductCollection() + $usedProducts = array(); + $collection = $this->getUsedProductCollection($product) ->addAttributeToSelect('*') ->addFilterByRequiredOptions(); if (is_array($requiredAttributeIds)) { foreach ($requiredAttributeIds as $attributeId) { - $attribute = $this->getAttributeById($attributeId); + $attribute = $this->getAttributeById($attributeId, $product); if (!is_null($attribute)) $collection->addAttributeToFilter($attribute->getAttributeCode(), array('notnull'=>1)); } } - foreach ($collection as $product) { - $this->_usedProducts[] = $product; + foreach ($collection as $item) { + $usedProducts[] = $item; } + + $this->getProduct($product)->setData($this->_usedProducts, $usedProducts); } Varien_Profiler::stop('CONFIGURABLE:'.__METHOD__); - return $this->_usedProducts; + return $this->getProduct($product)->getData($this->_usedProducts); } /** * Retrieve related products collection * - * @return unknown + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Product_Collection */ - public function getUsedProductCollection() + public function getUsedProductCollection($product = null) { $collection = Mage::getResourceModel('catalog/product_type_configurable_product_collection') - ->setProductFilter($this->getProduct()); - if (!is_null($this->getStoreFilter())) { - $collection->addStoreFilter($this->getStoreFilter()); + ->setFlag('require_stock_items', true) + ->setProductFilter($this->getProduct($product)); + if (!is_null($this->getStoreFilter($product))) { + $collection->addStoreFilter($this->getStoreFilter($product)); } return $collection; } - public function beforeSave() + /** + * Before save process + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Configurable + */ + public function beforeSave($product = null) { - parent::beforeSave(); + parent::beforeSave($product); - $this->getProduct()->canAffectOptions(false); + $this->getProduct($product)->canAffectOptions(false); - if ($this->getProduct()->getCanSaveConfigurableAttributes()) { - $this->getProduct()->canAffectOptions(true); - if ($data = $this->getProduct()->getConfigurableAttributesData()) { + if ($this->getProduct($product)->getCanSaveConfigurableAttributes()) { + $this->getProduct($product)->canAffectOptions(true); + if ($data = $this->getProduct($product)->getConfigurableAttributesData()) { if (!empty($data)) { foreach ($data as $attribute) { if (!empty($attribute['values'])) { - $this->getProduct()->setTypeHasOptions(true); - $this->getProduct()->setTypeHasRequiredOptions(true); + $this->getProduct($product)->setTypeHasOptions(true); + $this->getProduct($product)->setTypeHasRequiredOptions(true); break; } } } } } + + return $this; } /** * Save configurable product depended data * + * @param Mage_Catalog_Model_Product $product * @return Mage_Catalog_Model_Product_Type_Configurable */ - public function save() + public function save($product = null) { - parent::save(); + parent::save($product); /** * Save Attributes Information */ - if ($data = $this->getProduct()->getConfigurableAttributesData()) { + if ($data = $this->getProduct($product)->getConfigurableAttributesData()) { foreach ($data as $attributeData) { $id = isset($attributeData['id']) ? $attributeData['id'] : null; - $attribute = Mage::getModel('catalog/product_type_configurable_attribute') + Mage::getModel('catalog/product_type_configurable_attribute') ->setData($attributeData) ->setId($id) - ->setStoreId($this->getProduct()->getStoreId()) - ->setProductId($this->getProduct()->getId()) + ->setStoreId($this->getProduct($product)->getStoreId()) + ->setProductId($this->getProduct($product)->getId()) ->save(); } } @@ -341,11 +418,11 @@ public function save() /** * Save product relations */ - $data = $this->getProduct()->getConfigurableProductsData(); + $data = $this->getProduct($product)->getConfigurableProductsData(); if (is_array($data)) { $productIds = array_keys($data); Mage::getResourceModel('catalog/product_type_configurable') - ->saveProducts($this->getProduct()->getId(), $productIds); + ->saveProducts($this->getProduct($product)->getId(), $productIds); } return $this; } @@ -355,16 +432,16 @@ public function save() * * @return bool */ - public function isSalable() + public function isSalable($product = null) { - $salable = parent::isSalable(); + $salable = parent::isSalable($product); if (!is_null($salable)) { return $salable; } $salable = false; - foreach ($this->getUsedProducts() as $product) { - $salable = $salable || $product->isSalable(); + foreach ($this->getUsedProducts(null, $product) as $child) { + $salable = $salable || $child->isSalable(); } return $salable; } @@ -374,37 +451,47 @@ public function isSalable() * $attrbutesInfo = array( * $attributeId => $attributeValue * ) + * * @param array $attrbutesInfo + * @param Mage_Catalog_Model_Product $product * @return */ - public function getProductByAttributes($attributesInfo) + public function getProductByAttributes($attributesInfo, $product = null) { - foreach ($this->getUsedProducts() as $product) { + foreach ($this->getUsedProducts(null, $product) as $productObject) { $checkRes = true; foreach ($attributesInfo as $attributeId => $attributeValue) { - $code = $this->getAttributeById($attributeId)->getAttributeCode(); - if ($product->getData($code) != $attributeValue) { + $code = $this->getAttributeById($attributeId, $product)->getAttributeCode(); + if ($productObject->getData($code) != $attributeValue) { $checkRes = false; } } if ($checkRes) { - return $product; + return $productObject; } } return null; } - public function getSelectedAttributesInfo() + /** + * Retrieve Selected Attributes info + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getSelectedAttributesInfo($product = null) { $attributes = array(); Varien_Profiler::start('CONFIGURABLE:'.__METHOD__); - if ($attributesOption = $this->getProduct()->getCustomOption('attributes')) { + if ($attributesOption = $this->getProduct($product)->getCustomOption('attributes')) { $data = unserialize($attributesOption->getValue()); - $this->getUsedProductAttributeIds(); + $this->getUsedProductAttributeIds($product); + + $usedAttributes = $this->getProduct($product)->getData($this->_usedAttributes); foreach ($data as $attributeId => $attributeValue) { - if (isset($this->_usedAttributes[$attributeId])) { - $attribute = $this->_usedAttributes[$attributeId]; + if (isset($usedAttributes[$attributeId])) { + $attribute = $usedAttributes[$attributeId]; $label = $attribute->getLabel(); $value = $attribute->getProductAttribute(); if ($value->getSourceModel()) { @@ -426,23 +513,24 @@ public function getSelectedAttributesInfo() * Initialize product(s) for add to cart process * * @param Varien_Object $buyRequest - * @return unknown + * @param Mage_Catalog_Model_Product $product + * @return mixed */ - public function prepareForCart(Varien_Object $buyRequest) + public function prepareForCart(Varien_Object $buyRequest, $product = null) { if ($attributes = $buyRequest->getSuperAttribute()) { - $result = parent::prepareForCart($buyRequest); + $result = parent::prepareForCart($buyRequest, $product); if (is_array($result)) { - $product = $this->getProduct(); + $product = $this->getProduct($product); /** * $attributes = array($attributeId=>$attributeValue) */ - if ($subProduct = $this->getProductByAttributes($attributes)) { + if ($subProduct = $this->getProductByAttributes($attributes, $product)) { $product->addCustomOption('attributes', serialize($attributes)); $product->addCustomOption('product_qty_'.$subProduct->getId(), 1, $subProduct); $product->addCustomOption('simple_product', $subProduct->getId(), $subProduct); - $_result = $subProduct->getTypeInstance()->prepareForCart($buyRequest); + $_result = $subProduct->getTypeInstance(true)->prepareForCart($buyRequest, $subProduct); if (is_string($_result) && !is_array($_result)) { return $_result; } @@ -473,6 +561,16 @@ public function prepareForCart(Varien_Object $buyRequest) } } } + return $this->getSpecifyOptionMessage(); + } + + /** + * Retrieve message for specify option(s) + * + * @return string + */ + public function getSpecifyOptionMessage() + { return Mage::helper('catalog')->__('Please specify the product option(s)'); } @@ -480,15 +578,16 @@ public function prepareForCart(Varien_Object $buyRequest) * Prepare additional options/information for order item which will be * created from this product * - * @return attay + * @param Mage_Catalog_Model_Product $product + * @return array */ - public function getOrderOptions() + public function getOrderOptions($product = null) { - $options = parent::getOrderOptions(); - $options['attributes_info'] = $this->getSelectedAttributesInfo(); - if ($simpleOption = $this->getProduct()->getCustomOption('simple_product')) { - $options['simple_name'] = $simpleOption->getProduct()->getName(); - $options['simple_sku'] = $simpleOption->getProduct()->getSku(); + $options = parent::getOrderOptions($product); + $options['attributes_info'] = $this->getSelectedAttributesInfo($product); + if ($simpleOption = $this->getProduct($product)->getCustomOption('simple_product')) { + $options['simple_name'] = $simpleOption->getProduct($product)->getName(); + $options['simple_sku'] = $simpleOption->getProduct($product)->getSku(); } $options['product_calculations'] = self::CALCULATE_PARENT; @@ -502,31 +601,32 @@ public function getOrderOptions() * * @return bool */ - public function isVirtual() + public function isVirtual($product = null) { - if ($productOption = $this->getProduct()->getCustomOption('simple_product')) { - if ($product = $productOption->getProduct()) { - /* @var $product Mage_Catalog_Model_Product */ - return $product->getTypeInstance()->isVirtual(); + if ($productOption = $this->getProduct($product)->getCustomOption('simple_product')) { + if ($optionProduct = $productOption->getProduct()) { + /* @var $optionProduct Mage_Catalog_Model_Product */ + return $optionProduct->isVirtual(); } } - return parent::isVirtual(); + return parent::isVirtual($product); } /** * Return true if product has options * + * @param Mage_Catalog_Model_Product $product * @return bool */ - public function hasOptions() + public function hasOptions($product = null) { - if ($this->getProduct()->getOptions()) { + if ($this->getProduct($product)->getOptions()) { return true; } - $attributes = $this->getConfigurableAttributes(); + $attributes = $this->getConfigurableAttributes($product); if (count($attributes)) { - foreach ($attributes as $key => $attribute) { + foreach ($attributes as $attribute) { /** @var Mage_Catalog_Model_Product_Type_Configurable_Attribute $attribute */ if ($attribute->getData('prices')) { return true; @@ -541,18 +641,19 @@ public function hasOptions() * Return product weight based on simple product * weight or configurable product weight * + * @param Mage_Catalog_Model_Product $product * @return decimal */ - public function getWeight() + public function getWeight($product = null) { - if ($this->getProduct()->hasCustomOptions() && ($simpleProductOption = $this->getProduct()->getCustomOption('simple_product'))) { - $simpleProduct = $simpleProductOption->getProduct(); + if ($this->getProduct($product)->hasCustomOptions() && ($simpleProductOption = $this->getProduct($product)->getCustomOption('simple_product'))) { + $simpleProduct = $simpleProductOption->getProduct($product); if ($simpleProduct) { return $simpleProduct->getWeight(); } } - return $this->getProduct()->getData('weight'); + return $this->getProduct($product)->getData('weight'); } /** @@ -561,15 +662,16 @@ public function getWeight() * * @param Mage_Catalog_Model_Product $optionProduct * @param Mage_Sales_Model_Quote_Item_Option $option + * @param Mage_Catalog_Model_Product $product * @return Mage_Catalog_Model_Product_Type_Abstract */ - public function assignProductToOption($optionProduct, $option) + public function assignProductToOption($optionProduct, $option, $product = null) { if ($optionProduct) { $option->setProduct($optionProduct); } else { $option->getItem()->setHasError('error'); - $option->getItem()->addMessage(Mage::helper('catalog')->__('Selected configuration is not available.', $this->getProduct()->getName())); + $option->getItem()->addMessage(Mage::helper('catalog')->__('Selected configuration is not available.', $this->getProduct($product)->getName())); } return $this; diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php index c1b53ade40..24940699ff 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php @@ -1,101 +1,103 @@ - - */ -class Mage_Catalog_Model_Product_Type_Configurable_Price extends Mage_Catalog_Model_Product_Type_Price -{ - /** - * Get product final price - * - * @param double $qty - * @param Mage_Catalog_Model_Product $product - * @return double - */ - public function getFinalPrice($qty=null, $product) - { - if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) { - return $product->getCalculatedFinalPrice(); - } - - $finalPrice = parent::getFinalPrice($qty, $product); - $product->getTypeInstance()->setStoreFilter($product->getStore()); - $attributes = $product->getTypeInstance()->getConfigurableAttributes(); - - $selectedAttributes = array(); - if ($product->getCustomOption('attributes')) { - $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue()); - } - - $basePrice = $finalPrice; - foreach ($attributes as $attribute) { - $attributeId = $attribute->getProductAttribute()->getId(); - $value = $this->_getValueByIndex( - $attribute->getPrices() ? $attribute->getPrices() : array(), - isset($selectedAttributes[$attributeId]) ? $selectedAttributes[$attributeId] : null - ); - if($value) { - if($value['pricing_value'] != 0) { - $finalPrice += $this->_calcSelectionPrice($value, $basePrice); - } - } - } - $product->setFinalPrice($finalPrice); - return max(0, $product->getData('final_price')); - } - - /** - * Calculate configurable product selection price - * - * @param array $priceInfo - * @param decimal $productPrice - * @return decimal - */ - protected function _calcSelectionPrice($priceInfo, $productPrice) - { - if($priceInfo['is_percent']) { - $ratio = $priceInfo['pricing_value']/100; - $price = $productPrice * $ratio; - } else { - $price = $priceInfo['pricing_value']; - } - return $price; - } - - protected function _getValueByIndex($values, $index) { - foreach ($values as $value) { - if($value['value_index'] == $index) { - return $value; - } - } - return false; - } + + */ +class Mage_Catalog_Model_Product_Type_Configurable_Price extends Mage_Catalog_Model_Product_Type_Price +{ + /** + * Get product final price + * + * @param double $qty + * @param Mage_Catalog_Model_Product $product + * @return double + */ + public function getFinalPrice($qty=null, $product) + { + if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) { + return $product->getCalculatedFinalPrice(); + } + + $finalPrice = parent::getFinalPrice($qty, $product); + $product->getTypeInstance(true) + ->setStoreFilter($product->getStore(), $product); + $attributes = $product->getTypeInstance(true) + ->getConfigurableAttributes($product); + + $selectedAttributes = array(); + if ($product->getCustomOption('attributes')) { + $selectedAttributes = unserialize($product->getCustomOption('attributes')->getValue()); + } + + $basePrice = $finalPrice; + foreach ($attributes as $attribute) { + $attributeId = $attribute->getProductAttribute()->getId(); + $value = $this->_getValueByIndex( + $attribute->getPrices() ? $attribute->getPrices() : array(), + isset($selectedAttributes[$attributeId]) ? $selectedAttributes[$attributeId] : null + ); + if($value) { + if($value['pricing_value'] != 0) { + $finalPrice += $this->_calcSelectionPrice($value, $basePrice); + } + } + } + $product->setFinalPrice($finalPrice); + return max(0, $product->getData('final_price')); + } + + /** + * Calculate configurable product selection price + * + * @param array $priceInfo + * @param decimal $productPrice + * @return decimal + */ + protected function _calcSelectionPrice($priceInfo, $productPrice) + { + if($priceInfo['is_percent']) { + $ratio = $priceInfo['pricing_value']/100; + $price = $productPrice * $ratio; + } else { + $price = $priceInfo['pricing_value']; + } + return $price; + } + + protected function _getValueByIndex($values, $index) { + foreach ($values as $value) { + if($value['value_index'] == $index) { + return $value; + } + } + return false; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Grouped.php b/app/code/core/Mage/Catalog/Model/Product/Type/Grouped.php index 4b3ecefb1c..2a4423b972 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Grouped.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Grouped.php @@ -1,264 +1,309 @@ - - */ -class Mage_Catalog_Model_Product_Type_Grouped extends Mage_Catalog_Model_Product_Type_Abstract -{ - const TYPE_CODE = 'grouped'; - protected $_associatedProducts = null; - protected $_associatedProductIds= null; - protected $_statusFilters = null; - protected $_isComposite = true; - - /** - * Return relation info about used products - * - * @return Varien_Object Object with information data - */ - public function getRelationInfo() - { - $info = new Varien_Object(); - $info->setTable('catalog/product_link') - ->setParentFieldName('product_id') - ->setChildFieldName('linked_product_id') - ->setWhere('link_type_id=' . Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); - return $info; - } - - /** - * Retrieve Required children ids - * Return grouped array, ex array( - * group => array(ids) - * ) - * - * @param int $parentId - * @param bool $required - * @return array - */ - public function getChildrenIds($parentId, $required = true) - { - return Mage::getResourceSingleton('catalog/product_link') - ->getChildrenIds($parentId, - Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); - } - - /** - * Retrieve parent ids array by requered child - * - * @param int $childId - * @return array - */ - public function getParentIdsByChild($childId) - { - return Mage::getResourceSingleton('catalog/product_link') - ->getParentIdsByChild($childId, - Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); - } - - /** - * Retrieve array of associated products - * - * @return array - */ - public function getAssociatedProducts() - { - if (is_null($this->_associatedProducts)) { - $this->_associatedProducts = array(); - - if (!Mage::app()->getStore()->isAdmin()) { - $this->setSaleableStatus(); - } - - $collection = $this->getAssociatedProductCollection() - ->addAttributeToSelect('*') - ->addFilterByRequiredOptions() - ->setPositionOrder() - ->addStoreFilter($this->getStoreFilter()) - ->addAttributeToFilter('status', array('in' => $this->getStatusFilters())); - - foreach ($collection as $product) { - $this->_associatedProducts[] = $product; - } - } - return $this->_associatedProducts; - } - - /** - * Add status filter to collection - * - * @param int $status - * @return void - */ - public function addStatusFilter ($status) - { - $this->_statusFilters[] = $status; - return $this; - } - - /** - * Set only saleable filter - * - * @param none - * @return void - */ - public function setSaleableStatus () - { - $this->_statusFilters = Mage::getSingleton('catalog/product_status')->getSaleableStatusIds(); - return $this; - } - - /** - * Return all assigned status filters - * - * @param none - * @return void - */ - public function getStatusFilters () - { - if ($this->_statusFilters === null) { - return array( - Mage_Catalog_Model_Product_Status::STATUS_ENABLED, - Mage_Catalog_Model_Product_Status::STATUS_DISABLED - ); - } - return $this->_statusFilters; - } - - /** - * Retrieve related products identifiers - * - * @return array - */ - public function getAssociatedProductIds() - { - if (is_null($this->_associatedProductIds)) { - $this->_associatedProductIds = array(); - foreach ($this->getAssociatedProducts() as $product) { - $this->_associatedProductIds[] = $product->getId(); - } - } - return $this->_associatedProductIds; - } - - /** - * Retrieve collection of associated products - */ - public function getAssociatedProductCollection() - { - $collection = $this->getProduct()->getLinkInstance()->useGroupedLinks() - ->getProductCollection() - ->setIsStrongMode(); - $collection->setProduct($this->getProduct()); - return $collection; - } - - /** - * Check is product available for sale - * - * @return bool - */ - public function isSalable() - { - $salable = parent::isSalable(); - if (!is_null($salable)) { - return $salable; - } - - $salable = false; - foreach ($this->getAssociatedProducts() as $product) { - $salable = $salable || $product->isSalable(); - } - return $salable; - } - - /** - * Save type related data - * - * @return unknown - */ - public function save() - { - parent::save(); - $this->getProduct()->getLinkInstance()->saveGroupedLinks($this->getProduct()); - return $this; - } - - /** - * Initialize product(s) for add to cart process - * - * @param Varien_Object $buyRequest - * @return array || string || false - */ - public function prepareForCart(Varien_Object $buyRequest) - { - $productsInfo = $buyRequest->getSuperGroup(); - if (!empty($productsInfo) && is_array($productsInfo)) { - $products = array(); - $associatedProducts = $this->getAssociatedProducts(); - if ($associatedProducts) { - $productId = $this->getProduct()->getId(); - foreach ($associatedProducts as $subProduct) { - if(isset($productsInfo[$subProduct->getId()])) { - $qty = $productsInfo[$subProduct->getId()]; - if (!empty($qty)) { - - $_result = $subProduct->getTypeInstance()->prepareForCart($buyRequest); - if (is_string($_result) && !is_array($_result)) { - return $_result; - } - - if (!isset($_result[0])) { - return Mage::helper('checkout')->__('Can not add item to shopping cart'); - } - - $_result[0]->setCartQty($qty); - $_result[0]->addCustomOption('product_type', self::TYPE_CODE, $this->getProduct()); - $_result[0]->addCustomOption('info_buyRequest', - serialize(array( - 'super_product_config' => array( - 'product_type' => self::TYPE_CODE, - 'product_id' => $this->getProduct()->getId() - ) - )) - ); - $products[] = $_result[0]; - } - } - } - } - if (count($products)) { - return $products; - } - } - return Mage::helper('catalog')->__('Please specify the product(s) quantity'); - } + + */ +class Mage_Catalog_Model_Product_Type_Grouped extends Mage_Catalog_Model_Product_Type_Abstract +{ + const TYPE_CODE = 'grouped'; + + /** + * Cache key for Associated Products + * + * @var string + */ + protected $_keyAssociatedProducts = '_cache_instance_associated_products'; + + /** + * Cache key for Associated Product Ids + * + * @var string + */ + protected $_keyAssociatedProductIds = '_cache_instance_associated_product_ids'; + + /** + * Cache key for Status Filters + * + * @var string + */ + protected $_keyStatusFilters = '_cache_instance_status_filters'; + + /** + * Product is composite properties + * + * @var bool + */ + protected $_isComposite = true; + + /** + * Return relation info about used products + * + * @return Varien_Object Object with information data + */ + public function getRelationInfo() + { + $info = new Varien_Object(); + $info->setTable('catalog/product_link') + ->setParentFieldName('product_id') + ->setChildFieldName('linked_product_id') + ->setWhere('link_type_id=' . Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); + return $info; + } + + /** + * Retrieve Required children ids + * Return grouped array, ex array( + * group => array(ids) + * ) + * + * @param int $parentId + * @param bool $required + * @return array + */ + public function getChildrenIds($parentId, $required = true) + { + return Mage::getResourceSingleton('catalog/product_link') + ->getChildrenIds($parentId, + Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); + } + + /** + * Retrieve parent ids array by requered child + * + * @param int $childId + * @return array + */ + public function getParentIdsByChild($childId) + { + return Mage::getResourceSingleton('catalog/product_link') + ->getParentIdsByChild($childId, + Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED); + } + + /** + * Retrieve array of associated products + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getAssociatedProducts($product = null) + { + if (!$this->getProduct($product)->hasData($this->_keyAssociatedProducts)) { + $associatedProducts = array(); + + if (!Mage::app()->getStore()->isAdmin()) { + $this->setSaleableStatus($product); + } + + $collection = $this->getAssociatedProductCollection($product) + ->addAttributeToSelect('*') + ->addFilterByRequiredOptions() + ->setPositionOrder() + ->addStoreFilter($this->getStoreFilter($product)) + ->addAttributeToFilter('status', array('in' => $this->getStatusFilters($product))); + + foreach ($collection as $product) { + $associatedProducts[] = $product; + } + + $this->getProduct($product)->setData($this->_keyAssociatedProducts, $associatedProducts); + } + return $this->getProduct($product)->getData($this->_keyAssociatedProducts); + } + + /** + * Add status filter to collection + * + * @param int $status + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Grouped + */ + public function addStatusFilter($status, $product = null) + { + $statusFilters = $this->getProduct($product)->getData($this->_keyStatusFilters); + if (!is_array($statusFilters)) { + $statusFilters = array(); + } + + $statusFilters[] = $status; + $this->getProduct($product)->setData($this->_keyStatusFilters, $statusFilters); + + return $this; + } + + /** + * Set only saleable filter + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Grouped + */ + public function setSaleableStatus($product = null) + { + $this->getProduct($product)->setData($this->_keyStatusFilters, + Mage::getSingleton('catalog/product_status')->getSaleableStatusIds()); + return $this; + } + + /** + * Return all assigned status filters + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getStatusFilters($product = null) + { + if (!$this->getProduct($product)->hasData($this->_keyStatusFilters)) { + return array( + Mage_Catalog_Model_Product_Status::STATUS_ENABLED, + Mage_Catalog_Model_Product_Status::STATUS_DISABLED + ); + } + return $this->getProduct($product)->getData($this->_keyStatusFilters); + } + + /** + * Retrieve related products identifiers + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getAssociatedProductIds($product = null) + { + if (!$this->getProduct($product)->hasData($this->_keyAssociatedProductIds)) { + $associatedProductIds = array(); + foreach ($this->getAssociatedProducts($product) as $product) { + $associatedProductIds[] = $product->getId(); + } + $this->getProduct($product)->setData($this->_keyAssociatedProductIds, $associatedProductIds); + } + return $this->getProduct($product)->getData($this->_keyAssociatedProductIds); + } + + /** + * Retrieve collection of associated products + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection + */ + public function getAssociatedProductCollection($product = null) + { + $collection = $this->getProduct($product)->getLinkInstance()->useGroupedLinks() + ->getProductCollection() + ->setFlag('require_stock_items', true) + ->setIsStrongMode(); + $collection->setProduct($this->getProduct($product)); + return $collection; + } + + /** + * Check is product available for sale + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isSalable($product = null) + { + $salable = parent::isSalable($product); + if (!is_null($salable)) { + return $salable; + } + + $salable = false; + foreach ($this->getAssociatedProducts($product) as $associatedProduct) { + $salable = $salable || $associatedProduct->isSalable(); + } + return $salable; + } + + /** + * Save type related data + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Catalog_Model_Product_Type_Grouped + */ + public function save($product = null) + { + parent::save($product); + $this->getProduct($product)->getLinkInstance()->saveGroupedLinks($this->getProduct($product)); + return $this; + } + + /** + * Initialize product(s) for add to cart process + * + * @param Varien_Object $buyRequest + * @param Mage_Catalog_Model_Product $product + * @return array || string || false + */ + public function prepareForCart(Varien_Object $buyRequest, $product = null) + { + $productsInfo = $buyRequest->getSuperGroup(); + if (!empty($productsInfo) && is_array($productsInfo)) { + $products = array(); + $associatedProducts = $this->getAssociatedProducts($product); + if ($associatedProducts) { + foreach ($associatedProducts as $subProduct) { + if(isset($productsInfo[$subProduct->getId()])) { + $qty = $productsInfo[$subProduct->getId()]; + if (!empty($qty)) { + + $_result = $subProduct->getTypeInstance(true) + ->prepareForCart($buyRequest, $subProduct); + if (is_string($_result) && !is_array($_result)) { + return $_result; + } + + if (!isset($_result[0])) { + return Mage::helper('checkout')->__('Can not add item to shopping cart'); + } + + $_result[0]->setCartQty($qty); + $_result[0]->addCustomOption('product_type', self::TYPE_CODE, $this->getProduct($product)); + $_result[0]->addCustomOption('info_buyRequest', + serialize(array( + 'super_product_config' => array( + 'product_type' => self::TYPE_CODE, + 'product_id' => $this->getProduct($product)->getId() + ) + )) + ); + $products[] = $_result[0]; + } + } + } + } + if (count($products)) { + return $products; + } + } + return Mage::helper('catalog')->__('Please specify the product(s) quantity'); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Price.php b/app/code/core/Mage/Catalog/Model/Product/Type/Price.php index 74a21b5a3d..acba9283b7 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Price.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Price.php @@ -186,19 +186,7 @@ protected function _getCustomerGroupId($product) */ protected function _applySpecialPrice($product, $finalPrice) { - $specialPrice = $product->getSpecialPrice(); - if (is_numeric($specialPrice)) { - $storeDate = Mage::app()->getLocale()->storeDate($product->getStore()); - $fromDate = Mage::app()->getLocale()->date($product->getSpecialFromDate(), null, null, false); - $toDate = Mage::app()->getLocale()->date($product->getSpecialToDate(), null, null, false); - - if ($product->getSpecialFromDate() && $storeDate->compare($fromDate, Zend_Date::DATES)<0) { - } elseif ($product->getSpecialToDate() && $storeDate->compare($toDate, Zend_Date::DATES)>0) { - } else { - $finalPrice = min($finalPrice, $specialPrice); - } - } - return $finalPrice; + return self::calculateSpecialPrice($finalPrice, $product->getSpecialPrice(), $product->getSpecialFromDate(), $product->getSpecialToDate(), $product->getStore()); } /** @@ -260,26 +248,13 @@ protected function _applyOptionsPrice($product, $qty, $finalPrice) $basePrice = $finalPrice; foreach (explode(',', $optionIds->getValue()) as $optionId) { if ($option = $product->getOptionById($optionId)) { - $optionValue = $product->getCustomOption('option_'.$option->getId())->getValue(); - if ($option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - foreach(split(',', $optionValue) as $value) { - $finalPrice += $this->_getPricingOptionValue(array( - 'is_percent' => ($option->getValueById($value)->getPriceType() == 'percent')? true:false, - 'pricing_value' => $option->getValueById($value)->getPrice() - ), $basePrice); - } - } elseif ($option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $finalPrice += $this->_getPricingOptionValue(array( - 'is_percent' => ($option->getValueById($optionValue)->getPriceType() == 'percent')? true:false, - 'pricing_value' => $option->getValueById($optionValue)->getPrice() - ), $basePrice); - } else { - $finalPrice += $this->_getPricingOptionValue(array( - 'is_percent' => ($option->getPriceType() == 'percent')? true:false, - 'pricing_value' => $option->getPrice() - ), $basePrice); - } + + $quoteItemOption = $product->getCustomOption('option_'.$option->getId()); + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setQuoteItemOption($quoteItemOption); + + $finalPrice += $group->getOptionPrice($quoteItemOption->getValue(), $basePrice); } } } @@ -288,59 +263,77 @@ protected function _applyOptionsPrice($product, $qty, $finalPrice) } /** - * Get product pricing option value + * Calculate product price based on special price data and price rules * - * @param array $value - * @param double $basePrice - * @return double + * @param float $basePrice + * @param float $specialPrice + * @param string $specialPriceFrom + * @param string $specialPriceTo + * @param float|null|false $rulePrice + * @param mixed $wId + * @param mixed $gId + * @param null|int $productId + * @return float */ - protected function _getPricingOptionValue($value, $basePrice) - { - if($value['is_percent']) { - $ratio = $value['pricing_value']/100; - $price = $basePrice * $ratio; - } else { - $price = $value['pricing_value']; - } - - return $price; - } - public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $rulePrice = false, $wId = null, $gId = null, $productId = null) { + Varien_Profiler::start('__PRODUCT_CALCULATE_PRICE__'); if ($wId instanceof Mage_Core_Model_Store) { $sId = $wId->getId(); $wId = $wId->getWebsiteId(); } else { $sId = Mage::app()->getWebsite($wId)->getDefaultGroup()->getDefaultStoreId(); } - $storeDate = Mage::app()->getLocale()->storeDate($sId); + $finalPrice = $basePrice; if ($gId instanceof Mage_Customer_Model_Group) { $gId = $gId->getId(); } - $finalPrice = $basePrice; - $fromDate = Mage::app()->getLocale()->date($specialPriceFrom, null, null, false); - $toDate = Mage::app()->getLocale()->date($specialPriceTo, null, null, false); - - if ($specialPrice !== null && $specialPrice !== false) { - if ($specialPriceFrom && $storeDate->compare($fromDate, Zend_Date::DATES)<0) { - } elseif ($specialPriceTo && $storeDate->compare($toDate, Zend_Date::DATES)>0) { - } else { - $finalPrice = min($finalPrice, $specialPrice); - } - } + $finalPrice = self::calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $sId); if ($rulePrice === false) { - $rulePrice = Mage::getResourceModel('catalogrule/rule')->getRulePrice($storeDate, $wId, $gId, $productId); + $storeTimestamp = Mage::app()->getLocale()->storeTimeStamp($sId); + $rulePrice = Mage::getResourceModel('catalogrule/rule') + ->getRulePrice($storeTimestamp, $wId, $gId, $productId); } + if ($rulePrice !== null && $rulePrice !== false) { $finalPrice = min($finalPrice, $rulePrice); } $finalPrice = max($finalPrice, 0); + Varien_Profiler::stop('__PRODUCT_CALCULATE_PRICE__'); + return $finalPrice; + } + + /** + * Calculate and apply special price + * + * @param float $finalPrice + * @param float $specialPrice + * @param string $specialPriceFrom + * @param string $specialPriceTo + * @param mixed $store + * @return float + */ + public static function calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo, $store = null) + { + if (!is_null($specialPrice) && $specialPrice != false) { + if (!$store instanceof Mage_Core_Model_Store) { + $store = Mage::app()->getStore($store); + } + $storeTimeStamp = Mage::app()->getLocale()->storeTimeStamp($store); + $fromTimeStamp = strtotime($specialPriceFrom); + $toTimeStamp = strtotime($specialPriceTo); + + if ($specialPriceFrom && $storeTimeStamp < $fromTimeStamp) { + } elseif ($specialPriceTo && $storeTimeStamp > $toTimeStamp) { + } else { + $finalPrice = min($finalPrice, $specialPrice); + } + } return $finalPrice; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Virtual.php b/app/code/core/Mage/Catalog/Model/Product/Type/Virtual.php index 176ab1e075..9aa6261e02 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Type/Virtual.php +++ b/app/code/core/Mage/Catalog/Model/Product/Type/Virtual.php @@ -1,45 +1,46 @@ - - */ -class Mage_Catalog_Model_Product_Type_Virtual extends Mage_Catalog_Model_Product_Type_Abstract -{ - /** - * Check is virtual product - * - * @return bool - */ - public function isVirtual() - { - return true; - } + + */ +class Mage_Catalog_Model_Product_Type_Virtual extends Mage_Catalog_Model_Product_Type_Abstract +{ + /** + * Check is virtual product + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function isVirtual($product = null) + { + return true; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Product/Visibility.php b/app/code/core/Mage/Catalog/Model/Product/Visibility.php index d59a6ba219..22eb6edeb7 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Visibility.php +++ b/app/code/core/Mage/Catalog/Model/Product/Visibility.php @@ -20,16 +20,17 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ + /** - * Product visibility model + * Catalog Product visibilite model and attribute source model * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Model_Product_Visibility extends Varien_Object { @@ -38,12 +39,23 @@ class Mage_Catalog_Model_Product_Visibility extends Varien_Object const VISIBILITY_IN_SEARCH = 3; const VISIBILITY_BOTH = 4; + /** + * Initialize object + * + */ public function __construct() { parent::__construct(); $this->setIdFieldName('visibility_id'); } + /** + * Add visible in catalog filter to collection + * + * @deprecated + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @return Mage_Catalog_Model_Product_Visibility + */ public function addVisibleInCatalogFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) { $collection->setVisibility($this->getVisibleInCatalogIds()); @@ -51,6 +63,13 @@ public function addVisibleInCatalogFilterToCollection(Mage_Eav_Model_Entity_Coll return $this; } + /** + * Add visibility in searchfilter to collection + * + * @deprecated + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @return Mage_Catalog_Model_Product_Visibility + */ public function addVisibleInSearchFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) { $collection->setVisibility($this->getVisibleInSearchIds()); @@ -58,6 +77,13 @@ public function addVisibleInSearchFilterToCollection(Mage_Eav_Model_Entity_Colle return $this; } + /** + * Add visibility in site filter to collection + * + * @deprecated + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @return Mage_Catalog_Model_Product_Visibility + */ public function addVisibleInSiteFilterToCollection(Mage_Eav_Model_Entity_Collection_Abstract $collection) { $collection->setVisibility($this->getVisibleInSiteIds()); @@ -65,16 +91,41 @@ public function addVisibleInSiteFilterToCollection(Mage_Eav_Model_Entity_Collect return $this; } + /** + * Retrieve visible in catalog ids array + * + * @return array + */ public function getVisibleInCatalogIds() { return array(self::VISIBILITY_IN_CATALOG, self::VISIBILITY_BOTH); } + /** + * Retrieve visible in search ids array + * + * @return array + */ public function getVisibleInSearchIds() { return array(self::VISIBILITY_IN_SEARCH, self::VISIBILITY_BOTH); } + /** + * Retrieve visible in site ids array + * + * @return array + */ + public function getVisibleInSiteIds() + { + return array(self::VISIBILITY_IN_SEARCH, self::VISIBILITY_IN_CATALOG, self::VISIBILITY_BOTH); + } + + /** + * Retrieve option array + * + * @return array + */ static public function getOptionArray() { return array( @@ -85,6 +136,11 @@ static public function getOptionArray() ); } + /** + * Retrieve all options + * + * @return array + */ static public function getAllOption() { $options = self::getOptionArray(); @@ -92,27 +148,65 @@ static public function getAllOption() return $options; } + /** + * Retireve all options + * + * @return array + */ static public function getAllOptions() { $res = array(); $res[] = array('value'=>'', 'label'=> Mage::helper('catalog')->__('-- Please Select --')); foreach (self::getOptionArray() as $index => $value) { - $res[] = array( - 'value' => $index, - 'label' => $value - ); + $res[] = array( + 'value' => $index, + 'label' => $value + ); } return $res; } + /** + * Retrieve option text + * + * @param int $optionId + * @return string + */ static public function getOptionText($optionId) { $options = self::getOptionArray(); return isset($options[$optionId]) ? $options[$optionId] : null; } - public function getVisibleInSiteIds() + /** + * Retrieve Column(s) for Flat + * + * @return array + */ + public function getFlatColums() { - return array(self::VISIBILITY_IN_SEARCH, self::VISIBILITY_IN_CATALOG, self::VISIBILITY_BOTH); + return array(); + } + + /** + * Retrieve Indexes for Flat + * + * @return array + */ + public function getFlatIndexes() + { + return array(); + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return null; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Product/Website.php b/app/code/core/Mage/Catalog/Model/Product/Website.php index 7915c30985..31a3fdc6fc 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Website.php +++ b/app/code/core/Mage/Catalog/Model/Product/Website.php @@ -53,7 +53,11 @@ public function removeProducts($websiteIds, $productIds) Mage::getResourceModel('catalog/category')->refreshProductIndex( array(), $productIds ); - + Mage::dispatchEvent('catalog_product_website_update', array( + 'website_ids' => $websiteIds, + 'product_ids' => $productIds, + 'action' => 'remove' + )); } catch (Exception $e) { Mage::throwException( @@ -70,14 +74,19 @@ public function removeProducts($websiteIds, $productIds) * @param array $productIds * @return Mage_Catalog_Model_Product_Website */ - public function addProducts($websiteIds, $productsIds) + public function addProducts($websiteIds, $productIds) { try { - $this->_getResource()->addProducts($websiteIds, $productsIds); - $this->_refreshRewrites($productsIds); + $this->_getResource()->addProducts($websiteIds, $productIds); + $this->_refreshRewrites($productIds); Mage::getResourceModel('catalog/category')->refreshProductIndex( - array(), $productsIds + array(), $productIds ); + Mage::dispatchEvent('catalog_product_website_update', array( + 'website_ids' => $websiteIds, + 'product_ids' => $productIds, + 'action' => 'add' + )); } catch (Exception $e) { Mage::throwException( diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Attribute.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Attribute.php index f1669593e0..61c7ab2121 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Attribute.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Attribute.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,7 +29,7 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Model_Resource_Eav_Attribute extends Mage_Eav_Model_Entity_Attribute { @@ -37,23 +37,48 @@ class Mage_Catalog_Model_Resource_Eav_Attribute extends Mage_Eav_Model_Entity_At const SCOPE_GLOBAL = 1; const SCOPE_WEBSITE = 2; + /** + * Array with labels + * + * @var array + */ static protected $_labels = null; + /** + * Retrieve attribute is global scope flag + * + * @return bool + */ public function isScopeGlobal() { return $this->getIsGlobal() == self::SCOPE_GLOBAL; } + /** + * Retrieve attribute is website scope website + * + * @return bool + */ public function isScopeWebsite() { return $this->getIsGlobal() == self::SCOPE_WEBSITE; } + /** + * Retrieve attribute is store scope flag + * + * @return bool + */ public function isScopeStore() { return !$this->isScopeGlobal() && !$this->isScopeWebsite(); } + /** + * Retrieve store id + * + * @return int + */ public function getStoreId() { if ($dataObject = $this->getDataObject()) { @@ -62,6 +87,12 @@ public function getStoreId() return $this->getData('store_id'); } + /** + * Retrieve apply to products array + * Return empty array if applied to all products + * + * @return array + */ public function getApplyTo() { if ($this->getData('apply_to')) { @@ -71,6 +102,11 @@ public function getApplyTo() } } + /** + * Retrieve source model + * + * @return Mage_Eav_Model_Entity_Attribute_Source_Abstract + */ public function getSourceModel() { $model = $this->getData('source_model'); @@ -82,27 +118,46 @@ public function getSourceModel() return $model; } + /** + * Check is allow for rule condition + * + * @return bool + */ public function isAllowedForRuleCondition() { $allowedInputTypes = array('text', 'multiselect', 'textarea', 'date', 'datetime', 'select', 'boolean', 'price'); return $this->getIsVisible() && in_array($this->getFrontendInput(), $allowedInputTypes); } + /** + * Retrieve don't translated frontend label + * + * @return string + */ public function getFrontendLabel() { - $label = $this->_getLabelForStore(); - if ($label !== false) { - return $label; - } - return $this->getData('frontend_label'); + return $this->_getData('frontend_label'); } + /** + * Get Attribute translated label for store + * + * @deprecated + * @return string + */ protected function _getLabelForStore() { - self::initLabels(); - return isset(self::$_labels[$this->getData('frontend_label')]) ? self::$_labels[$this->getData('frontend_label')] : false; + return $this->getFrontendLabel(); +// self::initLabels(); +// return isset(self::$_labels[$this->getData('frontend_label')]) ? self::$_labels[$this->getData('frontend_label')] : false; } + /** + * Initialize store Labels for attributes + * + * @deprecated + * @param int $storeId + */ public static function initLabels($storeId = null) { if (is_null(self::$_labels)) { @@ -120,4 +175,14 @@ public static function initLabels($storeId = null) self::$_labels = Mage::app()->getTranslator()->getResource()->getTranslationArrayByStrings($attributeLabels, $storeId); } } + + /** + * Get default attribute source model + * + * @return string + */ + public function _getDefaultSourceModel() + { + return 'eav/entity_attribute_source_table'; + } } diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Abstract.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Abstract.php index ad8214d7bc..b9a7debcb9 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Abstract.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Abstract.php @@ -72,8 +72,19 @@ protected function _isApplicableAttribute ($object, $attribute) */ protected function _getLoadAttributesSelect($object, $table) { + /** + * This condition is applicable for all cases when we was work in not single + * store mode, customize some value per specific store view and than back + * to single store mode. We should load correct values + */ + if (Mage::app()->isSingleStoreMode()) { + $storeId = Mage::app()->getStore(true)->getId(); + } else { + $storeId = $object->getStoreId(); + } + $joinCondition = 'main.attribute_id=default.attribute_id AND ' - . $this->_read->quoteInto('main.store_id=? AND ', $object->getStoreId()) + . $this->_read->quoteInto('main.store_id=? AND ', $storeId) . $this->_read->quoteInto('main.'.$this->getEntityIdField() . '=?', $object->getId()); $select = $this->_read->select() @@ -147,6 +158,20 @@ protected function _insertAttribute($object, $attribute, $value) */ protected function _updateAttribute($object, $attribute, $valueId, $value) { + /** + * If we work in single store mode all values should be saved just + * for default store id + * In this case we clear all not default values + */ + if (Mage::app()->isSingleStoreMode()) { + $this->_getWriteAdapter()->delete( + $attribute->getBackend()->getTable(), + $this->_getWriteAdapter()->quoteInto('attribute_id=?', $attribute->getId()) . + $this->_getWriteAdapter()->quoteInto(' AND entity_id=?', $object->getId()) . + $this->_getWriteAdapter()->quoteInto(' AND store_id!=?', Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) + ); + } + /** * Update attribute value for store */ diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php index 86e9c454d5..1246849527 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category.php @@ -55,6 +55,13 @@ class Mage_Catalog_Model_Resource_Eav_Mysql4_Category extends Mage_Catalog_Model */ protected $_isActiveAttributeId = null; + /** + * Store id + * + * @var int + */ + protected $_storeId = null; + /** * Class constructor */ @@ -69,6 +76,31 @@ public function __construct() $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 * @@ -766,4 +798,164 @@ protected function _updateCategoryPath($category, $path) } 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(); + + $tree->addCollectionData(null, $sorted, $parent, $toLoad, true); + + 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') + ->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('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; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Collection.php index 583e8fcfc3..695eb57375 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Collection.php @@ -34,6 +34,19 @@ */ class Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Collection_Abstract { + /** + * Event prefix + * + * @var string + */ + protected $_eventPrefix = 'catalog_category_collection'; + + /** + * Event object name + * + * @var string + */ + protected $_eventObject = 'category_collection'; protected $_productTable; @@ -103,6 +116,32 @@ public function setLoadProductCount($flag) return $this; } + + /** + * Before collection load + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection + */ + protected function _beforeLoad() + { + Mage::dispatchEvent($this->_eventPrefix . '_load_before', + array($this->_eventObject => $this)); + return parent::_beforeLoad(); + } + + /** + * After collection load + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection + */ + protected function _afterLoad() + { + Mage::dispatchEvent($this->_eventPrefix . '_load_after', + array($this->_eventObject => $this)); + + return parent::_afterLoad(); + } + /** * Set id of the store that we should count products on * @@ -253,4 +292,53 @@ public function joinUrlRewrite() ); return $this; } + + public function addIsActiveFilter() + { + $this->addAttributeToFilter('is_active', 1); + return $this; + } + + public function addNameToResult() + { + $this->addAttributeToSelect('name'); + return $this; + } + + public function addUrlRewriteToResult() + { + $this->joinUrlRewrite(); + return $this; + } + + public function addPathsFilter($paths) + { + if (!is_array($paths)) { + $paths = array($paths); + } + $select = $this->getSelect(); + $orWhere = false; + foreach ($paths as $path) { + if ($orWhere) { + $select->orWhere('e.path LIKE ?', "$path%"); + } else { + $select->where('e.path LIKE ?', "$path%"); + $orWhere = true; + } + } + return $this; + } + + public function addLevelFilter($level) + { + $this->getSelect()->where('e.level <= ?', $level); + return $this; + } + + public function addOrderField($field) + { + $this->setOrder($field, 'ASC'); + return $this; + } + } diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat.php new file mode 100644 index 0000000000..2d8cb30e9b --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat.php @@ -0,0 +1,865 @@ + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat extends Mage_Core_Model_Mysql4_Abstract +{ + protected $_storeId = null; + + protected $_loaded = false; + + protected $_nodes = array(); + + protected $_isRebuilt = null; + + protected function _construct() + { + $this->_init('catalog/category_flat', 'entity_id'); + } + + /** + * Set store id + * + * @param integer $storeId + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + 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; + } + + /** + * Get main table name + * + * @return string + */ + public function getMainTable() + { + return $this->getMainStoreTable($this->getStoreId()); + } + + /** + * Return name of table for given $storeId. + * + * @param integer $storeId + * @return string + */ + public function getMainStoreTable($storeId = 0) + { + $table = parent::getMainTable(); + if (is_string($storeId)) { + $storeId = intval($storeId); + } + if ($this->getUseStoreTables() && $storeId) { + $table .= '_store_'.$storeId; + } + return $table; + } + + /** + * Return true if need use for each store different table of flat categoris data. + * + * @return boolean + */ + public function getUseStoreTables() + { + return true; + } + + /** + * Load nodes by parent id + * + * @param integer $parentId + * @param integer $recursionLevel + * @param integer $storeId + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + protected function _loadNodes($parentNode = null, $recursionLevel = 0, $storeId = 0) + { + $_conn = $this->_getReadAdapter(); + $startLevel = 1; + $parentPath = ''; + if ($parentNode instanceof Mage_Catalog_Model_Category) { + $parentPath = $parentNode->getPath(); + $startLevel = $parentNode->getLevel(); + } elseif (is_numeric($parentNode)) { + $selectParent = $_conn->select() + ->from($this->getMainStoreTable()) + ->where('entity_id = ?', $parentNode) + ->where('store_id = ?', '0'); + if ($parentNode = $_conn->fetchRow($selectParent)) { + $parentPath = $parentNode['path']; + $startLevel = $parentNode['level']; + } + } + $select = $_conn->select() + ->from(array('main_table'=>$this->getMainStoreTable($storeId)), array('main_table.entity_id', 'main_table.name', 'main_table.path', 'main_table.is_active', 'main_table.is_anchor')) + ->joinLeft( + array('url_rewrite'=>$this->getTable('core/url_rewrite')), + 'url_rewrite.category_id=main_table.entity_id AND url_rewrite.is_system=1 AND url_rewrite.product_id IS NULL AND url_rewrite.store_id="'.$storeId.'" AND url_rewrite.id_path LIKE "category/%"', + array('request_path' => 'url_rewrite.request_path')) + ->where('main_table.is_active = ?', '1') +// ->order('main_table.path', 'ASC') + ->order('main_table.position', 'ASC'); + + + + if ($parentPath) { + $select->where($_conn->quoteInto("main_table.path like ?", "$parentPath/%")); + } + if ($recursionLevel != 0) { + $select->where("main_table.level <= ?", $startLevel + $recursionLevel); + } + + $arrNodes = $_conn->fetchAll($select); + $nodes = array(); + foreach ($arrNodes as $node) { + $node['id'] = $node['entity_id']; + $nodes[$node['id']] = Mage::getModel('catalog/category')->setData($node); + } + + Mage::dispatchEvent('catalog_category_flat_load_nodes_after', array('nodes'=>$nodes)); + return $nodes; + } + + /** + * Creating sorted array of nodes + * + * @param array $children + * @param string $path + * @param Varien_Object $parent + */ + public function addChildNodes($children, $path, $parent) + { + if (isset($children[$path])) { + foreach ($children[$path] as $child) { + $childrenNodes = $parent->getChildrenNodes(); + if ($childrenNodes && isset($childrenNodes[$child->getId()])) { + $childrenNodes[$child['entity_id']]->setChildrenNodes(array($child->getId()=>$child)); + } else { + if ($childrenNodes) { + $childrenNodes[$child->getId()] = $child; + } else { + $childrenNodes = array($child->getId()=>$child); + } + $parent->setChildrenNodes($childrenNodes); + } + + if ($path) { + $childrenPath = explode('/', $path); + } else { + $childrenPath = array(); + } + $childrenPath[] = $child->getId(); + $childrenPath = implode('/', $childrenPath); + $this->addChildNodes($children, $childrenPath, $child); + } + } + } + + /** + * Return sorted array of nodes + * + * @param integer|null $parentId + * @param integer $recursionLevel + * @param integer $storeId + * @return array + */ + public function getNodes($parentId, $recursionLevel = 0, $storeId = 0) + { + if (!$this->_loaded) { + $selectParent = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable()) + ->where('entity_id = ?', $parentId); + if ($parentNode = $this->_getReadAdapter()->fetchRow($selectParent)) { + $parentNode['id'] = $parentNode['entity_id']; + $parentNode = Mage::getModel('catalog/category')->setData($parentNode); + $this->_nodes[$parentNode->getId()] = $parentNode; + $nodes = $this->_loadNodes($parentNode, $recursionLevel, $storeId); + $childrenItems = array(); + foreach ($nodes as $node) { + $pathToParent = explode('/', $node->getPath()); + array_pop($pathToParent); + $pathToParent = implode('/', $pathToParent); + $childrenItems[$pathToParent][] = $node; + } + $this->addChildNodes($childrenItems, $parentNode->getPath(), $parentNode); + $childrenNodes = $this->_nodes[$parentNode->getId()]; + if ($childrenNodes->getChildrenNodes()) { + $this->_nodes = $childrenNodes->getChildrenNodes(); + } + else { + $this->_nodes = array(); + } + $this->_loaded = true; + } + } + return $this->_nodes; + } + + /** + * Return array or collection of categories + * + * @param integer $parent + * @param integer $recursionLevel + * @param boolean|string $sorted + * @param boolean $asCollection + * @param boolean $toLoad + * @return array|Varien_Data_Collection + */ + public function getCategories($parent, $recursionLevel = 0, $sorted=false, $asCollection=false, $toLoad=true) + { + if ($asCollection) { + $parentPath = $this->_getReadAdapter()->fetchOne(new Zend_Db_Expr(" + SELECT path FROM {$this->getMainStoreTable()} WHERE entity_id = {$parent} + ")); + $collection = Mage::getModel('catalog/category')->getCollection() + ->addNameToResult() + ->addUrlRewriteToResult() + ->addParentPathFilter($parentPath) + ->addStoreFilter() + ->addSortedField($sorted); + if ($toLoad) { + return $collection->load(); + } + return $collection; + } + return $this->getNodes($parent, $recursionLevel, Mage::app()->getStore()->getId()); + } + + /** + * Return node with id $nodeId + * + * @param integer $nodeId + * @param array $nodes + * @return Varien_Object + */ + public function getNodeById($nodeId, $nodes = null) + { + if (is_null($nodes)) { + $nodes = $this->getNodes(); + } + if (isset($nodes[$nodeId])) { + return $nodes[$nodeId]; + } + foreach ($nodes as $node) { +// if ($node->getId() == $nodeId) { +// return $node; +// } + if ($node->getChildrenNodes()) { + return $this->getNodeById($nodeId, $node->getChildrenNodes()); + } + } + return array(); + } + + /** + * Check if category flat data is rebuilt + * + * @return bool + */ + public function isRebuilt() + { + if ($this->_isRebuilt === null) { + $select = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable($this->getStoreId()), 'entity_id') + ->limit(1); + try { + $this->_isRebuilt = (bool) $this->_getReadAdapter()->fetchOne($select); + } catch (Exception $e) { + $this->_isRebuilt = false; + } + } + return $this->_isRebuilt; + } + + protected function _getTableSqlSchema($storeId = 0) + { + $storeId = Mage::app()->getStore($storeId)->getId(); + $schema = "CREATE TABLE `{$this->getMainStoreTable($storeId)}` ( + `entity_id` int(10) unsigned not null, + `store_id` smallint(5) unsigned not null default '0', + `parent_id` int(10) unsigned not null default '0', + `path` varchar(255) not null default '', + `level` int(11) not null default '0', + `position` int(11) not null default '0', + `children_count` int(11) not null, + `created_at` datetime not null default '0000-00-00 00:00:00', + `updated_at` datetime not null default '0000-00-00 00:00:00', + KEY `CATEGORY_FLAT_CATEGORY_ID` (`entity_id`), + KEY `CATEGORY_FLAT_STORE_ID` (`store_id`), + KEY `path` (`path`), + KEY `IDX_LEVEL` (`level`), + CONSTRAINT `FK_CATEGORY_FLAT_CATEGORY_ID_STORE_{$storeId}` FOREIGN KEY (`entity_id`) + REFERENCES `{$this->getTable('catalog/category')}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_CATEGORY_FLAT_STORE_ID_STORE_{$storeId}` FOREIGN KEY (`store_id`) + REFERENCES `{$this->getTable('core/store')}` (`store_id`) ON DELETE CASCADE ON UPDATE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8"; + return $schema; + } + + /** + * Rebuild flat data from eav + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + public function rebuild() + { + $_read = $this->_getReadAdapter(); + if ($this->getUseStoreTables()) { + $stores = array(); + $selectStores = $_read->select() + ->from($this->getTable('core/store'), 'store_id'); + $stores = array(); + foreach ($_read->fetchAll($selectStores) as $store) { + $stores[] = $store['store_id']; + } + $this->_createTable($stores); + } else { + $this->_createTable(0); + } + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('catalog/category'), 'entity_id'); + $_categories = $this->_getReadAdapter()->fetchAll($select); + foreach ($_categories as $_category) { + foreach ($stores as $store) { + $_tmpCategory = Mage::getModel('catalog/category') + ->setStoreId($store) + ->load($_category['entity_id']); + if ($_tmpCategory->getId()) { + $this->_synchronize($_tmpCategory, 'insert'); + } + } + } + $_tmpCategory = null; + return $this; + } + + /** + * Creating table and adding attributes as fields to table + * + * @param array|integer $stores + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + protected function _createTable($stores) + { + if (!is_array($stores)) { + $stores = (int) $stores; + } + $_read = $this->_getReadAdapter(); + $_write = $this->_getWriteAdapter(); + if ($this->getUseStoreTables() && is_array($stores)) { + foreach ($stores as $store) { + $_read->query("DROP TABLE IF EXISTS `{$this->getMainStoreTable($store)}`"); + $_read->query($this->_getTableSqlSchema($store)); + } + } else { + $_read->query("DROP TABLE IF EXISTS `{$this->getMainStoreTable($stores)}`"); + $_read->query($this->_getTableSqlSchema($stores)); + } + $selectAttribute = $_read->select() + ->from($this->getTable('eav/entity_type'), array()) + ->join( + $this->getTable('eav/attribute'), + $this->getTable('eav/attribute').'.entity_type_id = '.$this->getTable('eav/entity_type').'.entity_type_id', + $this->getTable('eav/attribute').'.*' + ) + ->where($this->getTable('eav/entity_type').'.entity_type_code=?', 'catalog_category'); + $resultAttribute = $_read->fetchAll($selectAttribute); + foreach ($resultAttribute as $attribute) { + $type = ''; + switch ($attribute['backend_type']) { + case 'varchar': + $type = 'varchar(255) not null default \'\''; + break; + case 'int': + $type = 'int(10) not null default \'0\''; + break; + case 'text': + $type = 'text'; + break; + case 'datetime': + $type = 'datetime not null default \'0000-00-00 00:00:00\''; + break; + case 'decimal': + $type = 'decimal(10,2) not null default \'0.00\''; + break; + } + if ($type) { + if ($this->getUseStoreTables() && is_array($stores)) { + foreach ($stores as $store) { + $_write->addColumn($this->getMainStoreTable($store), $attribute['attribute_code'], $type); + } + } else { + $_write->addColumn($this->getMainStoreTable($stores), $attribute['attribute_code'], $type); + } + } + } + return $this; + } + + /** + * Synchronize flat data with eav model. + * + * @param Mage_Catalog_Model_Category $category + * @param null|string $action + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + protected function _synchronize($category, $action = null) + { + if (is_null($action)) { + $select = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable($category->getStoreId()), 'entity_id') + ->where('entity_id = ?', $category->getId()); + if ($result = $this->_getReadAdapter()->fetchOne($select)) { + $action = 'update'; + } else { + $action = 'insert'; + } + } + + if ($action == 'update') { + // update + $this->_getWriteAdapter()->update( + $this->getMainStoreTable($category->getStoreId()), + $this->_prepareDataForAllFields($category), + $this->_getReadAdapter()->quoteInto('entity_id = ?', $category->getId()) + ); + } elseif ($action == 'insert') { + // insert + $this->_getWriteAdapter()->insert( + $this->getMainStoreTable($category->getStoreId()), + $this->_prepareDataForAllFields($category) + ); + } + return $this; + } + + /** + * Synchronize flat data with eav model when category was moved. + * + * @param string $prevParentPath + * @param string $parentPath + * @param array $storeIds + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + protected function _move($prevParentPath, $parentPath) + { + $_staticFields = array( + 'parent_id', + 'path', + 'level', + 'position', + 'children_count', + 'updated_at' + ); + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('core/store'), 'store_id'); + $stores = $this->_getReadAdapter()->fetchAll($select); + foreach ($stores as $store) { + $update = "UPDATE {$this->getMainStoreTable($store['store_id'])}, {$this->getTable('catalog/category')} SET"; + foreach ($_staticFields as $field) { + $update .= " {$this->getMainStoreTable($store['store_id'])}.".$field."={$this->getTable('catalog/category')}.".$field.","; + } + $update = substr($update, 0, -1); + $update .= " WHERE {$this->getMainStoreTable($store['store_id'])}.entity_id = {$this->getTable('catalog/category')}.entity_id AND " . + "({$this->getTable('catalog/category')}.path like '$parentPath/%' OR " . + "{$this->getTable('catalog/category')}.path like '$prevParentPath/%')"; + $this->_getWriteAdapter()->query($update); + } + return $this; + } + + /** + * Synchronize flat data with eav model. + * + * @param Mage_Catalog_Model_Category|array $category + * @param array $storeIds + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + public function synchronize($category = null, $storeIds = array()) + { + if (is_null($category)) { + $storesCondition = ''; + if (!empty($storeIds)) { + $storesCondition = $this->_getReadAdapter()->quoteInto( + ' AND s.store_id IN (?)', $storeIds + ); + } + $stores = $this->_getReadAdapter()->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} + "); + foreach ($stores as $store) { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('catalog/category'), 'entity_id') + ->where('path LIKE ?', "{$store['root_path']}/%") + ->orWhere('path = ?', $store['root_path']); + $_categories = $this->_getReadAdapter()->fetchAll($select); + if (!$this->_getReadAdapter()->showTableStatus($this->getMainStoreTable($store['store_id']))) { + $this->_createTable($store['store_id']); + } + $this->_getWriteAdapter()->delete( + $this->getMainStoreTable($store['store_id']), + $this->_getReadAdapter()->quoteInto('store_id = ?', $store['store_id']) + ); + foreach ($_categories as $_category) { + $_tmpCategory = Mage::getModel('catalog/category') + ->setStoreId($store['store_id']) + ->load($_category['entity_id']); + $this->_synchronize($_tmpCategory, 'insert'); + } + } + $_tmpCategory = null; + } elseif ($category instanceof Mage_Catalog_Model_Category) { + foreach ($category->getStoreIds() as $storeId) { + $_tmpCategory = Mage::getModel('catalog/category') + ->setStoreId($storeId) + ->load($category->getId()); + $_tmpCategory->setStoreId($storeId); + $this->_synchronize($_tmpCategory); + } + $_tmpCategory = null; + } + return $this; + } + + /** + * Synchronize flat data with eav after moving category + * + * @param integer $categoryId + * @param integer $prevParentId + * @param integer $parentId + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat + */ + public function move($categoryId, $prevParentId, $parentId) + { + $_staticFields = array( + 'parent_id', + 'path', + 'level', + 'position', + 'children_count', + 'updated_at' + ); + $prevParent = Mage::getModel('catalog/category')->load($prevParentId); + $parent = Mage::getModel('catalog/category')->load($parentId); + if ($prevParent->getStore()->getWebsiteId() != $parent->getStore()->getWebsiteId()) { + foreach ($prevParent->getStoreIds() as $storeId) { + $this->_getWriteAdapter()->delete( + $this->getMainStoreTable($storeId), + $this->_getReadAdapter()->quoteInto('entity_id = ?', $categoryId) + ); + } + $categoryPath = $this->_getReadAdapter()->fetchOne(" + SELECT + path + FROM + {$this->getTable('catalog/category')} + WHERE + entity_id = '$categoryId' + "); + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('catalog/category'), 'entity_id') + ->where('path LIKE ?', "$categoryPath/%") + ->orWhere('path = ?', $categoryPath); + $_categories = $this->_getReadAdapter()->fetchAll($select); + foreach ($_categories as $_category) { + foreach ($parent->getStoreIds() as $storeId) { + $_tmpCategory = Mage::getModel('catalog/category') + ->setStoreId($storeId) + ->load($_category['entity_id']); + $this->_synchronize($_tmpCategory); + } + } + } else { + foreach ($parent->getStoreIds() as $store) { + $update = "UPDATE {$this->getMainStoreTable($store)}, {$this->getTable('catalog/category')} SET"; + foreach ($_staticFields as $field) { + $update .= " {$this->getMainStoreTable($store)}.".$field."={$this->getTable('catalog/category')}.".$field.","; + } + $update = substr($update, 0, -1); + $update .= " WHERE {$this->getMainStoreTable($store)}.entity_id = {$this->getTable('catalog/category')}.entity_id AND " . + "({$this->getTable('catalog/category')}.path like '{$parent->getPath()}/%' OR " . + "{$this->getTable('catalog/category')}.path like '{$prevParent->getPath()}/%')"; + $this->_getWriteAdapter()->query($update); + } + } + $prevParent = null; + $parent = null; + $_tmpCategory = null; +// $this->_move($categoryId, $prevParentPath, $parentPath); + return $this; + } + + /** + * Prepare array of category data to insert or update. + * + * array( + * 'field_name' => 'value' + * ) + * + * @param Mage_Catalog_Model_Category $category + * @param array $replaceFields + * @return array + */ + protected function _prepareDataForAllFields($category, $replaceFields = array()) + { + $table = $this->_getReadAdapter()->describeTable($this->getMainStoreTable($category->getStoreId())); + $data = array(); + foreach ($table as $column=>$columnData) { + if (null !== $category->getData($column)) { + if (key_exists($column, $replaceFields)) { + $value = $category->getData($replaceFields[$column]); + } else { + $value = $category->getData($column); + } + if (is_array($value)) { + $value = implode(',', $value); + } + $data[$column] = $value; + } + } + return $data; + } + + /** + * Get count of active/not active children categories + * + * @param Mage_Catalog_Model_Category $category + * @param bool $isActiveFlag + * @return integer + */ + public function getChildrenAmount($category, $isActiveFlag = true) + { + $_table = $this->getMainStoreTable($category->getStoreId()); + $select = $this->_getReadAdapter()->select() + ->from($_table, "COUNT({$_table}.entity_id)") + ->where("{$_table}.path LIKE ?", $category->getPath() . '/%') + ->where("{$_table}.is_active = ?", (int) $isActiveFlag); + return (int) $this->_getReadAdapter()->fetchOne($select); + } + + /** + * Get products count in category + * + * @param Mage_Catalog_Model_Category $category + * @return integer + */ + public function getProductCount($category) + { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('catalog/category_product'), "COUNT({$this->getTable('catalog/category_product')}.product_id)") + ->where("{$this->getTable('catalog/category_product')}.category_id = ?", $category->getId()) + ->group("{$this->getTable('catalog/category_product')}.category_id"); + return (int) $this->_getReadAdapter()->fetchOne($select); + } + + /** + * Return parent categories of category + * + * @param Mage_Catalog_Model_Category $category + * @return array + */ + public function getParentCategories($category, $isActive = true) + { + $categories = array(); + $select = $this->_getReadAdapter()->select() + ->from(array('main_table' => $this->getMainStoreTable($category->getStoreId())), array('main_table.entity_id', 'main_table.name')) + ->joinLeft( + array('url_rewrite'=>$this->getTable('core/url_rewrite')), + 'url_rewrite.category_id=main_table.entity_id AND url_rewrite.is_system=1 AND url_rewrite.product_id IS NULL AND url_rewrite.store_id="'.$category->getStoreId().'" AND url_rewrite.id_path LIKE "category/%"', + array('request_path' => 'url_rewrite.request_path')) + ->where('main_table.entity_id IN (?)', array_reverse(explode(',', $category->getPathInStore()))); + if ($isActive) { + $select->where('main_table.is_active = ?', '1'); + } + $select->order('main_table.path ASC'); + $result = $this->_getReadAdapter()->fetchAll($select); + foreach ($result as $row) { + $row['id'] = $row['entity_id']; + $categories[$row['entity_id']] = Mage::getModel('catalog/category')->setData($row); + } + return $categories; + } + + /** + * Return children categories of category + * + * @param Mage_Catalog_Model_Category $category + * @return array + */ + public function getChildrenCategories($category) + { +// $node = $this->getNodeById($category->getId()); +// if ($node && $node->getChildrenNodes()) { +// return $node->getChildrenNodes(); +// } + $categories = $this->_loadNodes($category, 1, $category->getStoreId()); + return $categories; + } + + /** + * 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->getMainStoreTable($category->getStoreId()), new Zend_Db_Expr("CONCAT(path, '/%')")) + ->where('entity_id = ?', Mage::app()->getStore()->getRootCategoryId()); + $select = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable($category->getStoreId()), 'entity_id') + ->where('entity_id = ?', $category->getId()) + ->where(new Zend_Db_Expr("path LIKE ({$innerSelect->__toString()})")); + return (bool) $this->_getReadAdapter()->fetchOne($select); + } + + /** + * Return children ids of category + * + * @param Mage_Catalog_Model_Category $category + * @param integer $level + * @return array + */ + public function getChildren($category, $recursive = true, $isActive = true) + { + $select = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable($category->getStoreId()), 'entity_id') + ->where('path LIKE ?', "{$category->getPath()}/%"); + if (!$recursive) { + $select->where('level <= ?', $category->getLevel() + 1); + } + if ($isActive) { + $select->where('is_active = ?', '1'); + } + $_categories = $this->_getReadAdapter()->fetchAll($select); + $categoriesIds = array(); + foreach ($_categories as $_category) { + $categoriesIds[] = $_category['entity_id']; + } + return $categoriesIds; + } + + /** + * Return all children ids of category (with category id) + * + * @param Mage_Catalog_Model_Category $category + * @return array + */ + public function getAllChildren($category) + { + $categoriesIds = $this->getChildren($category); + $myId = array($category->getId()); + $categoriesIds = array_merge($myId, $categoriesIds); + + return $categoriesIds; + } + +/** + * Check if category id exist + * + * @param int $id + * @return bool + */ + public function checkId($id) + { + $select = $this->_getReadAdapter()->select() + ->from($this->getMainStoreTable(), 'entity_id') + ->where('entity_id=?', $id); + return $this->_getReadAdapter()->fetchOne($select); + } + + /** + * Get design update data of parent categories + * + * @param Mage_Catalog_Model_Category $category + * @return array + */ + public function getDesignUpdateData($category) + { + $categories = array(); + $pathIds = array(); + foreach (array_reverse($category->getParentIds()) as $pathId) { + if ($pathId == Mage::app()->getStore()->getRootCategoryId()) { + $pathIds[] = $pathId; + break; + } + $pathIds[] = $pathId; + } + $select = $this->_getReadAdapter()->select() + ->from( + array('main_table' => $this->getMainStoreTable($category->getStoreId())), + array( + 'main_table.entity_id', + 'main_table.custom_design', + 'main_table.custom_design_apply', + 'main_table.custom_design_from', + 'main_table.custom_design_to', + ) + ) + ->where('main_table.entity_id IN (?)', $pathIds) + ->where('main_table.is_active = ?', '1') + ->order('main_table.path DESC'); + $result = $this->_getReadAdapter()->fetchAll($select); + foreach ($result as $row) { + $row['id'] = $row['entity_id']; + $categories[$row['entity_id']] = Mage::getModel('catalog/category')->setData($row); + } + return $categories; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat/Collection.php new file mode 100644 index 0000000000..ea95deaa23 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Category/Flat/Collection.php @@ -0,0 +1,285 @@ + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract +{ + /** + * Event prefix + * + * @var string + */ + protected $_eventPrefix = 'catalog_category_collection'; + + /** + * Event object name + * + * @var string + */ + protected $_eventObject = 'category_collection'; + + + /** + * Store id of application + * + * @var integer + */ + protected $_storeId = null; + + protected function _construct() + { + $this->_init('catalog/category_flat'); + $this->setModel('catalog/category'); + } + + protected function _initSelect() + { + $this->getSelect()->from( + array('main_table' => $this->getResource()->getMainStoreTable($this->getStoreId())), + array('entity_id', 'level', 'path', 'position', 'is_active', 'is_anchor') + ); + return $this; + } + + /** + * Add filter by entity id(s). + * + * @param mixed $categoryIds + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function addIdFilter($categoryIds) + { + if (is_array($categoryIds)) { + if (empty($categoryIds)) { + $condition = ''; + } else { + $condition = array('in' => $categoryIds); + } + } elseif (is_numeric($categoryIds)) { + $condition = $categoryIds; + } elseif (is_string($categoryIds)) { + $ids = explode(',', $categoryIds); + if (empty($ids)) { + $condition = $categoryIds; + } else { + $condition = array('in' => $ids); + } + } + $this->addFieldToFilter('entity_id', $condition); + return $this; + } + + /** + * Before collection load + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + protected function _beforeLoad() + { + Mage::dispatchEvent($this->_eventPrefix . '_load_before', + array($this->_eventObject => $this)); + return parent::_beforeLoad(); + } + + /** + * After collection load + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + protected function _afterLoad() + { + Mage::dispatchEvent($this->_eventPrefix . '_load_after', + array($this->_eventObject => $this)); + + return parent::_afterLoad(); + } + + + /** + * Set store id + * + * @param integer $storeId + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function setStoreId($storeId) + { + $this->_storeId = $storeId; + return $this; + } + + /** + * Return store id. + * If store id is not set yet, return store of application + * + * @return integer + */ + public function getStoreId() + { + if (is_null($this->_storeId)) { + return Mage::app()->getStore()->getId(); + } + return $this->_storeId; + } + + /** + * Add filter by path to collection + * + * @param string $parent + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function addParentPathFilter($parent) + { + $this->addFieldToFilter('path', array('like' => "{$parent}/%")); + return $this; + } + + /** + * Add store filter + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function addStoreFilter() + { + $this->addFieldToFilter('main_table.store_id', $this->getStoreId()); + return $this; + } + + /** + * Set field to sort by + * + * @param string $sorted + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function addSortedField($sorted) + { + if (is_string($sorted)) { + $this->addOrder($sorted, 'ASC'); + } else { + $this->addOrder('name', 'ASC'); + } + return $this; + } + + public function addIsActiveFilter() + { + $this->addFieldToFilter('is_active', 1); + return $this; + } + + public function addNameToResult() + { + $this->addAttributeToSelect('name'); + return $this; + } + + /** + * Add attribute to select + * + * @param array|string $attribute + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Flat_Collection + */ + public function addAttributeToSelect($attribute = '*') + { + if ($attribute == '*') { + // Save previous selected columns + $columns = $this->getSelect()->getPart(Zend_Db_Select::COLUMNS); + $this->getSelect()->reset(Zend_Db_Select::COLUMNS); + foreach ($columns as $column) { + if ($column[0] == 'main_table') { + // If column selected from main table, + // no need to select it again + continue; + } + + // Joined columns + if ($column[2] !== null) { + $expression = array($column[2] => $column[1]); + } else { + $expression = $column[2]; + } + $this->getSelect()->columns($expression, $column[0]); + } + + $this->getSelect()->columns('*', 'main_table'); + return $this; + } + + if (!is_array($attribute)) { + $attribute = array($attribute); + } + + $this->getSelect()->columns($attribute, 'main_table'); + return $this; + } + + public function addUrlRewriteToResult() + { + $storeId = Mage::app()->getStore()->getId(); + $this->getSelect()->joinLeft( + array('url_rewrite' => $this->getTable('core/url_rewrite')), + 'url_rewrite.category_id=main_table.entity_id AND url_rewrite.is_system=1 AND url_rewrite.product_id IS NULL AND url_rewrite.store_id="'.$storeId.'" AND url_rewrite.id_path LIKE "category/%"', + array('request_path') + ); + return $this; + } + + public function addPathsFilter($paths) + { + if (!is_array($paths)) { + $paths = array($paths); + } + $select = $this->getSelect(); + $orWhere = false; + foreach ($paths as $path) { + if ($orWhere) { + $select->orWhere('main_table.path LIKE ?', "$path%"); + } else { + $select->where('main_table.path LIKE ?', "$path%"); + $orWhere = true; + } + } + return $this; + } + + public function addLevelFilter($level) + { + $this->getSelect()->where('main_table.level <= ?', $level); + return $this; + } + + public function addOrderField($field) + { + $this->setOrder('main_table.' . $field, 'ASC'); + return $this; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Collection/Abstract.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Collection/Abstract.php index 599fb5eedc..db0b5c6b09 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Collection/Abstract.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Collection/Abstract.php @@ -71,8 +71,11 @@ public function getDefaultStoreId() * @param string $table * @return Mage_Eav_Model_Entity_Collection_Abstract */ - protected function _getLoadAttributesSelect($table) + protected function _getLoadAttributesSelect($table, $attributeIds = array()) { + if (empty($attributeIds)) { + $attributeIds = $this->_selectAttributes; + } if ((int) $this->getStoreId()) { $entityIdField = $this->getEntity()->getEntityIdField(); $joinCondition = 'store.attribute_id=default.attribute_id @@ -91,7 +94,7 @@ protected function _getLoadAttributesSelect($table) ) ->where('default.entity_type_id=?', $this->getEntity()->getTypeId()) ->where("default.$entityIdField in (?)", array_keys($this->_itemsById)) - ->where('default.attribute_id in (?)', $this->_selectAttributes) + ->where('default.attribute_id in (?)', $attributeIds) ->where('default.store_id = 0'); } else { @@ -174,4 +177,4 @@ protected function _joinAttributeToSelect($method, $attribute, $tableAlias, $con $condition[] = $this->getConnection()->quoteInto("$tableAlias.store_id=?", $store_id); return parent::_joinAttributeToSelect($method, $attribute, $tableAlias, $condition, $fieldCode, $fieldAlias); } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Config.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Config.php new file mode 100644 index 0000000000..d4e3151fd2 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Config.php @@ -0,0 +1,94 @@ + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Config extends Mage_Core_Model_Mysql4_Abstract +{ + /** + * catalog_product entity type id + * + * @var int + */ + protected $_entityTypeId; + + /** + * Initialize connection + * + */ + protected function _construct() { + $this->_init('eav/attribute', 'attribute_id'); + } + + /** + * Retrieve catalog_product entity type id + * + * @return int + */ + public function getEntityTypeId() + { + if (is_null($this->_entityTypeId)) { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('eav/entity_type'), 'entity_type_id') + ->where('entity_type_code=?', 'catalog_product'); + $this->_entityTypeId = $this->_getReadAdapter()->fetchOne($select); + } + return $this->_entityTypeId; + } + + /** + * Retrieve Product Attributes Used in Catalog Product listing + * + * @return array + */ + public function getAttributesUsedInListing() { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('eav/attribute')) + ->where('entity_type_id=?', $this->getEntityTypeId()) + ->where('used_in_product_listing=?', 1); + return $this->_getReadAdapter()->fetchAll($select); + } + + /** + * Retrieve Used Product Attributes for Catalog Product Listing Sort By + * + * @return array + */ + public function getAttributesUsedForSortBy() { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('eav/attribute')) + ->where('entity_type_id=?', $this->getEntityTypeId()) + ->where('used_for_sort_by=?', 1); + return $this->_getReadAdapter()->fetchAll($select); + } + +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php index c66316d0a2..15b68e7aaf 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php @@ -42,7 +42,6 @@ class Mage_Catalog_Model_Resource_Eav_Mysql4_Product extends Mage_Catalog_Model_ public function __construct() { parent::__construct(); - Mage::getSingleton('eav/config')->preloadAttributes('catalog_product', $this->_getDefaultAttributes()); $resource = Mage::getSingleton('core/resource'); $this->setType('catalog_product') ->setConnection( @@ -256,11 +255,6 @@ public function refreshIndex($product) ->where('entity_id IN (?)', $categoryIds); $categoriesInfo = $this->_getWriteAdapter()->fetchAll($categoriesSelect); - // get categories positions (bug #6940) - $select = $this->_getWriteAdapter()->select() - ->from($this->getTable('catalog/category_product'), array('category_id', 'position')) - ->where('product_id=' . $product->getId()); - $categoriesPositions = $this->_getWriteAdapter()->fetchPairs($select); $indexCategoryIds = array(); foreach ($categoriesInfo as $categoryInfo) { @@ -481,4 +475,4 @@ public function getParentProductIds($object) $configurableIds = $this->_getReadAdapter()->fetchCol($configurableSelect); return array_merge($groupedIds, $configurableIds); } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php index 6a9d2e8b62..5c0d483836 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php @@ -34,40 +34,201 @@ class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Collection_Abstract { + /** + * Catalog Product Flat is enabled cache per store + * + * @var array + */ + protected $_flatEnabled = array(); + + /** + * Product websites table name + * + * @var string + */ protected $_productWebsiteTable; + + /** + * Product categories table name + * + * @var string + */ protected $_productCategoryTable; + + /** + * Is add URL rewrites to collection flag + * + * @var bool + */ protected $_addUrlRewrite = false; + + /** + * Add URL rewrite for category + * + * @var int + */ protected $_urlRewriteCategory = ''; + + /** + * Is add minimal price to product collection flag + * + * @var bool + */ protected $_addMinimalPrice = false; + + /** + * Is add final price to product collection flag + * + * @var unknown_type + */ protected $_addFinalPrice = false; + + /** + * Cache for all ids + * + * @var array + */ protected $_allIdsCache = null; + + /** + * Is add tax percents to product collection flag + * + * @var bool + */ protected $_addTaxPercents = false; + + /** + * Category index is a joined flag + * + * @var bool + */ protected $_categoryIndexJoined = false; - public function __construct($resource=null) + /** + * Category product count select + * + * @var Zend_Db_Select + */ + protected $_productCountSelect = null; + + /** + * Retrieve Catalog Product Flat Helper object + * + * @return Mage_Catalog_Helper_Product_Flat + */ + public function getFlatHelper() { - /** - * Preload attributes for EAV optimization - */ - $attributes = Mage::getSingleton('catalog/config')->getProductAttributes(); - $attributes = array_merge($attributes, array( - 'tax_class_id', 'tier_price' - )); + return Mage::helper('catalog/product_flat'); + } - Mage::getSingleton('eav/config')->preloadAttributes('catalog_product', $attributes); - parent::__construct($resource); + /** + * Retrieve is flat enabled flag + * Return alvays false if magento run admin + * + * @return bool + */ + public function isEnabledFlat() + { + if (Mage::app()->getStore()->isAdmin()) { + return false; + } + if (!isset($this->_flatEnabled[$this->getStoreId()])) { + $this->_flatEnabled[$this->getStoreId()] = $this->getFlatHelper() + ->isEnabled($this->getStoreId()); + } + return $this->_flatEnabled[$this->getStoreId()]; } /** * Initialize resources + * */ protected function _construct() { - $this->_init('catalog/product'); + if ($this->isEnabledFlat()) { + $this->_init('catalog/product', 'catalog/product_flat'); + } + else { + $this->_init('catalog/product'); + } + $this->_productWebsiteTable = $this->getResource()->getTable('catalog/product_website'); $this->_productCategoryTable= $this->getResource()->getTable('catalog/category_product'); } + /** + * Standard resource collection initalization + * + * @param string $model + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + protected function _init($model, $entityModel=null) + { + if ($this->isEnabledFlat()) { + $entityModel = 'catalog/product_flat'; + } + + return parent::_init($model, $entityModel); + } + + /** + * Prepare static entity fields + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + protected function _prepareStaticFields() + { + if ($this->isEnabledFlat()) { + return $this; + } + return parent::_prepareStaticFields(); + } + + /** + * Retrieve collection empty item + * Redeclared for specifying id field name without getting resource model inside model + * + * @return Varien_Object + */ + public function getNewEmptyItem() + { + $object = parent::getNewEmptyItem(); + if ($this->isEnabledFlat()) { + $object->setIdFieldName($this->getEntity()->getIdFieldName()); + } + return $object; + } + + /** + * Set entity to use for attributes + * + * @param Mage_Eav_Model_Entity_Abstract $entity + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function setEntity($entity) + { + if ($this->isEnabledFlat() && ($entity instanceof Mage_Core_Model_Mysql4_Abstract)) { + $this->_entity = $entity; + return $this; + } + return parent::setEntity($entity); + } + + /** + * Set Store scope for collection + * + * @param mixed $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function setStore($store) + { + parent::setStore($store); + if ($this->isEnabledFlat()) { + $this->getEntity()->setStoreId($this->getStoreId()); + } + return $this; + } + /** * Initialize collection select * Redeclared for remove entity_type_id condition @@ -77,10 +238,34 @@ protected function _construct() */ protected function _initSelect() { - $this->getSelect()->from(array('e'=>$this->getEntity()->getEntityTable())); + if ($this->isEnabledFlat()) { + $this->getSelect() + ->from(array('e' => $this->getEntity()->getFlatTableName()), null) + ->where('e.is_child=?', 0) + ->from(null, array('status' => new Zend_Db_Expr(Mage_Catalog_Model_Product_Status::STATUS_ENABLED))); + $this->addAttributeToSelect(array('entity_id', 'type_id', 'child_id', 'is_child', 'attribute_set_id')); + } + else { + $this->getSelect()->from(array('e'=>$this->getEntity()->getEntityTable())); + } return $this; } + /** + * Load attributes into loaded entities + * + * @param bool $printQuery + * @param bool $logQuery + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function _loadAttributes($printQuery = false, $logQuery = false) + { + if ($this->isEnabledFlat()) { + return $this; + } + return parent::_loadAttributes($printQuery, $logQuery); + } + /** * Add attribute to entities in collection * @@ -89,10 +274,31 @@ protected function _initSelect() * @param array|string|integer|Mage_Core_Model_Config_Element $attribute * @return Mage_Eav_Model_Entity_Collection_Abstract */ - public function addAttributeToSelect($attribute, $joinType=false) + public function addAttributeToSelect($attribute, $joinType = false) { - if (is_array($attribute)) { - Mage::getSingleton('eav/config')->preloadAttributes('catalog_product', $attribute); + if ($this->isEnabledFlat()) { + if (!is_array($attribute)) { + $attribute = array($attribute); + } + foreach ($attribute as $attributeCode) { + if ($attributeCode == '*') { + foreach ($this->getEntity()->getAllTableColumns() as $column) { + $this->getSelect()->from(null, 'e.'.$column); + $this->_selectAttributes[$column] = $column; + $this->_staticFields[$column] = $column; + } + } + else { + if ($columns = $this->getEntity()->getAttributeForSelect($attributeCode)) { + foreach ($columns as $alias => $column) { + $this->getSelect()->from(null, array($alias => 'e.'.$column)); + $this->_selectAttributes[$column] = $column; + $this->_staticFields[$column] = $column; + } + } + } + } + return $this; } return parent::addAttributeToSelect($attribute, $joinType); } @@ -107,8 +313,7 @@ protected function _beforeLoad() if ($this->_addFinalPrice) { $this->_joinPriceRules(); } - $this->addAttributeToSelect('tax_class_id'); - + Mage::dispatchEvent('catalog_product_collection_load_before', array('collection'=>$this)); return parent::_beforeLoad(); } @@ -129,10 +334,6 @@ protected function _afterLoad() if ($this->_addFinalPrice) { $this->_addFinalPrice(); } - if ($this->_addTaxPercents) { - $this->_addTaxPercents(); - } - if (count($this)>0) { Mage::dispatchEvent('catalog_product_collection_load_after', array('collection'=>$this)); } @@ -226,20 +427,38 @@ public function addStoreFilter($store=null) if (is_null($store)) { $store = $this->getStoreId(); } + $store = Mage::app()->getStore($store); - if (!$store) { + if ($this->isEnabledFlat()) { + if ($store->getId() != $this->getStoreId()) { + $this->setStoreId($store); + } return $this; } - if ($store instanceof Mage_Core_Model_Store) { + /** + * For admin store we display all products + */ + if (!$store->isAdmin()) { $websiteId = $store->getWebsite()->getId(); + $this->joinField('website_id', 'catalog/product_website', 'website_id', 'product_id=entity_id', + '{{table}}.website_id='.$websiteId + ); } - else { - $websiteId = Mage::app()->getStore($store)->getWebsite()->getId(); + return $this; + } + + public function addWebsiteFilter($website=null) + { + if (is_null($website)) { + return $this; } - $this->joinField('website_id', 'catalog/product_website', 'website_id', 'product_id=entity_id', - '{{table}}.website_id='.$websiteId - ); + + if (is_array($website)) { + $this->joinField('website_id', 'catalog/product_website', 'website_id', 'product_id=entity_id', + '{{table}}.website_id IN('.$this->getConnection()->quoteInto('?', $website) . ')'); + } + return $this; } @@ -455,6 +674,41 @@ public function getAllIds($limit=null, $offset=null) return $this->getConnection()->fetchCol($idsSelect, $this->_bindParams); } + /** + * Retreive product count select for categories + * + * @return Varien_Db_Select + */ + public function getProductCountSelect() + { + if ($this->_productCountSelect === null) { + $this->_productCountSelect = clone $this->getSelect(); + $this->_productCountSelect->reset(Zend_Db_Select::COLUMNS) + ->reset(Zend_Db_Select::GROUP) + ->reset(Zend_Db_Select::ORDER) + ->distinct(false) + ->join(array('count_table' => $this->getTable('catalog/category_product_index')), + 'count_table.product_id = e.entity_id', + array('count_table.category_id', 'product_count' => new Zend_Db_Expr('COUNT(DISTINCT count_table.product_id)')) + ) + ->where('count_table.store_id = ?', $this->getStoreId()) + ->group('count_table.category_id'); + } + + return $this->_productCountSelect; + } + + /** + * Destruct product count select + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function unsProductCountSelect() + { + $this->_productCountSelect = null; + return $this; + } + /** * Adding product count to categories collection * @@ -463,33 +717,70 @@ public function getAllIds($limit=null, $offset=null) */ public function addCountToCategories($categoryCollection) { + $isAnchor = array(); + $isNotAnchor = array(); foreach ($categoryCollection as $category) { - $select = clone $this->getSelect(); - $select->reset(Zend_Db_Select::COLUMNS); - $select->reset(Zend_Db_Select::GROUP); - $select->reset(Zend_Db_Select::ORDER); - $select->distinct(false); - $select->join( - array('category_count_table' => $this->_productCategoryTable), - 'category_count_table.product_id=e.entity_id', - array('count_in_category'=>new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)')) - ); - if ($category->getIsAnchor()) { - $select->where($this->getConnection()->quoteInto( - 'category_count_table.category_id IN(?)', - explode(',', $category->getAllChildren()) - )); + $isAnchor[] = $category->getId(); + } else { + $isNotAnchor[] = $category->getId(); } - else { - $select->where($this->getConnection()->quoteInto( - 'category_count_table.category_id=?', - $category->getId() - )); + } + $productCounts = array(); + if ($isAnchor || $isNotAnchor) { + $select = $this->getProductCountSelect(); + + Mage::dispatchEvent('catalog_product_collection_before_add_count_to_categories', array('collection'=>$this)); + + if ($isAnchor) { + $anchorStmt = clone $select; + $anchorStmt->where('count_table.category_id in (?)', $isAnchor); + $productCounts += $this->getConnection()->fetchPairs($anchorStmt, array('category_id'=>'product_count')); + $anchorStmt = null; + } + if ($isNotAnchor) { + $notAnchorStmt = clone $select; + $notAnchorStmt->where('count_table.category_id in (?)', $isNotAnchor); + $productCounts += $this->getConnection()->fetchPairs($notAnchorStmt, array('category_id'=>'product_count')); + $notAnchorStmt = null; } + $select = null; + $this->unsProductCountSelect(); + } - $category->setProductCount((int) $this->getConnection()->fetchOne($select)); + foreach ($categoryCollection as $category) { + $_count = 0; + if (isset($productCounts[$category->getId()])) { + $_count = $productCounts[$category->getId()]; + } + $category->setProductCount($_count); } +// foreach ($categoryCollection as $category) { +// $select = clone $this->getSelect(); +// $select->reset(Zend_Db_Select::COLUMNS); +// $select->reset(Zend_Db_Select::GROUP); +// $select->reset(Zend_Db_Select::ORDER); +// $select->distinct(false); +// $select->join( +// array('category_count_table' => $this->_productCategoryTable), +// 'category_count_table.product_id=e.entity_id', +// array('count_in_category'=>new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)')) +// ); +// +// if ($category->getIsAnchor()) { +// $select->where($this->getConnection()->quoteInto( +// 'category_count_table.category_id IN(?)', +// explode(',', $category->getAllChildren()) +// )); +// } +// else { +// $select->where($this->getConnection()->quoteInto( +// 'category_count_table.category_id=?', +// $category->getId() +// )); +// } +// $category->setProductCount((int) $this->getConnection()->fetchOne($select)); +// } return $this; } @@ -560,7 +851,7 @@ protected function _addUrlRewrite() foreach ($this->getConnection()->fetchAll($select) as $row) { if (!isset($urlRewrites[$row['product_id']])) { - $urlRewrites[$row['product_id']] = $row['request_path']; + $urlRewrites[$row['product_id']] = $row['request_path']; } } @@ -611,10 +902,17 @@ public function addFinalPrice() */ protected function _joinPriceRules() { + if ($this->isEnabledFlat()) { + $customerGroup = Mage::getSingleton('customer/session')->getCustomerGroupId(); + $priceColumn = 'e.display_price_group_' . $customerGroup; + $this->getSelect()->from(null, array('_rule_price' => $priceColumn)); + + return $this; + } $wId = Mage::app()->getWebsite()->getId(); $gId = Mage::getSingleton('customer/session')->getCustomerGroupId(); - $storeDate = Mage::app()->getLocale()->storeDate($this->getStoreId()); + $storeDate = Mage::app()->getLocale()->storeTimeStamp($this->getStoreId()); $conditions = "_price_rule.product_id = e.entity_id AND "; $conditions .= "_price_rule.rule_date = '".$this->getResource()->formatDate($storeDate, false)."' AND "; $conditions .= "_price_rule.website_id = '{$wId}' AND "; @@ -635,7 +933,15 @@ protected function _addFinalPrice() $specialPrice = $product->getSpecialPrice(); $specialPriceFrom = $product->getSpecialFromDate(); $specialPriceTo = $product->getSpecialToDate(); - $rulePrice = $product->getData('_rule_price'); + if ($this->isEnabledFlat()) { + $rulePrice = null; + if ($product->getData('_rule_price') != $basePrice) { + $rulePrice = $product->getData('_rule_price'); + } + } + else { + $rulePrice = $product->getData('_rule_price'); + } $finalPrice = $product->getPriceModel()->calculatePrice( $basePrice, @@ -652,7 +958,8 @@ protected function _addFinalPrice() } } - public function getAllIdsCache($resetCache = false){ + public function getAllIdsCache($resetCache = false) + { $ids = null; if (!$resetCache) { $ids = $this->_allIdsCache; @@ -666,28 +973,73 @@ public function getAllIdsCache($resetCache = false){ return $ids; } - public function setAllIdsCache($value){ + public function setAllIdsCache($value) + { $this->_allIdsCache = $value; return $this; } - public function addAttributeToFilter($attribute, $condition=null, $joinType='inner'){ + /** + * Add attribute to filter + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract|string $attribute + * @param array $condition + * @param string $joinType + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function addAttributeToFilter($attribute, $condition=null, $joinType='inner') + { + if ($this->isEnabledFlat()) { + if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) { + $attribute = $attribute->getAttributeCode(); + } + + if (!isset($this->_selectAttributes[$attribute])) { + $this->addAttributeToSelect($attribute); + } + + if (isset($this->_selectAttributes[$attribute])) { + $this->getSelect()->where($this->_getConditionSql('e.'.$attribute, $condition)); + } + + return $this; + } + $this->_allIdsCache = null; if (is_string($attribute) && $attribute == 'is_saleable') { return $this->getSelect()->where($this->_getConditionSql('(IF(manage_stock, is_in_stock, 1))', $condition)); - } else { + } + else { return parent::addAttributeToFilter($attribute, $condition, $joinType); } } - public function addTaxPercents(){ + /** + * Add requere tax percent flag for product collection + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function addTaxPercents() + { $this->_addTaxPercents = true; - $this->addAttributeToSelect('tax_class_id'); - return $this; } - protected function _addTaxPercents(){ + /** + * Get require tax percent flag value + * + * @return bool + */ + public function requireTaxPercent() + { + return $this->_addTaxPercents; + } + + /** + * @deprecated from 1.3.0 + */ + protected function _addTaxPercents() + { $classToRate = array(); $request = Mage::getSingleton('tax/calculation')->getRateRequest(); foreach ($this as &$item) { @@ -762,6 +1114,8 @@ public function setVisibility($visibility) ); } + Mage::dispatchEvent('catalog_product_collection_set_visibility_after', array('collection' => $this)); + return $this; } @@ -772,38 +1126,87 @@ public function setOrder($attribute, $dir='desc') if ($attribute == 'price' && $storeId != 0) { $customerGroup = Mage::getSingleton('customer/session')->getCustomerGroupId(); - $priceAttributeId = $this->getAttribute('price')->getId(); + if ($this->isEnabledFlat()) { + $priceColumn = 'e.display_price_group_' . $customerGroup; + $this->getSelect()->order("{$priceColumn} {$dir}"); + } + else { + $priceAttributeId = $this->getAttribute('price')->getId(); - $entityCondition = '_price_order_table.entity_id = e.entity_id'; - $storeCondition = $this->getConnection()->quoteInto( - '_price_order_table.website_id = ?', - $websiteId - ); - $groupCondition = $this->getConnection()->quoteInto( - '_price_order_table.customer_group_id = ?', - $customerGroup - ); - $attributeCondition = $this->getConnection()->quoteInto( - '_price_order_table.attribute_id = ?', - $priceAttributeId - ); + $entityCondition = '_price_order_table.entity_id = e.entity_id'; + $storeCondition = $this->getConnection()->quoteInto( + '_price_order_table.website_id = ?', + $websiteId + ); + $groupCondition = $this->getConnection()->quoteInto( + '_price_order_table.customer_group_id = ?', + $customerGroup + ); + $attributeCondition = $this->getConnection()->quoteInto( + '_price_order_table.attribute_id = ?', + $priceAttributeId + ); - $this->getSelect()->joinLeft( - array('_price_order_table'=>$this->getTable('catalogindex/price')), - "{$entityCondition} AND {$storeCondition} AND {$groupCondition} AND {$attributeCondition}", - array() - ); - $this->getSelect()->order('_price_order_table.value ' . $dir); + $this->getSelect()->joinLeft( + array('_price_order_table'=>$this->getTable('catalogindex/price')), + "{$entityCondition} AND {$storeCondition} AND {$groupCondition} AND {$attributeCondition}", + array() + ); + $this->getSelect()->order('_price_order_table.value ' . $dir); - /** - * Distinct we are using for remove duplicates of products which have - * several rows in price index (like grouped products) - */ - $this->getSelect()->distinct(true); + /** + * Distinct we are using for remove duplicates of products which have + * several rows in price index (like grouped products) + */ + $this->getSelect()->distinct(true); + } } else { - parent::setOrder($attribute, $dir); + if ($this->isEnabledFlat()) { + if ($sortColumn = $this->getEntity()->getAttributeSortColumn($attribute)) { + $this->getSelect()->order("e.{$sortColumn} {$dir}"); + } + } + else { + parent::setOrder($attribute, $dir); + } } return $this; } + + /** + * Add attribute to sort order + * + * @param string $attribute + * @param string $dir + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection + */ + public function addAttributeToSort($attribute, $dir='asc') + { + if ($this->isEnabledFlat()) { + if ($attribute == 'position') { + $column = $attribute; + } + else { + $column = $this->getEntity()->getAttributeSortColumn($attribute); + } + + if ($column) { + $this->getSelect()->order("{$column} {$dir}"); + } + + return $this; + } + + if ($attribute !== 'position') { + $attrInstance = $this->getEntity()->getAttribute($attribute); + if ($attrInstance && $attrInstance->usesSource()) { + $attrInstance->getSource() + ->addValueSortToCollection($this, $dir); + return $this; + } + } + + return parent::addAttributeToSort($attribute, $dir); + } } diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item.php index b69b6de254..d591c3d767 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Catalog - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -30,17 +30,27 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Compare_Item extends Mage_Core_Model_Mysql4_Abstract { - + /** + * Initialize connection + * + */ protected function _construct() { $this->_init('catalog/compare_item', 'catalog_compare_item_id'); } - public function loadByProduct(Mage_Core_Model_Abstract $object, $product) + /** + * Load object by product + * + * @param Mage_Core_Model_Abstract $object + * @param mixed $product + * @return bool + */ + public function loadByProduct(Mage_Catalog_Model_Product_Compare_Item $object, $product) { $read = $this->_getReadAdapter(); if ($product instanceof Mage_Catalog_Model_Product) { @@ -69,6 +79,13 @@ public function loadByProduct(Mage_Core_Model_Abstract $object, $product) return true; } + /** + * Resource retrieve count compare items + * + * @param int $customerId + * @param int $visitorId + * @return int + */ public function getCount($customerId, $visitorId) { $select = $this->_getReadAdapter()->select()->from($this->getMainTable(), 'COUNT(*)') @@ -92,10 +109,10 @@ public function clean(Mage_Catalog_Model_Product_Compare_Item $object) ->from(array('compare_table' => $this->getMainTable()), array('catalog_compare_item_id')) ->joinLeft( array('visitor_table' => $this->getTable('log/visitor')), - 'compare_table.visitor_id = visitor_table.visitor_id', + '`visitor_table`.`visitor_id`=`compare_table`.`visitor_id`', array()) - ->where('compare_table.visitor_id NOT IS NULL') - ->where('visitor_table.visitor_id IS NULL') + ->where('compare_table.visitor_id>?',0) + ->where('`visitor_table`.`visitor_id` IS NULL') ->limit(1000); $itemIds = $this->_getReadAdapter()->fetchCol($select); @@ -105,7 +122,7 @@ public function clean(Mage_Catalog_Model_Product_Compare_Item $object) $this->_getWriteAdapter()->delete( $this->getMainTable(), - $this->_getWriteAdapter()->quoteInto('catalog_compare_item_id IN(?)', $eventIds) + $this->_getWriteAdapter()->quoteInto('catalog_compare_item_id IN(?)', $itemIds) ); } diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item/Collection.php index 599edcd201..394394e14d 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Compare/Item/Collection.php @@ -181,4 +181,18 @@ public function clear() return $this; } -} \ No newline at end of file + + /** + * Retrieve is flat enabled flag + * Overwrite disable flat for compared item if required EAV resource + * + * @return bool + */ + public function isEnabledFlat() + { + if (!Mage::helper('catalog/product_compare')->getAllowUsedFlat()) { + return false; + } + return parent::isEnabledFlat(); + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat.php new file mode 100644 index 0000000000..75854ac7d8 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat.php @@ -0,0 +1,142 @@ + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat + extends Mage_Core_Model_Mysql4_Abstract +{ + /** + * Store scope Id + * + * @var int + */ + protected $_storeId; + + /** + * Init connection and resource table + * + */ + protected function _construct() + { + $this->_init('catalog/product_flat', 'entity_id'); + $this->_storeId = Mage::app()->getStore()->getId(); + } + + /** + * Set store scope for resource model + * + * @param mixed $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat + */ + public function setStoreId($store) + { + $this->_storeId = Mage::app()->getStore($store)->getId(); + return $this; + } + + /** + * Retrieve Flat Table name + * + * @param mixed $store + * @return string + */ + public function getFlatTableName($store = null) + { + if (!is_numeric($store)) { + $store = Mage::app()->getStore($store)->getId(); + } + return $this->getTable('catalog/product_flat') . '_' . $store; + } + + /** + * Retrieve entity type id + * + * @return int + */ + public function getTypeId() + { + return Mage::getSingleton('eav/config') + ->getEntityType('catalog_product') + ->getEntityTypeId(); + } + + /** + * Retrieve attribute columns for collection select + * + * @param string $attributeCode + * @return array|null + */ + public function getAttributeForSelect($attributeCode) + { + $describe = $this->_getWriteAdapter()->describeTable($this->getFlatTableName()); + if (!isset($describe[$attributeCode])) { + return null; + } + $columns = array($attributeCode => $attributeCode); + + if (isset($describe[$attributeCode . '_value'])) { + $columns[$attributeCode . '_value'] = $attributeCode . '_value'; + } + + return $columns; + } + + /** + * Retrieve Attribute Sort column name + * + * @param string $attributeCode + * @return string + */ + public function getAttributeSortColumn($attributeCode) + { + $describe = $this->_getWriteAdapter()->describeTable($this->getFlatTableName()); + if (!isset($describe[$attributeCode])) { + return null; + } + if (isset($describe[$attributeCode . '_value'])) { + return $attributeCode . '_value'; + } + return $attributeCode; + } + + /** + * Retrieve Flat Table columns list + * + * @return array + */ + public function getAllTableColumns() + { + $describe = $this->_getWriteAdapter()->describeTable($this->getFlatTableName()); + return array_keys($describe); + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat/Indexer.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat/Indexer.php new file mode 100644 index 0000000000..6b35839cf1 --- /dev/null +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Flat/Indexer.php @@ -0,0 +1,935 @@ + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + extends Mage_Core_Model_Mysql4_Abstract +{ + const XML_NODE_MAX_INDEX_COUNT = 'global/catalog/product/flat/max_index_count'; + const XML_NODE_ATTRIBUTE_NODES = 'global/catalog/product/flat/attribute_nodes'; + + /** + * Attribute codes for flat + * + * @var array + */ + protected $_attributeCodes; + + /** + * Attribute objects for flat cache + * + * @var array + */ + protected $_attributes; + + /** + * Required system attributes for preload + * + * @var array + */ + protected $_systemAttributes = array('status', 'required_options', 'tax_class_id', 'weight'); + + /** + * Eav Catalog_Product Entity Type Id + * + * @var int + */ + protected $_entityTypeId; + + /** + * Flat table columns cache + * + * @var array + */ + protected $_columns; + + /** + * Flat table indexes cache + * + * @var array + */ + protected $_indexes; + + /** + * Product Type Instances cache + * + * @var array + */ + protected $_productTypes; + + /** + * Initialize connection + * + */ + protected function _construct() + { + $this->_init('catalog/product', 'entity_id'); + } + + /** + * Rebuild Catalog Product Flat Data + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function rebuild($store = null) + { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->rebuild($store->getId()); + } + $flag = $this->getFlatHelper()->getFlag(); + $flag->setIsBuild(true)->save(); + return $this; + } + + $this->prepareFlatTable($store); + $this->cleanNonWebsiteProducts($store); + $this->updateStaticAttributes($store); + $this->updateEavAttributes($store); + $this->updateEventAttributes($store); + $this->updateRelationProducts($store); + $this->cleanRelationProducts($store); + + return $this; + } + + /** + * Retrieve Catalog Product Flat helper + * + * @return Mage_Catalog_Helper_Product_Flat + */ + public function getFlatHelper() + { + return Mage::helper('catalog/product_flat'); + } + + /** + * Retrieve attribute codes using for flat + * + * @return array + */ + public function getAttributeCodes() + { + if (is_null($this->_attributeCodes)) { + $attributeNodes = Mage::getConfig() + ->getNode(self::XML_NODE_ATTRIBUTE_NODES) + ->children(); + foreach ($attributeNodes as $node) { + $attributes = Mage::getConfig()->getNode((string)$node)->asArray(); + $attributes = array_keys($attributes); + $this->_systemAttributes = array_unique(array_merge($attributes, $this->_systemAttributes)); + } + + $this->_attributeCodes = array(); + $whereCond = array( + $this->_getReadAdapter()->quoteInto('backend_type=?', 'static'), + $this->_getReadAdapter()->quoteInto('is_filterable>?', 0), + $this->_getReadAdapter()->quoteInto('is_filterable_in_search=?', 1), + $this->_getReadAdapter()->quoteInto('used_in_product_listing=?', 1), + $this->_getReadAdapter()->quoteInto('used_for_sort_by=?', 1), + $this->_getReadAdapter()->quoteInto('attribute_code IN(?)', $this->_systemAttributes) + ); + + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('eav/attribute'), array('attribute_id','attribute_code')) + ->where('entity_type_id=?', $this->getEntityTypeId()) + ->where(join(' OR ', $whereCond)); + $this->_attributeCodes = $this->_getReadAdapter() + ->fetchPairs($select); + } + return $this->_attributeCodes; + } + + /** + * Retrieve entity type + * + * @return string + */ + public function getEntityType() + { + return 'catalog_product'; + } + + /** + * Retrieve Catalog Entity Type Id + * + * @return int + */ + public function getEntityTypeId() + { + if (is_null($this->_entityTypeId)) { + $this->_entityTypeId = Mage::getResourceModel('catalog/config') + ->getEntityTypeId(); + } + return $this->_entityTypeId; + } + + /** + * Retrieve attribute objects for flat + * + * @param bool $cache + * @return array + */ + public function getAttributes() + { + if (is_null($this->_attributes)) { + $attributeCodes = $this->getAttributeCodes(false); + Mage::getSingleton('eav/config') + ->preloadAttributes($this->getEntityType(), $attributeCodes); + $entity = Mage::getSingleton('eav/config') + ->getEntityType($this->getEntityType()) + ->getEntity(); + foreach ($attributeCodes as $attributeCode) { + $attribute = Mage::getSingleton('eav/config') + ->getAttribute($this->getEntityType(), $attributeCode) + ->setEntity($entity); + $this->_attributes[$attributeCode] = $attribute; + } + } + return $this->_attributes; + } + + /** + * Retrieve loaded attribute by code + * + * @param string $attributeCode + * @return Mage_Eav_Model_Entity_Attribute + */ + public function getAttribute($attributeCode) + { + $attributes = $this->getAttributes(); + if (!isset($attributes[$attributeCode])) { + $attribute = Mage::getModel('catalog/resource_eav_attribute') + ->loadByCode($this->getEntityTypeId(), $attributeCode); + if (!$attribute->getId()) { + Mage::throwException(Mage::helper('catalog')->__('Invalid attribute %s', $attributeCode)); + } + $entity = Mage::getSingleton('eav/config') + ->getEntityType($this->getEntityType()) + ->getEntity(); + $attribute->setEntity($entity); + return $attribute; + } + return $attributes[$attributeCode]; + } + + /** + * Retrieve Catalog Product Flat Table name + * + * @param int $store + * @return string + */ + public function getFlatTableName($store) + { + return $this->getTable('catalog/product_flat') . '_' . $store; + } + + /** + * Retrieve catalog product flat table columns array + * + * @return array + */ + public function getFlatColumns() + { + if (is_null($this->_columns)) { + $this->_columns = array( + 'entity_id' => array( + 'type' => 'int(10)', + 'unsigned' => true, + 'is_null' => false, + 'default' => null, + 'extra' => 'auto_increment' + ), + 'child_id' => array( + 'type' => 'int(10)', + 'unsigned' => true, + 'is_null' => true, + 'default' => null, + 'extra' => null + ), + 'is_child' => array( + 'type' => 'tinyint(1)', + 'unsigned' => true, + 'is_null' => false, + 'default' => 0, + 'extra' => null + ), + 'attribute_set_id' => array( + 'type' => 'smallint(5)', + 'unsigned' => true, + 'is_null' => false, + 'default' => 0, + 'extra' => null + ), + 'type_id' => array( + 'type' => 'varchar(32)', + 'unsigned' => false, + 'is_null' => false, + 'default' => 'simple', + 'extra' => null + ) + ); + + foreach ($this->getAttributes() as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if (is_null($attribute->getFlatColumns())) { + continue; + } + + $this->_columns = array_merge($this->_columns, $attribute->getFlatColumns()); + } + + $columnsObject = new Varien_Object(); + $columnsObject->setColumns($this->_columns); + Mage::dispatchEvent('catalog_product_flat_prepare_columns', array( + 'columns' => $columnsObject + )); + $this->_columns = $columnsObject->getColumns(); + } + return $this->_columns; + } + + /** + * Retrieve catalog product flat table indexes array + * + * @return array + */ + public function getFlatIndexes() + { + if (is_null($this->_indexes)) { + $this->_indexes = array( + 'PRIMARY' => array( + 'type' => 'primary', + 'fields' => array('entity_id', 'child_id') + ), + 'IDX_CHILD_ID' => array( + 'type' => 'index', + 'fields' => array('child_id') + ), + 'IDX_IS_CHILD' => array( + 'type' => 'index', + 'fields' => array('entity_id', 'is_child') + ), + 'IDX_TYPE_ID' => array( + 'type' => 'index', + 'fields' => array('type_id') + ), + 'IDX_ATRRIBUTE_SET' => array( + 'type' => 'index', + 'fields' => array('attribute_set_id') + ), + ); + + foreach ($this->getAttributes() as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if (is_null($attribute->getFlatColumns())) { + continue; + } + $this->_indexes = array_merge($this->_indexes, $attribute->getFlatIndexes()); + } + + $indexesObject = new Varien_Object(); + $indexesObject->setIndexes($this->_indexes); + Mage::dispatchEvent('catalog_product_flat_prepare_indexes', array( + 'indexes' => $indexesObject + )); + $this->_indexes = $indexesObject->getIndexes(); + } + return $this->_indexes; + } + + /** + * Prepare flat table for store + * + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function prepareFlatTable($store) + { + $columns = $this->getFlatColumns(); + $indexes = $this->getFlatIndexes(); + + $maxIndex = Mage::getConfig()->getNode(self::XML_NODE_MAX_INDEX_COUNT); + + if (count($indexes) > $maxIndex) { + Mage::throwException(Mage::helper('catalog')->__("Flat Catalog module has a limit of %2\$d filterable and/or sort able attributes. Currently there are %1\$d. Please reduce the number of filterable/sort able attributes in order to use this module.", count($indexes), $maxIndex)); + } + + $tableName = $this->getFlatTableName($store); + $tableNameQuote = $this->_getWriteAdapter()->quoteIdentifier($tableName); + $tableExistsSql = $this->_getWriteAdapter() + ->quoteInto("SHOW TABLE STATUS LIKE ?", $tableName); + if (!$this->_getWriteAdapter()->fetchRow($tableExistsSql)) { + $sql = "CREATE TABLE {$tableNameQuote} (\n"; + foreach ($columns as $field => $fieldProp) { + $fieldNameQuote = $this->_getWriteAdapter()->quoteIdentifier($field); + $sql .= " {$fieldNameQuote} {$fieldProp['type']}"; + $sql .= ($fieldProp['unsigned'] ? ' UNSIGNED' : ''); + $sql .= ($fieldProp['extra'] ? ' ' . $fieldProp['extra'] : ''); + $sql .= ($fieldProp['is_null'] === false ? ' NOT NULL' : ''); + $sql .= ($fieldProp['default'] === null + ? ' DEFAULT NULL' + : $this->_getReadAdapter()->quoteInto(' DEFAULT ?', $fieldProp['default'])); + $sql .= ",\n"; + } + foreach ($indexes as $indexName => $indexProp) { + $fields = $indexProp['fields']; + if (is_array($fields)) { + $fieldSql = array(); + foreach ($fields as $field) { + $fieldSql[] = $this->_getReadAdapter()->quoteIdentifier($field); + } + $fieldSql = join(',', $fieldSql); + } + else { + $fieldSql = $this->_getReadAdapter()->quoteIdentifier($fields); + } + + switch (strtolower($indexProp['type'])) { + case 'primary': + $condition = 'PRIMARY KEY'; + break; + case 'unique': + $condition = 'UNIQUE ' . $this->_getReadAdapter()->quoteIdentifier($indexName); + break; + case 'fulltext': + $condition = 'FULLTEXT ' . $this->_getReadAdapter()->quoteIdentifier($indexName); + break; + default: + $condition = 'KEY ' . $this->_getReadAdapter()->quoteIdentifier($indexName); + break; + } + + $sql .= " {$condition} (" . $fieldSql . "),\n"; + } + + $sql .= " CONSTRAINT `FK_CATALOG_PRODUCT_FLAT_{$store}_ENTITY` FOREIGN KEY (`entity_id`)" + . " REFERENCES `{$this->getTable('catalog/product')}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE,\n" + . " CONSTRAINT `FK_CATALOG_PRODUCT_FLAT_{$store}_CHILD` FOREIGN KEY (`child_id`)" + . " REFERENCES `{$this->getTable('catalog/product')}` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE\n" + . ") ENGINE=InnoDB DEFAULT CHARSET=utf8"; + $this->_getWriteAdapter()->query($sql); + } + else { + $describe = $this->_getWriteAdapter()->describeTable($tableName); + $indexList = $this->_getWriteAdapter()->getIndexList($tableName); + + $addColumns = array_diff_key($columns, $describe); + $dropColumns = array_diff_key($describe, $columns); + + $addIndexes = array_diff_key($indexes, $indexList); + $dropIndexes = array_diff_key($indexList, $indexes); + + if ($addColumns or $dropColumns or $addIndexes or $dropIndexes) { + $sql = "ALTER TABLE {$tableNameQuote}"; + // add columns + foreach ($addColumns as $columnName => $columnProp) { + //var_dump($columnProp); + $columnNameQuote = $this->_getWriteAdapter()->quoteIdentifier($columnName); + $sql .= " ADD COLUMN {$columnNameQuote} {$columnProp['type']}"; + $sql .= ($columnProp['unsigned'] ? ' UNSIGNED' : ''); + $sql .= ($columnProp['extra'] ? ' ' . $columnProp['extra'] : ''); + $sql .= ($columnProp['is_null'] === false ? ' NOT NULL' : ''); + $sql .= ($columnProp['default'] === null + ? ' DEFAULT NULL' + : $this->_getReadAdapter()->quoteInto(' DEFAULT ?', $columnProp['default'])); + $sql .= ","; + } + // add indexes + foreach ($addIndexes as $indexName => $indexProp) { + $indexNameQuote = $this->_getWriteAdapter()->quoteIdentifier($indexName); + + switch (strtolower($indexProp['type'])) { + case 'primary': + $condition = 'PRIMARY KEY'; + break; + case 'unique': + $condition = 'UNIQUE ' . $indexNameQuote; + break; + case 'fulltext': + $condition = 'FULLTEXT ' . $indexNameQuote; + break; + default: + $condition = 'INDEX ' . $indexNameQuote; + break; + } + + $fields = $indexProp['fields']; + if (is_array($fields)) { + $fieldSql = array(); + foreach ($fields as $field) { + $fieldSql[] = $this->_getReadAdapter()->quoteIdentifier($field); + } + $fieldSql = join(',', $fieldSql); + } + else { + $fieldSql = $this->_getReadAdapter()->quoteIdentifier($fields); + } + + $sql .= " ADD {$condition} ({$fieldSql}),"; + } + // drop columns + foreach ($dropColumns as $columnName => $columnProp) { + $columnNameQuote = $this->_getWriteAdapter()->quoteIdentifier($columnName); + $sql .= " DROP COLUMN {$columnNameQuote},"; + } + // drop indexes + foreach ($dropIndexes as $indexName => $indexProp) { + $indexNameQuote = $this->_getWriteAdapter()->quoteIdentifier($indexName); + $sql .= " DROP INDEX {$indexNameQuote},"; + } + + $sql = rtrim($sql, ","); + $this->_getWriteAdapter()->query($sql); + } + } + + return $this; + } + + /** + * Add or Update static attributes + * + * @param int $store + * @param int|array $productIds update only product(s) + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateStaticAttributes($store, $productIds = null) + { + $website = Mage::app()->getStore($store)->getWebsite()->getId(); + $status = $this->getAttribute('status'); + /* @var $status Mage_Eav_Model_Entity_Attribute */ + $fieldList = array('entity_id', 'child_id', 'is_child', 'type_id', 'attribute_set_id'); + $isChild = new Zend_Db_Expr('0'); + $columns = $this->getFlatColumns(); + $select = $this->_getWriteAdapter()->select() + ->from( + array('e' => $this->getTable('catalog/product')), + array('entity_id', 'entity_id', $isChild, 'type_id', 'attribute_set_id')) + ->join( + array('wp' => $this->getTable('catalog/product_website')), + "`e`.`entity_id`=`wp`.`product_id` AND `wp`.`website_id`={$website}", + array()) + ->joinLeft( + array('t1' => $status->getBackend()->getTable()), + "`e`.`entity_id`=`t1`.`entity_id`", + array()) + ->joinLeft( + array('t2' => $status->getBackend()->getTable()), + "t2.entity_id = t1.entity_id" + . " AND t1.entity_type_id = t2.entity_type_id" + . " AND t1.attribute_id = t2.attribute_id" + . " AND t2.store_id = {$store}", + array()) + ->where("t1.entity_type_id=?", $status->getEntityTypeId()) + ->where("t1.attribute_id=?", $status->getId()) + ->where("t1.store_id=?", 0) + ->where("IFNULL(`t2`.`value`, `t1`.`value`)=?", Mage_Catalog_Model_Product_Status::STATUS_ENABLED); + foreach ($this->getAttributes() as $attributeCode => $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if ($attribute->getBackend()->getType() == 'static') { + if (!isset($columns[$attributeCode])) { + continue; + } + $fieldList[] = $attributeCode; + $select->from(null, $attributeCode); + } + } + + if (!is_null($productIds)) { + $select->where('e.entity_id IN(?)', $productIds); + } + + $sql = $select->insertFromSelect($this->getFlatTableName($store), $fieldList); + $this->_getWriteAdapter()->query($sql); + return $this; + } + + /** + * Remove non website products + * + * @param int $store + * @param int|array $productIds + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function cleanNonWebsiteProducts($store, $productIds = null) + { + $website = Mage::app()->getStore($store)->getWebsite()->getId(); + + $select = $this->_getWriteAdapter()->select() + ->from( + array('e' => $this->getFlatTableName($store)), + null) + ->joinLeft( + array('wp' => $this->getTable('catalog/product_website')), + "`e`.`entity_id`=`wp`.`product_id` AND `e`.`child_id`=`wp`.`product_id` AND `wp`.`website_id`={$website}", + array()); + if (!is_null($productIds)) { + $cond = array( + $this->_getWriteAdapter()->quoteInto('e.entity_id IN(?)', $productIds), + $this->_getWriteAdapter()->quoteInto('e.child_id IN(?)', $productIds) + ); + $select->where(join(' OR ', $cond)); + } + + $sql = $select->deleteFromSelect('e'); + $this->_getWriteAdapter()->query($sql); + + return $this; + } + + /** + * Update attribute flat data + * + * @param Mage_Eav_Model_Entity_Attribute $attribute + * @param int $store + * @param int|array $productIds update only product(s) + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateAttribute($attribute, $store, $productIds = null) + { + if ($attribute->getBackend()->getType() == 'static') { + $select = $this->_getWriteAdapter()->select() + ->from(array('main_table' => $this->getTable('catalog/product')), $attribute->getAttributeCode()); + if (!is_null($productIds)) { + $select->where('main_table.entity_id IN(?)', $productIds); + } + $sql = $select->crossUpdateFromSelect(array('e' => $this->getFlatTableName($store))); + $this->_getWriteAdapter()->query($sql); + } + else { + $select = $attribute->getFlatUpdateSelect($store); + if ($select instanceof Varien_Db_Select) { + if (!is_null($productIds)) { + $select->where('e.entity_id IN(?)', $productIds); + } + $sql = $select->crossUpdateFromSelect(array('e' => $this->getFlatTableName($store))); + $this->_getWriteAdapter()->query($sql); + } + } + return $this; + } + + /** + * Update non static EAV attributes flat data + * + * @param int $store + * @param int|array $productIds update only product(s) + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateEavAttributes($store, $productIds = null) + { + foreach ($this->getAttributes() as $attribute) { + /* @var $attribute Mage_Eav_Model_Entity_Attribute */ + if ($attribute->getBackend()->getType() != 'static') { + $this->updateAttribute($attribute, $store, $productIds); + } + } + return $this; + } + + /** + * Update events observer attributes + * + * @param int $store + * @return Mage_Catalog_Model_Product_Flat_Indexer + */ + public function updateEventAttributes($store = null) + { + Mage::dispatchEvent('catalog_product_flat_rebuild', array( + 'store_id' => $store, + 'table' => $this->getFlatTableName($store) + )); + } + + /** + * Retrieve Product Type Instances + * as key - type code, value - instance model + * + * @return array + */ + public function getProductTypeInstances() + { + if (is_null($this->_productTypes)) { + $this->_productTypes = array(); + $productEmulator = new Varien_Object(); + + foreach (array_keys(Mage_Catalog_Model_Product_Type::getTypes()) as $typeId) { + $productEmulator->setTypeId($typeId); + $this->_productTypes[$typeId] = Mage::getSingleton('catalog/product_type') + ->factory($productEmulator); + } + } + return $this->_productTypes; + } + + /** + * Update relation products + * + * @param int $store + * @param int|array $productIds Update child product(s) only + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateRelationProducts($store, $productIds = null) + { +// $website = Mage::app()->getStore($store)->getWebsite()->getId(); + foreach ($this->getProductTypeInstances() as $typeInstance) { + if (!$typeInstance->isComposite()) { + continue; + } + $relation = $typeInstance->getRelationInfo(); + if ($relation + and $relation->getTable() + and $relation->getParentFieldName() + and $relation->getChildFieldName() + ) { + $columns = $this->getFlatColumns(); + $fieldList = array_keys($columns); + unset($columns['entity_id']); + unset($columns['child_id']); + unset($columns['is_child']); + + $select = $this->_getWriteAdapter()->select() + ->from( + array('t' => $this->getTable($relation->getTable())), + array($relation->getParentFieldName(), $relation->getChildFieldName(), new Zend_Db_Expr('1'))) +// ->join( +// array('wp' => $this->getTable('catalog/product_website')), +// "`t`.`{$relation->getChildFieldName()}`=`wp`.`product_id`" +// . " AND `t`.`{$relation->getParentFieldName()}`=`wp`.`product_id`" +// . " AND `wp`.`website_id`={$website}", +// array()) + ->join( + array('e' => $this->getFlatTableName($store)), + "`e`.`entity_id`=`t`.`{$relation->getChildFieldName()}`", + array_keys($columns) + ); + if (!is_null($relation->getWhere())) { + $select->where($relation->getWhere()); + } + if (!is_null($productIds)) { + $cond = array( + $this->_getWriteAdapter()->quoteInto("{$relation->getChildFieldName()} IN(?)", $productIds), + $this->_getWriteAdapter()->quoteInto("{$relation->getParentFieldName()} IN(?)", $productIds) + ); + + $select->where(join(' OR ', $cond)); + } + $sql = $select->insertFromSelect($this->getFlatTableName($store), $fieldList); + $this->_getWriteAdapter()->query($sql); + } + } + + return $this; + } + + /** + * Update children data from parent + * + * @param int $store + * @param int|array $productIds + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateChildrenDataFromParent($store, $productIds = null) + { + $select = $this->_getWriteAdapter()->select(); + foreach (array_keys($this->getFlatColumns()) as $columnName) { + if ($columnName == 'entity_id' || $columnName == 'child_id' || $columnName == 'is_child') { + continue; + } + $select->from(null, array($columnName => new Zend_Db_Expr('`t1`.`'. $columnName.'`'))); + } + $select + ->joinLeft( + array('t1' => $this->getFlatTableName($store)), + "`t2`.`child_id`=`t1`.`entity_id` AND `t1`.`is_child`=0", + array()) + ->where('t2.is_child=1'); + + if (!is_null($productIds)) { + $select->where('t2.child_id IN(?)', $productIds); + } + + $sql = $select->crossUpdateFromSelect(array('t2' => $this->getFlatTableName($store))); + $this->_getWriteAdapter()->query($sql); + + return $this; + } + + /** + * Clean unused relation products + * + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function cleanRelationProducts($store) + { + foreach ($this->getProductTypeInstances() as $typeInstance) { + if (!$typeInstance->isComposite()) { + continue; + } + $relation = $typeInstance->getRelationInfo(); + if ($relation + and $relation->getTable() + and $relation->getParentFieldName() + and $relation->getChildFieldName() + ) { + $select = $this->_getWriteAdapter()->select() + ->distinct(true) + ->from( + $this->getTable($relation->getTable()), + "{$relation->getParentFieldName()}" + ) + ; + $joinLeftCond = null; + if (!is_null($relation->getWhere())) { + $select->where($relation->getWhere()); + $joinLeftCond = ' AND ' . $relation->getWhere(); + } + + $entitySelect = new Zend_Db_Expr($select->__toString()); + + $select = $this->_getWriteAdapter()->select() + ->from( + array('e' => $this->getFlatTableName($store)), + null + ) + ->joinLeft( + array('t' => $this->getTable($relation->getTable())), + "e.entity_id=t.{$relation->getParentFieldName()} AND e.child_id=t.{$relation->getChildFieldName()}" + . $joinLeftCond, + array()) + ->where("e.is_child=?", 1) + ->where("e.entity_id IN(?)", $entitySelect) + ->where("t.{$relation->getChildFieldName()} IS NULL"); + + $sql = $select->deleteFromSelect('e'); + $this->_getWriteAdapter()->query($sql); + } + } + + return $this; + } + + /** + * Remove product data from flat + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function removeProduct($productIds, $store) + { + $cond = array( + $this->_getWriteAdapter()->quoteInto('entity_id IN(?)', $productIds), + $this->_getWriteAdapter()->quoteInto('child_id IN(?)', $productIds) + ); + $cond = join(' OR ', $cond); + $this->_getWriteAdapter()->delete($this->getFlatTableName($store), $cond); + + return $this; + } + + /** + * Remove children from parent product + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function removeProductChildren($productIds, $store) + { + $cond = array( + $this->_getWriteAdapter()->quoteInto('entity_id IN(?)', $productIds), + $this->_getWriteAdapter()->quoteInto('is_child=?', 1), + ); + $this->_getWriteAdapter()->delete($this->getFlatTableName($store), $cond); + + return $this; + } + + /** + * Update flat data for product + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function updateProduct($productIds, $store) + { + $this->saveProduct($productIds, $store); + + Mage::dispatchEvent('catalog_product_flat_update_product', array( + 'store_id' => $store, + 'table' => $this->getFlatTableName($store), + 'product_ids' => $productIds + )); + + return $this; + } + + /** + * Save product(s) data for store + * + * @param int|array $productIds + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function saveProduct($productIds, $store) + { + $this->updateStaticAttributes($store, $productIds); + $this->updateEavAttributes($store, $productIds); + + return $this; + } + + /** + * Delete flat table process + * + * @param int $store + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat_Indexer + */ + public function deleteFlatTable($store) + { + $tableName = $this->getFlatTableName($store); + $tableNameQuote = $this->_getWriteAdapter()->quoteIdentifier($tableName); + $tableExistsSql = $this->_getWriteAdapter() + ->quoteInto("SHOW TABLE STATUS LIKE ?", $tableName); + if ($this->_getWriteAdapter()->query($tableExistsSql)) { + $sql = sprintf('DROP TABLE IF EXISTS %s', $tableNameQuote); + $this->_getWriteAdapter()->query($sql); + } + + return $this; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Status.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Status.php index 6523f1c060..f28ab9329f 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Status.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Status.php @@ -1,215 +1,231 @@ - - */ -class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status extends Mage_Core_Model_Mysql4_Abstract -{ - protected function _construct() - { - $this->_init('catalog/product_enabled_index', 'product_id'); - } - - /** - * Product atrribute cache - * - * @var array - */ - protected $_productAttributes = array(); - - /** - * Retrieve product attribute - * - * @return Mage_Eav_Model_Entity_Attribute_Abstract - */ - protected function _getProductAttribute($attribute) - { - if (empty($this->_productAttributes[$attribute])) { - $this->_productAttributes[$attribute] = Mage::getSingleton('catalog/product')->getResource()->getAttribute($attribute); - } - return $this->_productAttributes[$attribute]; - } - - /** - * Refresh enabled index cache - * - * @param int $productId - * @param int $storeId - * - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status - */ - public function refreshEnabledIndex($productId, $storeId) - { - $statusAttributeId = $this->_getProductAttribute('status')->getId(); - $visibilityAttributeId = $this->_getProductAttribute('visibility')->getId(); - $statusTable = $this->_getProductAttribute('status')->getBackend()->getTable(); - $visibilityTable = $this->_getProductAttribute('visibility')->getBackend()->getTable(); - - $indexTable = $this->getTable('catalog/product_enabled_index'); - - if ($storeId == 0) { - foreach (Mage::app()->getStores() as $store) { - $this->refreshEnabledIndex($productId, $store->getId()); - } - - return $this; - } - - $this->_getWriteAdapter()->delete($indexTable, array( - $this->_getWriteAdapter()->quoteInto('product_id=?', $productId), - $this->_getWriteAdapter()->quoteInto('store_id=?', $storeId) - )); - - $query = "INSERT INTO $indexTable - SELECT - {$productId}, {$storeId}, IFNULL(t_v.value, t_v_default.value) - FROM - {$visibilityTable} AS t_v_default - LEFT JOIN {$visibilityTable} AS `t_v` - ON (t_v.entity_id = t_v_default.entity_id) AND (t_v.attribute_id='{$visibilityAttributeId}') AND (t_v.store_id='{$storeId}') - INNER JOIN {$statusTable} AS `t_s_default` - ON (t_s_default.entity_id = t_v_default.entity_id) AND (t_s_default.attribute_id='{$statusAttributeId}') AND t_s_default.store_id=0 - LEFT JOIN {$statusTable} AS `t_s` - ON (t_s.entity_id = t_v_default.entity_id) AND (t_s.attribute_id='{$statusAttributeId}') AND (t_s.store_id='{$storeId}') - WHERE - t_v_default.entity_id={$productId} - AND t_v_default.attribute_id='{$visibilityAttributeId}' AND t_v_default.store_id=0 - AND (IFNULL(t_s.value, t_s_default.value)=".Mage_Catalog_Model_Product_Status::STATUS_ENABLED.")"; - $this->_getWriteAdapter()->query($query); - - return $this; - } - - /** - * Update product status for store - * - * @param int $productId - * @param int $storId - * @param int $value - * - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status - */ - public function updateProductStatus($productId, $storId, $value) - { - $statusAttributeId = $this->_getProductAttribute('status')->getId(); - $statusEntityTypeId = $this->_getProductAttribute('status')->getEntityTypeId(); - $statusTable = $this->_getProductAttribute('status')->getBackend()->getTable(); - $refreshIndex = true; - - $prop = array( - 'entity_type_id' => $statusEntityTypeId, - 'attribute_id' => $statusAttributeId, - 'store_id' => $storId, - 'entity_id' => $productId, - 'value' => $value - ); - - $select = $this->_getWriteAdapter()->select() - ->from($statusTable) - ->where('attribute_id=?', $statusAttributeId) - ->where('store_id=?', $storId) - ->where('entity_id=?', $productId); - $row = $this->_getWriteAdapter()->fetchRow($select); - - if ($row) { - if ($row['value'] == $value) { - $refreshIndex = false; - } - else { - $this->_getWriteAdapter()->update($statusTable, $prop, $this->_getWriteAdapter()->quoteInto('value_id=?', $row['value_id'])); - } - } - else { - $this->_getWriteAdapter()->insert($statusTable, $prop); - } - - if ($refreshIndex) { - $this->refreshEnabledIndex($productId, $storId); - } - - return $this; - } - - /** - * Retrieve Product(s) status for store - * Return array where key is a product_id, value - status - * - * @param array|int $productIds - * @param int $storeId - * @return array - */ - public function getProductStatus($productIds, $storeId = null) - { - $statuses = array(); - - $attribute = $this->_getProductAttribute('status'); - $attributeTable = $attribute->getBackend()->getTable(); - - if (!is_array($productIds)) { - $productIds = array($productIds); - } - - if (is_null($storeId) || $storeId == 0) { - $select = $this->_getReadAdapter()->select() - ->from($attributeTable, array('entity_id', 'value')) - ->where('entity_id IN(?)', $productIds) - ->where('attribute_id=?', $attribute->getAttributeId()) - ->where('store_id=?', 0); - $rows = $this->_getWriteAdapter()->fetchPairs($select); - } - else { - $select = $this->_getReadAdapter()->select() - ->from( - array('t1' => $attributeTable), - array('entity_id', 'IFNULL(t2.value, t1.value) as value')) - ->joinLeft( - array('t2' => $attributeTable), - $this->_getReadAdapter()->quoteInto('t1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id=?', $storeId), - array() - ) - ->where('t1.store_id = ?', 0) - ->where('t1.attribute_id = ?', $attribute->getAttributeId()) - ->where('t1.entity_id IN(?)', $productIds); - $rows = $this->_getWriteAdapter()->fetchPairs($select); - } - - foreach ($productIds as $productId) { - if (isset($rows[$productId])) { - $statuses[$productId] = $rows[$productId]; - } - else { - $statuses[$productId] = -1; - } - } - - return $statuses; - } -} \ No newline at end of file + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status extends Mage_Core_Model_Mysql4_Abstract +{ + /** + * Product atrribute cache + * + * @var array + */ + protected $_productAttributes = array(); + + /** + * Initialize connection + * + */ + protected function _construct() + { + $this->_init('catalog/product_enabled_index', 'product_id'); + } + + /** + * Retrieve product attribute (public method for status model) + * + * @param string $attributeCode + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + public function getProductAttribute($attributeCode) + { + return $this->_getProductAttribute($attributeCode); + } + + /** + * Retrieve product attribute + * + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + protected function _getProductAttribute($attribute) + { + if (empty($this->_productAttributes[$attribute])) { + $this->_productAttributes[$attribute] = Mage::getSingleton('catalog/product')->getResource()->getAttribute($attribute); + } + return $this->_productAttributes[$attribute]; + } + + /** + * Refresh enabled index cache + * + * @param int $productId + * @param int $storeId + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status + */ + public function refreshEnabledIndex($productId, $storeId) + { + $statusAttributeId = $this->_getProductAttribute('status')->getId(); + $visibilityAttributeId = $this->_getProductAttribute('visibility')->getId(); + $statusTable = $this->_getProductAttribute('status')->getBackend()->getTable(); + $visibilityTable = $this->_getProductAttribute('visibility')->getBackend()->getTable(); + + $indexTable = $this->getTable('catalog/product_enabled_index'); + + if ($storeId == 0) { + foreach (Mage::app()->getStores() as $store) { + $this->refreshEnabledIndex($productId, $store->getId()); + } + + return $this; + } + + $this->_getWriteAdapter()->delete($indexTable, array( + $this->_getWriteAdapter()->quoteInto('product_id=?', $productId), + $this->_getWriteAdapter()->quoteInto('store_id=?', $storeId) + )); + + $query = "INSERT INTO $indexTable + SELECT + {$productId}, {$storeId}, IFNULL(t_v.value, t_v_default.value) + FROM + {$visibilityTable} AS t_v_default + LEFT JOIN {$visibilityTable} AS `t_v` + ON (t_v.entity_id = t_v_default.entity_id) AND (t_v.attribute_id='{$visibilityAttributeId}') AND (t_v.store_id='{$storeId}') + INNER JOIN {$statusTable} AS `t_s_default` + ON (t_s_default.entity_id = t_v_default.entity_id) AND (t_s_default.attribute_id='{$statusAttributeId}') AND t_s_default.store_id=0 + LEFT JOIN {$statusTable} AS `t_s` + ON (t_s.entity_id = t_v_default.entity_id) AND (t_s.attribute_id='{$statusAttributeId}') AND (t_s.store_id='{$storeId}') + WHERE + t_v_default.entity_id={$productId} + AND t_v_default.attribute_id='{$visibilityAttributeId}' AND t_v_default.store_id=0 + AND (IFNULL(t_s.value, t_s_default.value)=".Mage_Catalog_Model_Product_Status::STATUS_ENABLED.")"; + $this->_getWriteAdapter()->query($query); + + return $this; + } + + /** + * Update product status for store + * + * @param int $productId + * @param int $storId + * @param int $value + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Status + */ + public function updateProductStatus($productId, $storId, $value) + { + $statusAttributeId = $this->_getProductAttribute('status')->getId(); + $statusEntityTypeId = $this->_getProductAttribute('status')->getEntityTypeId(); + $statusTable = $this->_getProductAttribute('status')->getBackend()->getTable(); + $refreshIndex = true; + + $prop = array( + 'entity_type_id' => $statusEntityTypeId, + 'attribute_id' => $statusAttributeId, + 'store_id' => $storId, + 'entity_id' => $productId, + 'value' => $value + ); + + $select = $this->_getWriteAdapter()->select() + ->from($statusTable) + ->where('attribute_id=?', $statusAttributeId) + ->where('store_id=?', $storId) + ->where('entity_id=?', $productId); + $row = $this->_getWriteAdapter()->fetchRow($select); + + if ($row) { + if ($row['value'] == $value) { + $refreshIndex = false; + } + else { + $this->_getWriteAdapter()->update($statusTable, $prop, $this->_getWriteAdapter()->quoteInto('value_id=?', $row['value_id'])); + } + } + else { + $this->_getWriteAdapter()->insert($statusTable, $prop); + } + + if ($refreshIndex) { + $this->refreshEnabledIndex($productId, $storId); + } + + return $this; + } + + /** + * Retrieve Product(s) status for store + * Return array where key is a product_id, value - status + * + * @param array|int $productIds + * @param int $storeId + * @return array + */ + public function getProductStatus($productIds, $storeId = null) + { + $statuses = array(); + + $attribute = $this->_getProductAttribute('status'); + $attributeTable = $attribute->getBackend()->getTable(); + + if (!is_array($productIds)) { + $productIds = array($productIds); + } + + if (is_null($storeId) || $storeId == 0) { + $select = $this->_getReadAdapter()->select() + ->from($attributeTable, array('entity_id', 'value')) + ->where('entity_id IN(?)', $productIds) + ->where('attribute_id=?', $attribute->getAttributeId()) + ->where('store_id=?', 0); + $rows = $this->_getWriteAdapter()->fetchPairs($select); + } + else { + $select = $this->_getReadAdapter()->select() + ->from( + array('t1' => $attributeTable), + array('entity_id', 'IFNULL(t2.value, t1.value) as value')) + ->joinLeft( + array('t2' => $attributeTable), + $this->_getReadAdapter()->quoteInto('t1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id=?', $storeId), + array() + ) + ->where('t1.store_id = ?', 0) + ->where('t1.attribute_id = ?', $attribute->getAttributeId()) + ->where('t1.entity_id IN(?)', $productIds); + $rows = $this->_getWriteAdapter()->fetchPairs($select); + } + + foreach ($productIds as $productId) { + if (isset($rows[$productId])) { + $statuses[$productId] = $rows[$productId]; + } + else { + $statuses[$productId] = -1; + } + } + + return $statuses; + } +} diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Attribute/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Attribute/Collection.php index bde956408c..e542ca0319 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Attribute/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Attribute/Collection.php @@ -1,240 +1,240 @@ - - */ -class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection - extends Mage_Core_Model_Mysql4_Collection_Abstract -{ - protected $_labelTable; - protected $_priceTable; - /** - * Product instance - * - * @var Mage_Catalog_Model_Product - */ - protected $_product; - - protected function _construct() - { - $this->_init('catalog/product_type_configurable_attribute'); - $this->_labelTable = $this->getTable('catalog/product_super_attribute_label'); - $this->_priceTable = $this->getTable('catalog/product_super_attribute_pricing'); - } - - protected function _initSelect() - { - parent::_initSelect(); - return $this; - } - - public function setProductFilter($product) - { - $this->_product = $product; - $this->addFieldToFilter('product_id', $product->getId()); - return $this; - } - - public function orderByPosition($dir='asc') - { - $this->getSelect()->order('position '.$dir); - return $this; - } - - public function getStoreId() - { - return (int) $this->_product->getStoreId(); - } - - protected function _afterLoad() - { - parent::_afterLoad(); - Varien_Profiler::start('TTT1:'.__METHOD__); - $this->_addProductAttributes(); - Varien_Profiler::stop('TTT1:'.__METHOD__); - Varien_Profiler::start('TTT2:'.__METHOD__); - $this->_addAssociatedProductFilters(); - Varien_Profiler::stop('TTT2:'.__METHOD__); - Varien_Profiler::start('TTT3:'.__METHOD__); - $this->_loadLabels(); - Varien_Profiler::stop('TTT3:'.__METHOD__); - Varien_Profiler::start('TTT4:'.__METHOD__); - $this->_loadPrices(); - Varien_Profiler::stop('TTT4:'.__METHOD__); - return $this; - } - - /** - * Add product attributes to collection items - * - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection - */ - protected function _addProductAttributes() - { - foreach ($this->_items as $item) { - $productAttribute = $this->getProduct()->getTypeInstance() - ->getAttributeById($item->getAttributeId()); - $item->setProductAttribute($productAttribute); - } - return $this; - } - - public function _addAssociatedProductFilters() - { - $this->getProduct()->getTypeInstance() - ->getUsedProducts($this->getColumnValues('attribute_id')); // Filter associated products - return $this; - } - - /** - * Load attribute labels - * - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection - */ - protected function _loadLabels() - { - if ($this->count()) { - $select = $this->getConnection()->select() - ->from(array('default'=>$this->_labelTable)) - ->joinLeft( - array('store'=>$this->_labelTable), - 'store.product_super_attribute_id=default.product_super_attribute_id AND store.store_id='.$this->getStoreId(), - array( - 'store_lebel'=>'value', - 'label' => new Zend_Db_Expr('IFNULL(store.value, default.value)') - ) - ) - ->where('default.product_super_attribute_id IN (?)', array_keys($this->_items)) - ->where('default.store_id=0'); - foreach ($this->getConnection()->fetchAll($select) as $data) { - $this->getItemById($data['product_super_attribute_id'])->setLabel($data['label']); - } - } - return $this; - } - - /** - * Load attribute prices information - * - * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection - */ - protected function _loadPrices() - { - if ($this->count()) { - /*$select = $this->getConnection()->select() - ->from(array('price'=>$this->_priceTable)) - ->join(array('option'=>$this->getTable('eav/attribute_option')), - 'option.option_id=price.value_index' - ) - ->joinLeft(array('option_label'=>$this->getTable('eav/attribute_option_value')), - 'option_label.option_id=price.value_index AND option_label.store_id=' . $this->getStoreId(), - array('store_label'=>'value') - ) - ->join(array('option_default_label'=>$this->getTable('eav/attribute_option_value')), - 'option_default_label.option_id=price.value_index', - array( - 'default_label'=>'value', - 'label' => new Zend_Db_Expr('IFNULL(option_label.value, option_default_label.value)') - ) - ) - ->where('price.product_super_attribute_id IN (?)', array_keys($this->_items)) - ->where('option_default_label.store_id=0') - ->order('option.sort_order asc'); OLD */ - - - - $select = $this->getConnection()->select() - ->from(array('price'=>$this->_priceTable)) - ->where('price.product_super_attribute_id IN (?)', array_keys($this->_items)) - ->where('price.pricing_value IS NOT NULL'); - - $pricings = $this->getConnection()->fetchAll($select); - - $values = array(); - - - foreach ($this->_items as $item) { - $productAttribute = $item->getProductAttribute(); - if (!($productAttribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract)) - continue; - $options = $productAttribute->getFrontend()->getSelectOptions(); - foreach ($options as $option) { - foreach ($this->getProduct()->getTypeInstance()->getUsedProducts() as $associatedProduct) { - if (!empty($option['value']) - && $option['value'] == $associatedProduct->getData( - $productAttribute->getAttributeCode())) { - // If option aviable in associated product - if (!isset($values[$item->getId() . ':' . $option['value']])) { - // If option not added, we will add it. - $values[$item->getId() . ':' . $option['value']] = array( - 'product_super_attribute_id' => $item->getId(), - 'value_index' => $option['value'], - 'label' => $option['label'], - 'default_label' => $option['label'], - 'store_label' => $option['label'], - 'is_percent' => 0, - 'pricing_value' => null - ); - } - } - } - } - } - - - foreach ($pricings as $pricing) { - // Addding pricing to options - $valueKey = $pricing['product_super_attribute_id'] . ':' . $pricing['value_index']; - if (isset($values[$valueKey])) { - $values[$valueKey]['pricing_value'] = $pricing['pricing_value']; - $values[$valueKey]['is_percent'] = $pricing['is_percent']; - $values[$valueKey]['value_id'] = $pricing['value_id']; - } - } - - foreach ($values as $data) { - $this->getItemById($data['product_super_attribute_id'])->addPrice($data); - } - } - return $this; - } - - /** - * Retrive product instance - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - return $this->_product; - } + + */ +class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection + extends Mage_Core_Model_Mysql4_Collection_Abstract +{ + protected $_labelTable; + protected $_priceTable; + /** + * Product instance + * + * @var Mage_Catalog_Model_Product + */ + protected $_product; + + protected function _construct() + { + $this->_init('catalog/product_type_configurable_attribute'); + $this->_labelTable = $this->getTable('catalog/product_super_attribute_label'); + $this->_priceTable = $this->getTable('catalog/product_super_attribute_pricing'); + } + + protected function _initSelect() + { + parent::_initSelect(); + return $this; + } + + public function setProductFilter($product) + { + $this->_product = $product; + $this->addFieldToFilter('product_id', $product->getId()); + return $this; + } + + public function orderByPosition($dir='asc') + { + $this->getSelect()->order('position '.$dir); + return $this; + } + + public function getStoreId() + { + return (int) $this->_product->getStoreId(); + } + + protected function _afterLoad() + { + parent::_afterLoad(); + Varien_Profiler::start('TTT1:'.__METHOD__); + $this->_addProductAttributes(); + Varien_Profiler::stop('TTT1:'.__METHOD__); + Varien_Profiler::start('TTT2:'.__METHOD__); + $this->_addAssociatedProductFilters(); + Varien_Profiler::stop('TTT2:'.__METHOD__); + Varien_Profiler::start('TTT3:'.__METHOD__); + $this->_loadLabels(); + Varien_Profiler::stop('TTT3:'.__METHOD__); + Varien_Profiler::start('TTT4:'.__METHOD__); + $this->_loadPrices(); + Varien_Profiler::stop('TTT4:'.__METHOD__); + return $this; + } + + /** + * Add product attributes to collection items + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection + */ + protected function _addProductAttributes() + { + foreach ($this->_items as $item) { + $productAttribute = $this->getProduct()->getTypeInstance(true) + ->getAttributeById($item->getAttributeId(), $this->getProduct()); + $item->setProductAttribute($productAttribute); + } + return $this; + } + + public function _addAssociatedProductFilters() + { + $this->getProduct()->getTypeInstance(true) + ->getUsedProducts($this->getColumnValues('attribute_id'), $this->getProduct()); // Filter associated products + return $this; + } + + /** + * Load attribute labels + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection + */ + protected function _loadLabels() + { + if ($this->count()) { + $select = $this->getConnection()->select() + ->from(array('default'=>$this->_labelTable)) + ->joinLeft( + array('store'=>$this->_labelTable), + 'store.product_super_attribute_id=default.product_super_attribute_id AND store.store_id='.$this->getStoreId(), + array( + 'store_lebel'=>'value', + 'label' => new Zend_Db_Expr('IFNULL(store.value, default.value)') + ) + ) + ->where('default.product_super_attribute_id IN (?)', array_keys($this->_items)) + ->where('default.store_id=0'); + foreach ($this->getConnection()->fetchAll($select) as $data) { + $this->getItemById($data['product_super_attribute_id'])->setLabel($data['label']); + } + } + return $this; + } + + /** + * Load attribute prices information + * + * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection + */ + protected function _loadPrices() + { + if ($this->count()) { + /*$select = $this->getConnection()->select() + ->from(array('price'=>$this->_priceTable)) + ->join(array('option'=>$this->getTable('eav/attribute_option')), + 'option.option_id=price.value_index' + ) + ->joinLeft(array('option_label'=>$this->getTable('eav/attribute_option_value')), + 'option_label.option_id=price.value_index AND option_label.store_id=' . $this->getStoreId(), + array('store_label'=>'value') + ) + ->join(array('option_default_label'=>$this->getTable('eav/attribute_option_value')), + 'option_default_label.option_id=price.value_index', + array( + 'default_label'=>'value', + 'label' => new Zend_Db_Expr('IFNULL(option_label.value, option_default_label.value)') + ) + ) + ->where('price.product_super_attribute_id IN (?)', array_keys($this->_items)) + ->where('option_default_label.store_id=0') + ->order('option.sort_order asc'); OLD */ + + + + $select = $this->getConnection()->select() + ->from(array('price'=>$this->_priceTable)) + ->where('price.product_super_attribute_id IN (?)', array_keys($this->_items)) + ->where('price.pricing_value IS NOT NULL'); + + $pricings = $this->getConnection()->fetchAll($select); + + $values = array(); + + + foreach ($this->_items as $item) { + $productAttribute = $item->getProductAttribute(); + if (!($productAttribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract)) + continue; + $options = $productAttribute->getFrontend()->getSelectOptions(); + foreach ($options as $option) { + foreach ($this->getProduct()->getTypeInstance(true)->getUsedProducts(null, $this->getProduct()) as $associatedProduct) { + if (!empty($option['value']) + && $option['value'] == $associatedProduct->getData( + $productAttribute->getAttributeCode())) { + // If option aviable in associated product + if (!isset($values[$item->getId() . ':' . $option['value']])) { + // If option not added, we will add it. + $values[$item->getId() . ':' . $option['value']] = array( + 'product_super_attribute_id' => $item->getId(), + 'value_index' => $option['value'], + 'label' => $option['label'], + 'default_label' => $option['label'], + 'store_label' => $option['label'], + 'is_percent' => 0, + 'pricing_value' => null + ); + } + } + } + } + } + + + foreach ($pricings as $pricing) { + // Addding pricing to options + $valueKey = $pricing['product_super_attribute_id'] . ':' . $pricing['value_index']; + if (isset($values[$valueKey])) { + $values[$valueKey]['pricing_value'] = $pricing['pricing_value']; + $values[$valueKey]['is_percent'] = $pricing['is_percent']; + $values[$valueKey]['value_id'] = $pricing['value_id']; + } + } + + foreach ($values as $data) { + $this->getItemById($data['product_super_attribute_id'])->addPrice($data); + } + } + return $this; + } + + /** + * Retrive product instance + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + return $this->_product; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Product/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Product/Collection.php index 129d1a169b..2492424577 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Product/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Type/Configurable/Product/Collection.php @@ -56,4 +56,15 @@ public function setProductFilter($product) $this->getSelect()->where('link_table.parent_id=?', (int) $product->getId()); return $this; } + + /** + * Retrieve is flat enabled flag + * Return alvays false if magento run admin + * + * @return bool + */ + public function isEnabledFlat() + { + return false; + } } diff --git a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Setup.php b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Setup.php index 26a992a5c3..fff7ce30eb 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Setup.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Setup.php @@ -1390,5 +1390,4 @@ public function rebuildCategoryLevels() } return $this; } - } diff --git a/app/code/core/Mage/Catalog/controllers/CategoryController.php b/app/code/core/Mage/Catalog/controllers/CategoryController.php index 7c9b535db8..bd77eaf3d9 100644 --- a/app/code/core/Mage/Catalog/controllers/CategoryController.php +++ b/app/code/core/Mage/Catalog/controllers/CategoryController.php @@ -40,6 +40,7 @@ class Mage_Catalog_CategoryController extends Mage_Core_Controller_Front_Action */ protected function _initCatagory() { + Mage::dispatchEvent('catalog_controller_category_init_before', array('controller_action'=>$this)); $categoryId = (int) $this->getRequest()->getParam('id', false); if (!$categoryId) { return false; @@ -54,6 +55,12 @@ protected function _initCatagory() } Mage::getSingleton('catalog/session')->setLastVisitedCategoryId($category->getId()); Mage::register('current_category', $category); + try { + Mage::dispatchEvent('catalog_controller_category_init_after', array('category'=>$category, 'controller_action'=>$this)); + } catch (Mage_Core_Exception $e) { + Mage::logException($e); + return false; + } return $category; } diff --git a/app/code/core/Mage/Catalog/controllers/IndexController.php b/app/code/core/Mage/Catalog/controllers/IndexController.php index 52f81f6ef4..05685c4989 100644 --- a/app/code/core/Mage/Catalog/controllers/IndexController.php +++ b/app/code/core/Mage/Catalog/controllers/IndexController.php @@ -1,36 +1,91 @@ -_redirect('/'); - } +_redirect('/'); + } + + public function productAction() + { + $productIds = array( + 16,17,18,19,20,25,26,27,28,29,30,31,32,33,34,35,36,37 +,38,39,41,42,44,45,46,47,48,49,51,52,53,74,75,79,80,81,82,84,85,86,87,88,89,90,91,92,94,95,96,97,99,100 +,101,102,104,105,106,107,109,110,111,113,114,115,117,118,121,122,124,125,127,128,129,130,131,132,133 +,134,137,138,139,140,141,143,145,147,148,149,150,151,152,153,154,155,156,157,159,160,161,162,166 + ); +// $productIds = array( +// 26 +// ); + $time = microtime(true); + for ($i = 0; $i < 5000; $i ++) + { + $productId = array_rand($productIds, 1); + $productId = $productIds[$productId]; + $product = Mage::getModel('catalog/product'); + $memory = memory_get_usage(); + $product + ->load($productId); + + // kill options + foreach($product->getOptions() as $option) { + /* @var $option Mage_Catalog_Model_Product_Option */ + foreach ($option->getValues() as $value) { + /* @var $value Mage_Catalog_Model_Product_Option_Value */ + $value->setProduct(null); + $value->unsetOption(); + } + $option->setProduct(null); + } + $product->setOptions(array()); + //$product->setCustomOptions(array()); +// $product->getStockItem() +// ->setProduct(null); +// $product->setStockItem(null); + /* @var $product Mage_Catalog_Model_Product */ + echo sprintf("%04d. sku: %s, time: %.3f, memory: %.3f/%.3f Mb
", + $i, + $product->getSku(), + microtime(true) - $time, + $memory / 1024 / 1024, + memory_get_usage() / 1024 / 1024 + ); + +// var_dump($product); +// +// +// +// var_dump( $product->debug() ); +// die(); + $time = microtime(true); + } + } } \ No newline at end of file diff --git a/app/code/core/Mage/Catalog/controllers/Product/CompareController.php b/app/code/core/Mage/Catalog/controllers/Product/CompareController.php index 22a07068aa..ab783d3023 100644 --- a/app/code/core/Mage/Catalog/controllers/Product/CompareController.php +++ b/app/code/core/Mage/Catalog/controllers/Product/CompareController.php @@ -30,10 +30,10 @@ * * @category Mage * @package Mage_Catalog - * @author Magento Core Team + * @author Magento Core Team */ - class Mage_Catalog_Product_CompareController extends Mage_Core_Controller_Front_Action - { +class Mage_Catalog_Product_CompareController extends Mage_Core_Controller_Front_Action +{ public function indexAction() { $items = $this->getRequest()->getParam('items'); @@ -73,6 +73,8 @@ public function addAction() ); Mage::dispatchEvent('catalog_product_compare_add_product', array('product'=>$product)); } + + Mage::helper('catalog/product_compare')->calculate(); } $this->_redirectReferer(); @@ -104,6 +106,7 @@ public function removeAction() $this->__('Product %s successfully removed from compare list', $product->getName()) ); Mage::dispatchEvent('catalog_product_compare_remove_product', array('product'=>$item)); + Mage::helper('catalog/product_compare')->calculate(); } } } @@ -130,6 +133,7 @@ public function clearAction() try { $items->clear(); $session->addSuccess($this->__('Compare list successfully cleared')); + Mage::helper('catalog/product_compare')->calculate(); } catch (Mage_Core_Exception $e) { $session->addError($e->getMessage()); diff --git a/app/code/core/Mage/Catalog/controllers/ProductController.php b/app/code/core/Mage/Catalog/controllers/ProductController.php index f702f1a4f4..2ade6484d5 100644 --- a/app/code/core/Mage/Catalog/controllers/ProductController.php +++ b/app/code/core/Mage/Catalog/controllers/ProductController.php @@ -39,6 +39,7 @@ class Mage_Catalog_ProductController extends Mage_Core_Controller_Front_Action */ protected function _initProduct() { + Mage::dispatchEvent('catalog_controller_product_init_before', array('controller_action'=>$this)); $categoryId = (int) $this->getRequest()->getParam('category', false); $productId = (int) $this->getRequest()->getParam('id'); @@ -75,7 +76,14 @@ protected function _initProduct() Mage::register('current_product', $product); Mage::register('product', $product); - Mage::dispatchEvent('catalog_controller_product_init', array('product'=>$product)); + try { + Mage::dispatchEvent('catalog_controller_product_init', array('product'=>$product)); + Mage::dispatchEvent('catalog_controller_product_init_after', array('product'=>$product, 'controller_action' => $this)); + } catch (Mage_Core_Exception $e) { + Mage::logException($e); + return false; + } + return $product; } @@ -119,6 +127,11 @@ public function viewAction() if ($product = $this->_initProduct()) { Mage::dispatchEvent('catalog_controller_product_view', array('product'=>$product)); + if ($this->getRequest()->getParam('options')) { + $notice = $product->getTypeInstance(true)->getSpecifyOptionMessage(); + Mage::getSingleton('catalog/session')->addNotice($notice); + } + Mage::getSingleton('catalog/session')->setLastViewedProductId($product->getId()); Mage::getModel('catalog/design')->applyDesign($product, Mage_Catalog_Model_Design::APPLY_FOR_PRODUCT); @@ -129,9 +142,9 @@ public function viewAction() $this->renderLayout(); } else { - if (isset($_GET['store'])) { + if (isset($_GET['store']) && $this->getRequest()->isDispatched()) { $this->_redirect(''); - } else { + } elseif ($this->getRequest()->isDispatched()) { $this->_forward('noRoute'); } } @@ -142,7 +155,14 @@ public function viewAction() */ public function galleryAction() { - $this->_initProduct(); + if (!$this->_initProduct()) { + if (isset($_GET['store']) && $this->getRequest()->isDispatched()) { + $this->_redirect(''); + } elseif ($this->getRequest()->isDispatched()) { + $this->_forward('noRoute'); + } + return; + } $this->loadLayout(); $this->renderLayout(); } diff --git a/app/code/core/Mage/Catalog/controllers/Seo/SitemapController.php b/app/code/core/Mage/Catalog/controllers/Seo/SitemapController.php index 2f195dc214..84a78c9723 100644 --- a/app/code/core/Mage/Catalog/controllers/Seo/SitemapController.php +++ b/app/code/core/Mage/Catalog/controllers/Seo/SitemapController.php @@ -54,7 +54,14 @@ public function preDispatch(){ */ public function categoryAction() { - $this->loadLayout(); + $update = $this->getLayout()->getUpdate(); + $update->addHandle('default'); + $this->addActionLayoutHandles(); + if (Mage::helper('catalog/map')->getIsUseCategoryTreeMode()) { + $update->addHandle(strtolower($this->getFullActionName()).'_tree'); + } + $this->loadLayoutUpdates(); + $this->generateLayoutXml()->generateLayoutBlocks(); $this->renderLayout(); } diff --git a/app/code/core/Mage/Catalog/etc/api.xml b/app/code/core/Mage/Catalog/etc/api.xml index 5bdba37fac..2fa71d02c8 100644 --- a/app/code/core/Mage/Catalog/etc/api.xml +++ b/app/code/core/Mage/Catalog/etc/api.xml @@ -405,6 +405,19 @@ catalog_product_attribute_tier_price catalog_product_attribute_tier_price + + + catalogCategory + catalogCategoryAttribute + catalogProduct + catalogProductAttribute + catalogProductAttributeSet + catalogProductType + catalogProductAttributeTierPrice + catalogProductAttributeMedia + catalogProductLink + + diff --git a/app/code/core/Mage/Catalog/etc/config.xml b/app/code/core/Mage/Catalog/etc/config.xml index b643d5cd15..1fb67964fd 100644 --- a/app/code/core/Mage/Catalog/etc/config.xml +++ b/app/code/core/Mage/Catalog/etc/config.xml @@ -28,7 +28,7 @@ - 0.7.57 + 0.7.63 @@ -43,6 +43,7 @@ 111 11 11 + 11 1 1 @@ -101,9 +102,6 @@ catalog_category_product_index
- - catalog_category_tree
-
catalog_compare_item
@@ -116,12 +114,14 @@ catalog_product_enabled_index
- - catalog_product_link
-
catalog_product_link_type
+ + + catalog_product_link
+
+ catalog_product_link_attribute
@@ -160,10 +160,6 @@ catalog_product_entity_media_gallery_value
- - catalog_product_entity_media_gallery_image
-
- catalog_product_option
@@ -182,6 +178,14 @@ catalog_product_option_type_title
+ + + catalog_category_flat
+
+ + + catalog_product_flat
+
@@ -211,13 +215,154 @@ Mage_Catalog_Block + + + + + singleton + catalog/observer + storeAdd + + + singleton + catalog/product_flat_observer + storeAdd + + + + + + + singleton + catalog/observer + storeEdit + + + singleton + catalog/product_flat_observer + storeEdit + + + + + + + singleton + catalog/product_flat_observer + storeDelete + + + + + + + singleton + catalog/observer + storeGroupSave + + + singleton + catalog/product_flat_observer + storeGroupSave + + + + + + + singleton + catalog/observer + categoryMove + + + + + + + singleton + catalog/observer + catalogProductImportAfter + + + singleton + catalog/product_flat_observer + catalogProductImportAfter + + + + + + + singleton + catalog/observer + categorySaveAfter + + + + + + + + singleton + catalog/product_flat_observer + customerGroupSaveAfter + + + + + + + + singleton + catalog/product_flat_observer + catalogProductSaveAfter + + + + + + + singleton + catalog/product_flat_observer + catalogProductStatusUpdate + + + + + + + singleton + catalog/product_flat_observer + catalogProductWebsiteUpdate + + + + + + + singleton + catalog/product_flat_observer + catalogEntityAttributeSaveAfter + + + + + + + singleton + catalog/observer + catalogProductCompareClean + + + + + catalog/product_type_simple - 10 0 @@ -228,7 +373,6 @@ - 50 @@ -239,12 +383,10 @@ - 30 catalog/product_type_virtual - 20 0 @@ -274,6 +416,15 @@ + + + adminhtml/catalog_product_edit_tab_options_type_file + + + + + + + + + adminhtml/catalog_product_edit_tab_options_type_date + + + + + + + + + + + + 64 + + frontend/product/collection/attributes + +
@@ -387,62 +559,6 @@ - - - - - singleton - catalog/observer - storeAdd - - - - - - - singleton - catalog/observer - storeEdit - - - - - - - singleton - catalog/observer - storeGroupSave - - - - - - - singleton - catalog/observer - categoryMove - - - - - - - singleton - catalog/observer - catalogProductImportAfter - - - - - - - singleton - catalog/observer - catalogProductCompareClean - - - - @@ -477,6 +593,15 @@ + + + + model + catalog/product_option_observer + copyQuoteFilesToOrderFiles + + + @@ -536,7 +661,13 @@ 5,10,15,20,25 9 10 + 0 + position + + 0 + 30 + 0 @@ -551,6 +682,11 @@ 1 - + + m,d,y + 12h + php,exe + - - - - 0.7.5 - - - - - - Mage_CatalogInventory_Model - cataloginventory_mysql4 - - - Mage_CatalogInventory_Model_Mysql4 - - - cataloginventory_stock
-
- - cataloginventory_stock_item
-
- - cataloginventory_stock_status
-
-
-
-
- - - Mage_CatalogInventory_Helper - - - - - - Mage_CatalogInventory - Mage_Eav_Model_Entity_Setup - - - core_setup - - - - - core_write - - - - - core_read - - - - - - - - - singleton - cataloginventory/observer - addInventoryData - - - - - - - singleton - cataloginventory/observer - addInventoryDataToCollection - - - - - - - singleton - cataloginventory/observer - productStatusUpdate - - - - - - - singleton - cataloginventory/observer - checkQuoteItemQty - - - - - - - singleton - cataloginventory/observer - lockOrderInventoryData - - - - - - - singleton - cataloginventory/observer - createOrderItem - - - - - - - singleton - cataloginventory/observer - cancelOrderItem - - - - - - - singleton - cataloginventory/observer - refundOrderItem - - - - - - - singleton - cataloginventory/observer - saveInventoryData - - - - - - - singleton - cataloginventory/observer - copyInventoryData - - - - - - - singleton - cataloginventory/observer - updateItemsStockUponConfigChange - - - - - - - - - - 1 - - - 1 - - - - -
- - - - - - - Mage_CatalogInventory.csv - - - - - - - - - - - - Mage_CatalogInventory.csv - - - - - - - - - - - - - - Inventory Section - - - - - - - - - - - - - - - 1 - 1 - - - 1 - 0 - 10000 - 1 - 0 - 1 - - - -
+ + + + + + 0.7.5 + + + + + + Mage_CatalogInventory_Model + cataloginventory_mysql4 + + + Mage_CatalogInventory_Model_Mysql4 + + + cataloginventory_stock
+
+ + cataloginventory_stock_item
+
+ + cataloginventory_stock_status
+
+
+
+
+ + + Mage_CatalogInventory_Helper + + + + + + Mage_CatalogInventory + Mage_Eav_Model_Entity_Setup + + + core_setup + + + + + core_write + + + + + core_read + + + + + + + + + singleton + cataloginventory/observer + addInventoryData + + + + + + + singleton + cataloginventory/observer + addStockStatusToCollection + + + + + + + singleton + cataloginventory/observer + addInventoryDataToCollection + + + + + + + singleton + cataloginventory/observer + productStatusUpdate + + + + + + + singleton + cataloginventory/observer + checkQuoteItemQty + + + + + + + singleton + cataloginventory/observer + lockOrderInventoryData + + + + + + + singleton + cataloginventory/observer + createOrderItem + + + + + + + singleton + cataloginventory/observer + cancelOrderItem + + + + + + + singleton + cataloginventory/observer + refundOrderItem + + + + + + + singleton + cataloginventory/observer + saveInventoryData + + + + + + + singleton + cataloginventory/observer + copyInventoryData + + + + + + + singleton + cataloginventory/observer + updateItemsStockUponConfigChange + + + + + + + singleton + cataloginventory/observer + catalogProductWebsiteUpdate + + + + + + + + + + 1 + + + 1 + + + + +
+ + + + + + + Mage_CatalogInventory.csv + + + + + + + + + + + + Mage_CatalogInventory.csv + + + + + + + + + + + + + + Inventory Section + + + + + + + + + + + + + + + 1 + 1 + + + 1 + 0 + 10000 + 1 + 0 + 1 + + + +
diff --git a/app/code/core/Mage/CatalogInventory/etc/wsdl.xml b/app/code/core/Mage/CatalogInventory/etc/wsdl.xml new file mode 100644 index 0000000000..ee4559e55b --- /dev/null +++ b/app/code/core/Mage/CatalogInventory/etc/wsdl.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Retrieve stock data by product ids + + + + + Update product stock data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/CatalogRule/Model/Mysql4/Rule.php b/app/code/core/Mage/CatalogRule/Model/Mysql4/Rule.php index 47f895b6ef..9aae021fba 100644 --- a/app/code/core/Mage/CatalogRule/Model/Mysql4/Rule.php +++ b/app/code/core/Mage/CatalogRule/Model/Mysql4/Rule.php @@ -53,13 +53,17 @@ public function _beforeSave(Mage_Core_Model_Abstract $object) ->setSecond(0); $object->setFromDate($date); } - $object->setFromDate($object->getFromDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + if ($object->getFromDate() instanceof Zend_Date) { + $object->setFromDate($object->getFromDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + } if (!$object->getToDate()) { $object->setToDate(new Zend_Db_Expr('NULL')); } else { - $object->setToDate($object->getToDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + if ($object->getToDate() instanceof Zend_Date) { + $object->setToDate($object->getToDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + } } parent::_beforeSave($object); } @@ -83,8 +87,12 @@ public function updateRuleProductData(Mage_CatalogRule_Model_Rule $rule) return $this; } - $productIds = $rule->getMatchingProductIds(); $websiteIds = explode(',', $rule->getWebsiteIds()); + if (empty($websiteIds)) { + return $this; + } + + $productIds = $rule->getMatchingProductIds(); $customerGroupIds = $rule->getCustomerGroupIds(); $fromTime = strtotime($rule->getFromDate()); @@ -180,13 +188,25 @@ public function removeCatalogPricesForDateRange($fromDate, $toDate, $productId=n $conds[] = $write->quoteInto('product_id=?', $productId); } - /** - * Add product ids to affected products - */ - $query = 'REPLACE INTO ' . $this->getTable('catalogrule/affected_product') . ' FROM - SELECT DISTINCT product_id FROM ' . $this->getTable('catalogrule/rule_product_price') . ' WHERE ' . - join(' AND ', $conds); + $write->delete($this->getTable('catalogrule/rule_product_price'), $conds); + return $this; + } + /** + * Delete old price rules data + * + * @param int $maxDate + * @param mixed $productId + * @return Mage_CatalogRule_Model_Mysql4_Rule + */ + public function deleteOldData($date, $productId=null) + { + $write = $this->_getWriteAdapter(); + $conds = array(); + $conds[] = $write->quoteInto('rule_dateformatDate($date)); + if (!is_null($productId)) { + $conds[] = $write->quoteInto('product_id=?', $productId); + } $write->delete($this->getTable('catalogrule/rule_product_price'), $conds); return $this; } @@ -270,9 +290,10 @@ public function getRuleProductsForDateRange($fromDate, $toDate, $productId=null) * @param int $fromDate * @param int $toDate * @param int|null $productId + * @param int|null $websiteId * @return Zend_Db_Statement_Interface */ - protected function _getRuleProductsStmt($fromDate, $toDate, $productId=null) + protected function _getRuleProductsStmt($fromDate, $toDate, $productId=null, $websiteId = null) { $read = $this->_getReadAdapter(); /** @@ -310,13 +331,21 @@ protected function _getRuleProductsStmt($fromDate, $toDate, $productId=null) array('default_price'=>'pp_default.value') ); - foreach (Mage::app()->getWebsites() as $website) { - $websiteId = $website->getId(); + if ($websiteId !== null) { + $website = Mage::app()->getWebsite($websiteId); $defaultGroup = $website->getDefaultGroup(); - if (!$defaultGroup instanceof Mage_Core_Model_Store_Group) { - continue; + if ($defaultGroup instanceof Mage_Core_Model_Store_Group) { + $storeId = $defaultGroup->getDefaultStoreId(); + } else { + $storeId = Mage_Core_Model_App::ADMIN_STORE_ID; } - $storeId = $defaultGroup->getDefaultStoreId(); + + $select->joinInner( + array('product_website'=>$this->getTable('catalog/product_website')), + 'product_website.product_id=rp.product_id AND product_website.website_id='.$websiteId, + array() + ); + $tableAlias = 'pp'.$websiteId; $fieldAlias = 'website_'.$websiteId.'_price'; $select->joinLeft( @@ -324,8 +353,26 @@ protected function _getRuleProductsStmt($fromDate, $toDate, $productId=null) sprintf($joinCondition, $tableAlias, $storeId), array($fieldAlias=>$tableAlias.'.value') ); - } + } else { + foreach (Mage::app()->getWebsites() as $website) { + $websiteId = $website->getId(); + $defaultGroup = $website->getDefaultGroup(); + if ($defaultGroup instanceof Mage_Core_Model_Store_Group) { + $storeId = $defaultGroup->getDefaultStoreId(); + } else { + $storeId = Mage_Core_Model_App::ADMIN_STORE_ID; + } + $storeId = $defaultGroup->getDefaultStoreId(); + $tableAlias = 'pp'.$websiteId; + $fieldAlias = 'website_'.$websiteId.'_price'; + $select->joinLeft( + array($tableAlias=>$priceTable), + sprintf($joinCondition, $tableAlias, $storeId), + array($fieldAlias=>$tableAlias.'.value') + ); + } + } return $read->query($select); } @@ -346,8 +393,15 @@ public function applyAllRulesForDateRange($fromDate=null, $toDate=null, $product Mage::dispatchEvent('catalogrule_before_apply', array('resource'=>$this)); + $clearOldData = false; if ($fromDate === null) { $fromDate = mktime(0,0,0,date('m'),date('d')-1); + /** + * If fromDate not specified we can delete all data oldest than 1 day + * We have run it for clear table in case when cron was not installed + * and old data exist in table + */ + $clearOldData = true; } if (is_string($fromDate)) { $fromDate = strtotime($fromDate); @@ -366,76 +420,161 @@ public function applyAllRulesForDateRange($fromDate=null, $toDate=null, $product } $this->removeCatalogPricesForDateRange($fromDate, $toDate, $productId); - - $productsStmt = $this->_getRuleProductsStmt($fromDate, $toDate, $productId); + if ($clearOldData) { + $this->deleteOldData($fromDate, $productId); + } try { - $dayPrices = array(); - $stopFlags = array(); - $prevKey = null; - while ($ruleData = $productsStmt->fetch()) { - $productId = $ruleData['product_id']; - $productKey= $productId . '_' . $ruleData['website_id'] . '_' . $ruleData['customer_group_id']; - - if ($prevKey && ($prevKey != $productKey)) { - $stopFlags = array(); - } - - /** - * Build prices for each day - */ - for ($time=$fromDate; $time<=$toDate; $time+=self::SECONDS_IN_DAY) { - - if (($ruleData['from_time']==0 || $time >= $ruleData['from_time']) - && ($ruleData['to_time']==0 || $time <=$ruleData['to_time'])) { - - $priceKey = $time . '_' . $productKey; - - if (isset($stopFlags[$priceKey])) { - continue; - } - - if (!isset($dayPrices[$priceKey])) { - $dayPrices[$priceKey] = array( - 'rule_date' => $time, - 'website_id' => $ruleData['website_id'], - 'customer_group_id' => $ruleData['customer_group_id'], - 'product_id' => $productId, - 'rule_price' => $this->_calcRuleProductPrice($ruleData), - 'latest_start_date' => $ruleData['from_time'], - 'earliest_end_date' => $ruleData['to_time'], - ); - } - else { - $dayPrices[$priceKey]['rule_price'] = $this->_calcRuleProductPrice( - $ruleData, - $dayPrices[$priceKey] - ); - $dayPrices[$priceKey]['latest_start_date'] = max( - $dayPrices[$priceKey]['latest_start_date'], - $ruleData['from_time'] - ); - $dayPrices[$priceKey]['earliest_end_date'] = min( - $dayPrices[$priceKey]['earliest_end_date'], - $ruleData['to_time'] - ); - } - - if ($ruleData['action_stop']) { - $stopFlags[$priceKey] = true; - } - } - } - - $prevKey = $productKey; - - if (count($dayPrices)>100) { - $this->_saveRuleProductPrices($dayPrices); - $dayPrices = array(); - } - } - $this->_saveRuleProductPrices($dayPrices); - $write->commit(); + /** + * Update products rules prices per each website separatly + * because of max join limit in mysql + */ + foreach (Mage::app()->getWebsites(false) as $website) { + $productsStmt = $this->_getRuleProductsStmt( + $fromDate, + $toDate, + $productId, + $website->getId() + ); + + $dayPrices = array(); + $stopFlags = array(); + $prevKey = null; + + while ($ruleData = $productsStmt->fetch()) { + $productId = $ruleData['product_id']; + $productKey= $productId . '_' + . $ruleData['website_id'] . '_' + . $ruleData['customer_group_id']; + + if ($prevKey && ($prevKey != $productKey)) { + $stopFlags = array(); + } + + /** + * Build prices for each day + */ + for ($time=$fromDate; $time<=$toDate; $time+=self::SECONDS_IN_DAY) { + if (($ruleData['from_time']==0 || $time >= $ruleData['from_time']) + && ($ruleData['to_time']==0 || $time <=$ruleData['to_time'])) { + + $priceKey = $time . '_' . $productKey; + + if (isset($stopFlags[$priceKey])) { + continue; + } + + if (!isset($dayPrices[$priceKey])) { + $dayPrices[$priceKey] = array( + 'rule_date' => $time, + 'website_id' => $ruleData['website_id'], + 'customer_group_id' => $ruleData['customer_group_id'], + 'product_id' => $productId, + 'rule_price' => $this->_calcRuleProductPrice($ruleData), + 'latest_start_date' => $ruleData['from_time'], + 'earliest_end_date' => $ruleData['to_time'], + ); + } + else { + $dayPrices[$priceKey]['rule_price'] = $this->_calcRuleProductPrice( + $ruleData, + $dayPrices[$priceKey] + ); + $dayPrices[$priceKey]['latest_start_date'] = max( + $dayPrices[$priceKey]['latest_start_date'], + $ruleData['from_time'] + ); + $dayPrices[$priceKey]['earliest_end_date'] = min( + $dayPrices[$priceKey]['earliest_end_date'], + $ruleData['to_time'] + ); + } + + if ($ruleData['action_stop']) { + $stopFlags[$priceKey] = true; + } + } + } + + $prevKey = $productKey; + + if (count($dayPrices)>100) { + $this->_saveRuleProductPrices($dayPrices); + $dayPrices = array(); + } + } + $this->_saveRuleProductPrices($dayPrices); + } + $this->_saveRuleProductPrices($dayPrices); + $write->commit(); + + // +// $dayPrices = array(); +// $stopFlags = array(); +// $prevKey = null; +// while ($ruleData = $productsStmt->fetch()) { +// $productId = $ruleData['product_id']; +// $productKey= $productId . '_' . $ruleData['website_id'] . '_' . $ruleData['customer_group_id']; +// +// if ($prevKey && ($prevKey != $productKey)) { +// $stopFlags = array(); +// } +// +// /** +// * Build prices for each day +// */ +// for ($time=$fromDate; $time<=$toDate; $time+=self::SECONDS_IN_DAY) { +// +// if (($ruleData['from_time']==0 || $time >= $ruleData['from_time']) +// && ($ruleData['to_time']==0 || $time <=$ruleData['to_time'])) { +// +// $priceKey = $time . '_' . $productKey; +// +// if (isset($stopFlags[$priceKey])) { +// continue; +// } +// +// if (!isset($dayPrices[$priceKey])) { +// $dayPrices[$priceKey] = array( +// 'rule_date' => $time, +// 'website_id' => $ruleData['website_id'], +// 'customer_group_id' => $ruleData['customer_group_id'], +// 'product_id' => $productId, +// 'rule_price' => $this->_calcRuleProductPrice($ruleData), +// 'latest_start_date' => $ruleData['from_time'], +// 'earliest_end_date' => $ruleData['to_time'], +// ); +// } +// else { +// $dayPrices[$priceKey]['rule_price'] = $this->_calcRuleProductPrice( +// $ruleData, +// $dayPrices[$priceKey] +// ); +// $dayPrices[$priceKey]['latest_start_date'] = max( +// $dayPrices[$priceKey]['latest_start_date'], +// $ruleData['from_time'] +// ); +// $dayPrices[$priceKey]['earliest_end_date'] = min( +// $dayPrices[$priceKey]['earliest_end_date'], +// $ruleData['to_time'] +// ); +// } +// +// if ($ruleData['action_stop']) { +// $stopFlags[$priceKey] = true; +// } +// } +// } +// +// $prevKey = $productKey; +// +// if (count($dayPrices)>100) { +// $this->_saveRuleProductPrices($dayPrices); +// $dayPrices = array(); +// } +// } +// $this->_saveRuleProductPrices($dayPrices); +// $write->commit(); } catch (Exception $e) { $write->rollback(); throw $e; @@ -449,6 +588,7 @@ public function applyAllRulesForDateRange($fromDate=null, $toDate=null, $product 'product_condition' => $productCondition )); $write->delete($this->getTable('catalogrule/affected_product')); + return $this; } diff --git a/app/code/core/Mage/CatalogRule/Model/Observer.php b/app/code/core/Mage/CatalogRule/Model/Observer.php index d475808763..1adedd63e7 100644 --- a/app/code/core/Mage/CatalogRule/Model/Observer.php +++ b/app/code/core/Mage/CatalogRule/Model/Observer.php @@ -89,7 +89,7 @@ public function processFrontFinalPrice($observer) if ($observer->hasDate()) { $date = $observer->getDate(); } else { - $date = Mage::app()->getLocale()->storeDate($storeId); + $date = Mage::app()->getLocale()->storeTimeStamp($storeId); } if ($observer->hasWebsiteId()) { diff --git a/app/code/core/Mage/CatalogRule/Model/Rule.php b/app/code/core/Mage/CatalogRule/Model/Rule.php index f916661670..b2f4a31bd4 100644 --- a/app/code/core/Mage/CatalogRule/Model/Rule.php +++ b/app/code/core/Mage/CatalogRule/Model/Rule.php @@ -138,6 +138,10 @@ public function getMatchingProductIds() { if (empty($this->_productIds)) { $productCollection = Mage::getResourceModel('catalog/product_collection'); + $websiteIds = explode(',', $this->getWebsiteIds()); + if (!empty($websiteIds)) { + $productCollection->addWebsiteFilter($websiteIds); + } $this->setCollectedAttributes(array()); $this->getConditions()->collectValidatedAttributes($productCollection); diff --git a/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php b/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php index 923d85aba9..2bf9bc91b7 100644 --- a/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php +++ b/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php @@ -46,23 +46,35 @@ public function getAttributeObject() return $obj; } + /** + * Add special attributes + * + * @param array $attributes + */ protected function _addSpecialAttributes(array &$attributes) { $attributes['attribute_set_id'] = Mage::helper('catalogrule')->__('Attribute Set'); $attributes['category_ids'] = Mage::helper('catalogrule')->__('Category'); } + /** + * Load attribute options + * + * @return Mage_CatalogRule_Model_Rule_Condition_Product + */ public function loadAttributeOptions() { $productAttributes = Mage::getResourceSingleton('catalog/product') - ->loadAllAttributes()->getAttributesByCode(); + ->loadAllAttributes() + ->getAttributesByCode(); $attributes = array(); - foreach ($productAttributes as $attr) { - if (!$attr->isAllowedForRuleCondition() || !$attr->getIsUsedForPriceRules()) { + foreach ($productAttributes as $attribute) { + /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */ + if (!$attribute->isAllowedForRuleCondition() || !$attribute->getIsUsedForPriceRules()) { continue; } - $attributes[$attr->getAttributeCode()] = $attr->getFrontend()->getLabel(); + $attributes[$attribute->getAttributeCode()] = $attribute->getFrontendLabel(); } $this->_addSpecialAttributes($attributes); @@ -73,6 +85,12 @@ public function loadAttributeOptions() return $this; } + /** + * Retrieve value by option + * + * @param mixed $option + * @return string + */ public function getValueOption($option=null) { if (!$this->getData('value_option')) { @@ -106,6 +124,11 @@ public function getValueOption($option=null) return $this->getData('value_option'.(!is_null($option) ? '/'.$option : '')); } + /** + * Retrieve select option values + * + * @return array + */ public function getValueSelectOptions() { if (!$this->getData('value_select_options')) { @@ -129,6 +152,11 @@ public function getValueSelectOptions() return $this->getData('value_select_options'); } + /** + * Retrieve after element HTML + * + * @return string + */ public function getValueAfterElementHtml() { $html = ''; @@ -145,6 +173,11 @@ public function getValueAfterElementHtml() return $html; } + /** + * Retrieve attribute element + * + * @return Varien_Form_Element_Abstract + */ public function getAttributeElement() { $element = parent::getAttributeElement(); @@ -152,6 +185,12 @@ public function getAttributeElement() return $element; } + /** + * Collect validated attributes + * + * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $productCollection + * @return Mage_CatalogRule_Model_Rule_Condition_Product + */ public function collectValidatedAttributes($productCollection) { $attributes = $this->getRule()->getCollectedAttributes(); @@ -161,6 +200,11 @@ public function collectValidatedAttributes($productCollection) return $this; } + /** + * Retrieve input type + * + * @return string + */ public function getInputType() { if ($this->getAttribute()==='attribute_set_id') { @@ -184,6 +228,11 @@ public function getInputType() } } + /** + * Retrieve value element type + * + * @return string + */ public function getValueElementType() { if ($this->getAttribute()==='attribute_set_id') { @@ -207,6 +256,11 @@ public function getValueElementType() } } + /** + * Retrieve value element + * + * @return Varien_Data_Form_Element_Abstract + */ public function getValueElement() { $element = parent::getValueElement(); @@ -221,6 +275,11 @@ public function getValueElement() return $element; } + /** + * Retrieve value element chooser URL + * + * @return string + */ public function getValueElementChooserUrl() { $url = false; @@ -236,6 +295,11 @@ public function getValueElementChooserUrl() return $url!==false ? Mage::helper('adminhtml')->getUrl($url) : ''; } + /** + * Retrieve Explicit Apply + * + * @return bool + */ public function getExplicitApply() { switch ($this->getAttribute()) { @@ -251,6 +315,12 @@ public function getExplicitApply() return false; } + /** + * Load array + * + * @param array $arr + * @return Mage_CatalogRule_Model_Rule_Condition_Product + */ public function loadArray($arr) { $this->setAttribute(isset($arr['attribute']) ? $arr['attribute'] : false); @@ -264,6 +334,12 @@ public function loadArray($arr) return parent::loadArray($arr); } + /** + * Validate product attrbute value for condition + * + * @param Varien_Object $object + * @return bool + */ public function validate(Varien_Object $object) { $attr = $object->getResource()->getAttribute($this->getAttribute()); diff --git a/app/code/core/Mage/CatalogRule/etc/config.xml b/app/code/core/Mage/CatalogRule/etc/config.xml index ac149249f5..adca8d3265 100644 --- a/app/code/core/Mage/CatalogRule/etc/config.xml +++ b/app/code/core/Mage/CatalogRule/etc/config.xml @@ -28,7 +28,7 @@ - 0.7.5 + 0.7.6 diff --git a/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/mysql4-upgrade-0.7.5-0.7.6.php b/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/mysql4-upgrade-0.7.5-0.7.6.php new file mode 100644 index 0000000000..b6a5a57a69 --- /dev/null +++ b/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/mysql4-upgrade-0.7.5-0.7.6.php @@ -0,0 +1,36 @@ +getConnection()->addKey( + $installer->getTable('catalogrule_product'), + 'sort_order', + array('rule_id', 'from_time','to_time','website_id','customer_group_id','product_id','sort_order'), + 'unique' +); \ No newline at end of file diff --git a/app/code/core/Mage/CatalogSearch/Block/Advanced/Result.php b/app/code/core/Mage/CatalogSearch/Block/Advanced/Result.php index aaf727a69e..a3562329e9 100644 --- a/app/code/core/Mage/CatalogSearch/Block/Advanced/Result.php +++ b/app/code/core/Mage/CatalogSearch/Block/Advanced/Result.php @@ -51,11 +51,15 @@ protected function _prepareLayout() } public function setListOrders() { + $category = Mage::getSingleton('catalog/layer') + ->getCurrentCategory(); + /* @var $category Mage_Catalog_Model_Category */ + + $availableOrders = $category->getAvailableSortByOptions(); + unset($availableOrders['position']); + $this->getChild('search_result_list') - ->setAvailableOrders(array( - 'name' => Mage::helper('catalogsearch')->__('Name'), - 'price'=>Mage::helper('catalogsearch')->__('Price')) - ); + ->setAvailableOrders($availableOrders); } public function setListModes() { diff --git a/app/code/core/Mage/CatalogSearch/Block/Result.php b/app/code/core/Mage/CatalogSearch/Block/Result.php index 9169c99697..9ca3315673 100644 --- a/app/code/core/Mage/CatalogSearch/Block/Result.php +++ b/app/code/core/Mage/CatalogSearch/Block/Result.php @@ -79,7 +79,7 @@ protected function _prepareLayout() /** * Retrieve search list toolbar block * - * @return Mage_Catalog_Block_Product_List_Toolbar + * @return Mage_Catalog_Block_Product_List */ public function getListBlock() { @@ -92,13 +92,20 @@ public function getListBlock() * @return Mage_CatalogSearch_Block_Result */ public function setListOrders() { + $category = Mage::getSingleton('catalog/layer') + ->getCurrentCategory(); + /* @var $category Mage_Catalog_Model_Category */ + $availableOrders = $category->getAvailableSortByOptions(); + unset($availableOrders['position']); + $availableOrders = array_merge(array( + 'relevance' => $this->__('Relevance') + ), $availableOrders); + $this->getListBlock() - ->setAvailableOrders(array( - 'relevance' => $this->__('Relevance'), - 'name' => $this->__('Name'), - 'price' => $this->__('Price'), - )) - ->setDefaultDirection('desc'); + ->setAvailableOrders($availableOrders) + ->setDefaultDirection('desc') + ->setSortBy('relevance'); + return $this; } diff --git a/app/code/core/Mage/CatalogSearch/Helper/Data.php b/app/code/core/Mage/CatalogSearch/Helper/Data.php index 21540b28fd..0c19e426f2 100644 --- a/app/code/core/Mage/CatalogSearch/Helper/Data.php +++ b/app/code/core/Mage/CatalogSearch/Helper/Data.php @@ -109,13 +109,21 @@ public function getQueryText() { if (is_null($this->_queryText)) { $this->_queryText = $this->_getRequest()->getParam($this->getQueryParamName()); - if (is_array($this->_queryText)) { - $this->_queryText = null; - } - $this->_queryText = trim($this->_queryText); - if (Mage::helper('core/string')->strlen($this->_queryText) > $this->getMaxQueryLength()) { - $this->_queryText = Mage::helper('core/string')->substr($this->_queryText, 0, $this->getMaxQueryLength()); - $this->_isMaxLength = true; + if ($this->_queryText === null) { + $this->_queryText = ''; + } else { + if (is_array($this->_queryText)) { + $this->_queryText = null; + } + $this->_queryText = trim($this->_queryText); + if (Mage::helper('core/string')->strlen($this->_queryText) > $this->getMaxQueryLength()) { + $this->_queryText = Mage::helper('core/string')->substr( + $this->_queryText, + 0, + $this->getMaxQueryLength() + ); + $this->_isMaxLength = true; + } } } return $this->_queryText; diff --git a/app/code/core/Mage/CatalogSearch/Model/Advanced.php b/app/code/core/Mage/CatalogSearch/Model/Advanced.php index 66b0af6149..ffeb82b7bb 100644 --- a/app/code/core/Mage/CatalogSearch/Model/Advanced.php +++ b/app/code/core/Mage/CatalogSearch/Model/Advanced.php @@ -129,7 +129,7 @@ public function addFilters($values) } if (false !== $condition) { - $this->addSearchCriteria($attribute, $value); + $this->_addSearchCriteria($attribute, $value); if (in_array($code, $filteredAttributes)) continue; @@ -153,7 +153,14 @@ public function addFilters($values) return $this; } - private function addSearchCriteria($attribute, $value) + /** + * Add data about search criteria to object state + * + * @param Mage_Eav_Model_Entity_Attribute $attribute + * @param mixed $value + * @return Mage_CatalogSearch_Model_Advanced + */ + protected function _addSearchCriteria($attribute, $value) { $name = $attribute->getFrontend()->getLabel(); @@ -197,6 +204,7 @@ private function addSearchCriteria($attribute, $value) } $this->_searchCriterias[] = array('name'=>$name, 'value'=>$value); + return $this; } public function getSearchCriterias() diff --git a/app/code/core/Mage/CatalogSearch/Model/Fulltext/Observer.php b/app/code/core/Mage/CatalogSearch/Model/Fulltext/Observer.php index 48306ecd1f..a55a5f3e6e 100644 --- a/app/code/core/Mage/CatalogSearch/Model/Fulltext/Observer.php +++ b/app/code/core/Mage/CatalogSearch/Model/Fulltext/Observer.php @@ -33,6 +33,16 @@ */ class Mage_CatalogSearch_Model_Fulltext_Observer { + /** + * Retrieve fulltext (indexer) model + * + * @return Mage_CatalogSearch_Model_Fulltext + */ + protected function _getFulltextModel() + { + return Mage::getSingleton('catalogsearch/fulltext'); + } + /** * Update product index when product data updated * @@ -133,4 +143,34 @@ public function refreshStoreIndex($observer) Mage::getModel('catalogsearch/fulltext')->rebuildIndex($storeId); return $this; } + + /** + * Catalog Product mass website update + * + * @param Varien_Event_Observer $observer + * @return Mage_CatalogSearch_Model_Fulltext_Observer + */ + public function catalogProductWebsiteUpdate(Varien_Event_Observer $observer) + { + $websiteIds = $observer->getEvent()->getWebsiteIds(); + $productIds = $observer->getEvent()->getProductIds(); + $actionType = $observer->getEvent()->getAction(); + + foreach ($websiteIds as $websiteId) { + foreach (Mage::app()->getWebsite($websiteId)->getStoreIds() as $storeId) { + if ($actionType == 'remove') { + $this->_getFulltextModel() + ->cleanIndex($storeId, $productIds) + ->resetSearchResults(); + } + elseif ($actionType == 'add') { + $this->_getFulltextModel() + ->rebuildIndex($storeId, $productIds) + ->resetSearchResults(); + } + } + } + + return $this; + } } \ No newline at end of file diff --git a/app/code/core/Mage/CatalogSearch/etc/config.xml b/app/code/core/Mage/CatalogSearch/etc/config.xml index 7cc8cc9f0c..943f235029 100644 --- a/app/code/core/Mage/CatalogSearch/etc/config.xml +++ b/app/code/core/Mage/CatalogSearch/etc/config.xml @@ -133,6 +133,15 @@ + + + + singleton + catalogsearch/fulltext_observer + catalogProductWebsiteUpdate + + + Mage_CatalogSearch_Block diff --git a/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php b/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php index 7a8ebd6147..fa7298bace 100644 --- a/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php +++ b/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php @@ -129,23 +129,16 @@ public function getProductOptions() $options = array(); foreach (explode(',', $optionIds->getValue()) as $optionId) { if ($option = $this->getProduct()->getOptionById($optionId)) { - $formatedValue = ''; - $optionGroup = $option->getGroupByType(); - $optionValue = $this->getItem()->getOptionByCode('option_' . $option->getId())->getValue(); - if ($option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX - || $option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE) { - foreach(split(',', $optionValue) as $value) { - $formatedValue .= $option->getValueById($value)->getTitle() . ', '; - } - $formatedValue = Mage::helper('core/string')->substr($formatedValue, 0, -2); - } elseif ($optionGroup == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) { - $formatedValue = $option->getValueById($optionValue)->getTitle(); - } else { - $formatedValue = $optionValue; - } + + $quoteItemOption = $this->getItem()->getOptionByCode('option_' . $option->getId()); + + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setQuoteItemOption($quoteItemOption); + $options[] = array( 'label' => $option->getTitle(), - 'value' => $this->htmlEscape($formatedValue), + 'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()) ); } } @@ -232,6 +225,10 @@ public function getMessages() public function getFormatedOptionValue($optionValue) { + if (Mage::helper('catalog/product_options')->isHtmlFormattedOptionValue($optionValue)) { + return array('value' => $optionValue); + } + $formateOptionValue = array(); if (is_array($optionValue)) { $_truncatedValue = implode("\n", $optionValue); @@ -250,7 +247,6 @@ public function getFormatedOptionValue($optionValue) $formateOptionValue['value'] = $formateOptionValue['value'] . ' ...'; $optionValue = nl2br($optionValue); $formateOptionValue = array_merge($formateOptionValue, array('full_view' => $optionValue)); - } return $formateOptionValue; diff --git a/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer/Configurable.php b/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer/Configurable.php index 7d0533ac74..ce4d45b6a8 100644 --- a/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer/Configurable.php +++ b/app/code/core/Mage/Checkout/Block/Cart/Item/Renderer/Configurable.php @@ -1,123 +1,124 @@ - - */ -class Mage_Checkout_Block_Cart_Item_Renderer_Configurable extends Mage_Checkout_Block_Cart_Item_Renderer -{ - const CONFIGURABLE_PRODUCT_IMAGE= 'checkout/cart/configurable_product_image'; - const USE_PARENT_IMAGE = 'parent'; - - /** - * Get item configurable product - * - * @return Mage_Catalog_Model_Product - */ - public function getConfigurableProduct() - { - if ($option = $this->getItem()->getOptionByCode('product_type')) { - return $option->getProduct(); - } - return $this->getProduct(); - } - - /** - * Get item configurable child product - * - * @return Mage_Catalog_Model_Product - */ - public function getChildProduct() - { - if ($option = $this->getItem()->getOptionByCode('simple_product')) { - return $option->getProduct(); - } - return $this->getProduct(); - } - - /** - * Get product thumbnail image - * - * @return Mage_Catalog_Model_Product_Image - */ - public function getProductThumbnail() - { - $product = $this->getChildProduct(); - if (!$product || !$product->getData('thumbnail') - || ($product->getData('thumbnail') == 'no_selection') - || (Mage::getStoreConfig(self::CONFIGURABLE_PRODUCT_IMAGE) == self::USE_PARENT_IMAGE)) { - $product = $this->getProduct(); - } - return $this->helper('catalog/image')->init($product, 'thumbnail'); - } - - /** - * Get item product name - * - * @return string - */ - public function getProductName() - { - return $this->getProduct()->getName(); - } - - /** - * Get url to item product - * - * @return string - */ - public function getProductUrl() - { - return $this->getProduct()->getProductUrl(); - } - - /** - * Get selected for configurable product attributes - * - * @return array - */ - public function getProductAttributes() - { - $attributes = $this->getProduct()->getTypeInstance()->getSelectedAttributesInfo(); - return $attributes; - } - - /** - * Get list of all otions for product - * - * @return array - */ - public function getOptionList() - { - $options = array_merge($this->getProductAttributes(), $this->getProductOptions()); - return $options; - } - + + */ +class Mage_Checkout_Block_Cart_Item_Renderer_Configurable extends Mage_Checkout_Block_Cart_Item_Renderer +{ + const CONFIGURABLE_PRODUCT_IMAGE= 'checkout/cart/configurable_product_image'; + const USE_PARENT_IMAGE = 'parent'; + + /** + * Get item configurable product + * + * @return Mage_Catalog_Model_Product + */ + public function getConfigurableProduct() + { + if ($option = $this->getItem()->getOptionByCode('product_type')) { + return $option->getProduct(); + } + return $this->getProduct(); + } + + /** + * Get item configurable child product + * + * @return Mage_Catalog_Model_Product + */ + public function getChildProduct() + { + if ($option = $this->getItem()->getOptionByCode('simple_product')) { + return $option->getProduct(); + } + return $this->getProduct(); + } + + /** + * Get product thumbnail image + * + * @return Mage_Catalog_Model_Product_Image + */ + public function getProductThumbnail() + { + $product = $this->getChildProduct(); + if (!$product || !$product->getData('thumbnail') + || ($product->getData('thumbnail') == 'no_selection') + || (Mage::getStoreConfig(self::CONFIGURABLE_PRODUCT_IMAGE) == self::USE_PARENT_IMAGE)) { + $product = $this->getProduct(); + } + return $this->helper('catalog/image')->init($product, 'thumbnail'); + } + + /** + * Get item product name + * + * @return string + */ + public function getProductName() + { + return $this->getProduct()->getName(); + } + + /** + * Get url to item product + * + * @return string + */ + public function getProductUrl() + { + return $this->getProduct()->getProductUrl(); + } + + /** + * Get selected for configurable product attributes + * + * @return array + */ + public function getProductAttributes() + { + $attributes = $this->getProduct()->getTypeInstance(true) + ->getSelectedAttributesInfo($this->getProduct()); + return $attributes; + } + + /** + * Get list of all otions for product + * + * @return array + */ + public function getOptionList() + { + $options = array_merge($this->getProductAttributes(), $this->getProductOptions()); + return $options; + } + } \ No newline at end of file diff --git a/app/code/core/Mage/Checkout/Block/Cart/Totals.php b/app/code/core/Mage/Checkout/Block/Cart/Totals.php index 6e480ea1c9..8701f26673 100644 --- a/app/code/core/Mage/Checkout/Block/Cart/Totals.php +++ b/app/code/core/Mage/Checkout/Block/Cart/Totals.php @@ -61,7 +61,11 @@ protected function _getTotalRenderer($code) public function renderTotal($total, $area = null, $colspan = 1) { - return $this->_getTotalRenderer($total->getCode()) + $code = $total->getCode(); + if ($total->getAs()) { + $code = $total->getAs(); + } + return $this->_getTotalRenderer($code) ->setTotal($total) ->setColspan($colspan) ->setRenderingArea(is_null($area) ? -1 : $area) diff --git a/app/code/core/Mage/Checkout/Model/Cart.php b/app/code/core/Mage/Checkout/Model/Cart.php index a6e45f2623..d767a355cf 100644 --- a/app/code/core/Mage/Checkout/Model/Cart.php +++ b/app/code/core/Mage/Checkout/Model/Cart.php @@ -222,7 +222,9 @@ public function addProduct($product, $info=null) if (is_string($result)) { $this->getCheckoutSession()->setRedirectUrl($product->getProductUrl()); - $this->getCheckoutSession()->setUseNotice(true); + if ($this->getCheckoutSession()->getUseNotice() === null) { + $this->getCheckoutSession()->setUseNotice(true); + } Mage::throwException($result); } } diff --git a/app/code/core/Mage/Checkout/Model/Type/Multishipping.php b/app/code/core/Mage/Checkout/Model/Type/Multishipping.php index 920a6b79ea..3702040a1b 100644 --- a/app/code/core/Mage/Checkout/Model/Type/Multishipping.php +++ b/app/code/core/Mage/Checkout/Model/Type/Multishipping.php @@ -50,6 +50,9 @@ protected function _init() * reset quote shipping addresses and items */ $this->getQuote()->setIsMultiShipping(true); + if (!$this->getCustomer()->getId()) { + return $this; + } if ($this->getCheckoutSession()->getCheckoutState() === Mage_Checkout_Model_Session::CHECKOUT_STATE_BEGIN) { $this->getCheckoutSession()->setCheckoutState(true); @@ -335,7 +338,7 @@ protected function _prepareOrder(Mage_Sales_Model_Quote_Address $address) foreach ($address->getAllItems() as $item) { $item->setProductType($item->getQuoteItem()->getProductType()) - ->setProductOptions($item->getQuoteItem()->getProduct()->getTypeInstance()->getOrderOptions()); + ->setProductOptions($item->getQuoteItem()->getProduct()->getTypeInstance(true)->getOrderOptions($item->getQuoteItem()->getProduct())); $orderItem = $convertQuote->itemToOrderItem($item); if ($item->getParentItem()) { $orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId())); diff --git a/app/code/core/Mage/Cms/Model/Mysql4/Block/Collection.php b/app/code/core/Mage/Cms/Model/Mysql4/Block/Collection.php index 4d4efa4b69..e7dfaa79c0 100644 --- a/app/code/core/Mage/Cms/Model/Mysql4/Block/Collection.php +++ b/app/code/core/Mage/Cms/Model/Mysql4/Block/Collection.php @@ -62,7 +62,8 @@ public function addStoreFilter($store) 'main_table.block_id = store_table.block_id', array() ) - ->where('store_table.store_id in (?)', array(0, $store)); + ->where('store_table.store_id in (?)', array(0, $store)) + ->group('main_table.block_id'); return $this; } diff --git a/app/code/core/Mage/Cms/Model/Mysql4/Page/Collection.php b/app/code/core/Mage/Cms/Model/Mysql4/Page/Collection.php index e69ccff0db..3afdea5b3b 100644 --- a/app/code/core/Mage/Cms/Model/Mysql4/Page/Collection.php +++ b/app/code/core/Mage/Cms/Model/Mysql4/Page/Collection.php @@ -100,7 +100,8 @@ public function addStoreFilter($store) 'main_table.page_id = store_table.page_id', array() ) - ->where('store_table.store_id in (?)', array(0, $store)); + ->where('store_table.store_id in (?)', array(0, $store)) + ->group('main_table.page_id'); return $this; } diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-install-0.7.0.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-install-0.7.0.php index 732a1f2891..2f371e0d85 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-install-0.7.0.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-install-0.7.0.php @@ -18,10 +18,10 @@ * 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_Cms - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.0-0.7.1.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.0-0.7.1.php index 1bcbb71aab..bfcae22ef2 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.0-0.7.1.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.0-0.7.1.php @@ -18,10 +18,10 @@ * 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_CMS - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.1-0.7.2.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.1-0.7.2.php index a87c5a303d..73b8474b04 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.1-0.7.2.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.1-0.7.2.php @@ -18,10 +18,10 @@ * 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_CMS - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.2-0.7.3.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.2-0.7.3.php index a8cbd303df..0e6d3a24f9 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.2-0.7.3.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.2-0.7.3.php @@ -18,10 +18,10 @@ * 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_CMS - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.4-0.7.5.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.4-0.7.5.php index ece36d0da2..1b57280e61 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.4-0.7.5.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.4-0.7.5.php @@ -18,10 +18,10 @@ * 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_CMS - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.5-0.7.6.php b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.5-0.7.6.php index 98a535c69f..2ebdaae036 100644 --- a/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.5-0.7.6.php +++ b/app/code/core/Mage/Cms/sql/cms_setup/mysql4-upgrade-0.7.5-0.7.6.php @@ -18,10 +18,10 @@ * 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_CMS - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Cms + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ $installer = $this; diff --git a/app/code/core/Mage/Core/Block/Html/Date.php b/app/code/core/Mage/Core/Block/Html/Date.php index 9f3c5c77d9..de6e494423 100644 --- a/app/code/core/Mage/Core/Block/Html/Date.php +++ b/app/code/core/Mage/Core/Block/Html/Date.php @@ -38,7 +38,7 @@ class Mage_Core_Block_Html_Date extends Mage_Core_Block_Template protected function _toHtml() { $html = 'getValue().'" class="'.$this->getClass().'" style="width:100px" /> '; + $html .= 'value="'.$this->getValue().'" class="'.$this->getClass().'" style="width:100px" '.$this->getExtraParams().'/> '; $html .= 'helper('core')->__('Select Date') . '" id="' . $this->getId() . '_trig" />'; diff --git a/app/code/core/Mage/Core/Block/Profiler.php b/app/code/core/Mage/Core/Block/Profiler.php index 2aae44e6d3..82a313a2a9 100644 --- a/app/code/core/Mage/Core/Block/Profiler.php +++ b/app/code/core/Mage/Core/Block/Profiler.php @@ -43,21 +43,21 @@ protected function _toHtml() $out .= '
'; $out .= '
Memory usage: real: '.memory_get_usage(true).', emalloc: '.memory_get_usage().'
'; $out .= ''; - $out .= ''; + $out .= ''; foreach ($timers as $name=>$timer) { $sum = Varien_Profiler::fetch($name,'sum'); $count = Varien_Profiler::fetch($name,'count'); $realmem = Varien_Profiler::fetch($name,'realmem'); $emalloc = Varien_Profiler::fetch($name,'emalloc'); - if ($sum<.0010 && $count<10 && $realmem==0) { + if ($sum<.0010 && $count<10 && $emalloc<10000) { continue; } $out .= '' .'' .'' .'' - .'' .'' + .'' .'' ; } diff --git a/app/code/core/Mage/Core/Controller/Front/Action.php b/app/code/core/Mage/Core/Controller/Front/Action.php index 3f93015164..931534b38d 100644 --- a/app/code/core/Mage/Core/Controller/Front/Action.php +++ b/app/code/core/Mage/Core/Controller/Front/Action.php @@ -54,7 +54,9 @@ public function preDispatch() public function postDispatch() { parent::postDispatch(); - Mage::getSingleton('core/session')->setLastUrl(Mage::getUrl('*/*/*'), array('_current'=>true)); + if (!$this->getFlag('', self::FLAG_NO_START_SESSION )) { + Mage::getSingleton('core/session')->setLastUrl(Mage::getUrl('*/*/*'), array('_current'=>true)); + } return $this; } diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php b/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php index 70523ed633..aff8519c20 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php @@ -29,7 +29,7 @@ class Mage_Core_Controller_Varien_Router_Admin extends Mage_Core_Controller_Vari { public function fetchDefault() { - // set defaults + // set defaults $d = explode('/', (string)Mage::getConfig()->getNode('default/web/default/admin')); $this->getFront()->setDefault(array( 'module' => !empty($d[0]) ? $d[0] : '', @@ -38,111 +38,41 @@ public function fetchDefault() )); } - public function match(Zend_Controller_Request_Http $request) + /** + * dummy call to pass through checking + * + * @return unknown + */ + protected function _beforeModuleMatch() { - $this->fetchDefault(); - - $front = $this->getFront(); - - $p = explode('/', trim($request->getPathInfo(), '/')); - - // get module name - if ($request->getModuleName()) { - $module = $request->getModuleName(); - } else { - $module = !empty($p[0]) ? $p[0] : $this->getFront()->getDefault('module'); - } - if (!$module) { - if (Mage::app()->getStore()->isAdmin()) { - $module = 'admin'; - } else { - return false; - } - } - - $realModule = $this->getModuleByFrontName($module); - if (!$realModule) { - if ($moduleFrontName = array_search($module, $this->_modules)) { - $realModule = $module; - $module = $moduleFrontName; - } else { - return false; - } - } - - $request->setRouteName($this->getRouteByFrontName($module)); + return true; + } + /** + * checking if we installed or not and doing redirect + * + * @return bool + */ + protected function _afterModuleMatch() + { if (!Mage::isInstalled()) { Mage::app()->getFrontController()->getResponse() ->setRedirect(Mage::getUrl('install')) ->sendResponse(); exit; } + return true; + } - $this->_checkShouldBeSecure($request); - - // get controller name - if ($request->getControllerName()) { - $controller = $request->getControllerName(); - } else { - $controller = !empty($p[1]) ? $p[1] : $front->getDefault('controller'); - } - $controllerFileName = $this->getControllerFileName($realModule, $controller); - if (!$this->validateControllerFileName($controllerFileName)) { - $controller = 'index'; - $action = 'noroute'; - $controllerFileName = $this->getControllerFileName($realModule, $controller); - } - - $controllerClassName = $this->getControllerClassName($realModule, $controller); - if (!$controllerClassName) { - $controller = 'index'; - $action = 'noroute'; - $controllerFileName = $this->getControllerFileName($realModule, $controller); - } - - // get action name - if (empty($action)) { - if ($request->getActionName()) { - $action = $request->getActionName(); - } else { - $action = !empty($p[2]) ? $p[2] : $front->getDefault('action'); - } - } - - // include controller file if needed - if (!class_exists($controllerClassName, false)) { - if (!file_exists($controllerFileName)) { - return false; - } - include $controllerFileName; - - if (!class_exists($controllerClassName, false)) { - throw Mage::exception('Mage_Core', Mage::helper('core')->__('Controller file was loaded but class does not exist')); - } - } - // instantiate controller class - $controllerInstance = new $controllerClassName($request, $front->getResponse()); - - if (!$controllerInstance->hasAction($action)) { - return false; - } - - // set values only after all the checks are done - $request->setModuleName($module); - $request->setControllerName($controller); - $request->setActionName($action); - - // set parameters from pathinfo - for ($i=3, $l=sizeof($p); $i<$l; $i+=2) { - $request->setParam($p[$i], isset($p[$i+1]) ? $p[$i+1] : ''); - } - - // dispatch action - $request->setDispatched(true); - $controllerInstance->dispatch($action); - - return true;#$request->isDispatched(); + /** + * We need to have noroute action in this router + * not to pass dispatching to next routers + * + * @return bool + */ + protected function _noRouteShouldBeApplied() + { + return true; } protected function _shouldBeSecure($path) diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php index 56845be250..7e8ddac21e 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php @@ -39,10 +39,32 @@ public function collectRoutes($configArea, $useRouterName) } foreach ($routers as $routerName=>$routerConfig) { $use = (string)$routerConfig->use; - if ($use==$useRouterName) { - $moduleName = (string)$routerConfig->args->module; + if ($use == $useRouterName) { + $modules = array((string)$routerConfig->args->module); + if ($routerConfig->args->modules) { + foreach ($routerConfig->args->modules->children() as $customModule) { + if ($customModule) { + if ($before = $customModule->getAttribute('before')) { + $position = array_search($before, $modules); + if ($position === false) { + $position = 0; + } + array_splice($modules, $position, 0, (string)$customModule); + } elseif ($after = $customModule->getAttribute('after')) { + $position = array_search($after, $modules); + if ($position === false) { + $position = count($modules); + } + array_splice($modules, $position+1, 0, (string)$customModule); + } else { + $modules[] = (string)$customModule; + } + } + } + } + $frontName = (string)$routerConfig->args->frontName; - $this->addModule($frontName, $moduleName, $routerName); + $this->addModule($frontName, $modules, $routerName); } } } @@ -57,11 +79,37 @@ public function fetchDefault() )); } - public function match(Zend_Controller_Request_Http $request) + /** + * checking if this admin if yes then we don't use this router + * + * @return bool + */ + protected function _beforeModuleMatch() { if (Mage::app()->getStore()->isAdmin()) { return false; } + return true; + } + + /** + * dummy call to pass through checking + * + * @return bool + */ + protected function _afterModuleMatch() + { + return true; + } + + public function match(Zend_Controller_Request_Http $request) + { + //checkings before even try to findout that current module + //should use this router + if (!$this->_beforeModuleMatch()) { + return false; + } + $this->fetchDefault(); $front = $this->getFront(); @@ -73,79 +121,115 @@ public function match(Zend_Controller_Request_Http $request) $module = $request->getModuleName(); } else { if(!empty($p[0])) { - $module = $p[0]; + $module = $p[0]; } else { - $module = $this->getFront()->getDefault('module'); + $module = $this->getFront()->getDefault('module'); $request->setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, ''); } } if (!$module) { - return false; - } - $realModule = $this->getModuleByFrontName($module); - if (!$realModule) { - if ($moduleFrontName = array_search($module, $this->_modules)) { - $realModule = $module; - $module = $moduleFrontName; + if (Mage::app()->getStore()->isAdmin()) { + $module = 'admin'; } else { return false; } } - $request->setRouteName($this->getRouteByFrontName($module)); - - // get controller name - if ($request->getControllerName()) { - $controller = $request->getControllerName(); - } else { - if (!empty($p[1])) { - $controller = $p[1]; + /** + * Searching router args by module name from route using it as key + */ + $modules = $this->getModuleByFrontName($module); + + /** + * If we did not found anything we searching exact this module + * name in array values + */ + if ($modules === false) { + if ($moduleFrontName = $this->getModuleByName($module, $this->_modules)) { + $modules = array($module); + $module = $moduleFrontName; } else { - $controller = $front->getDefault('controller'); - $request->setAlias( - Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, - ltrim($request->getOriginalPathInfo(), '/') - ); + return false; } } - $controllerFileName = $this->getControllerFileName($realModule, $controller); - if (!$this->validateControllerFileName($controllerFileName)) { - return false; - } - $controllerClassName = $this->getControllerClassName($realModule, $controller); - if (!$controllerClassName) { + //checkings after we foundout that this router should be used for current module + if (!$this->_afterModuleMatch()) { return false; } - // get action name - if (empty($action)) { - if ($request->getActionName()) { - $action = $request->getActionName(); + /** + * Going through modules to find appropriate controller + */ + $found = false; + foreach ($modules as $realModule) { + $request->setRouteName($this->getRouteByFrontName($module)); + + // get controller name + if ($request->getControllerName()) { + $controller = $request->getControllerName(); } else { - $action = !empty($p[2]) ? $p[2] : $front->getDefault('action'); + if (!empty($p[1])) { + $controller = $p[1]; + } else { + $controller = $front->getDefault('controller'); + $request->setAlias( + Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, + ltrim($request->getOriginalPathInfo(), '/') + ); + } } - } - $this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action); + // get action name + if (empty($action)) { + if ($request->getActionName()) { + $action = $request->getActionName(); + } else { + $action = !empty($p[2]) ? $p[2] : $front->getDefault('action'); + } + } - // include controller file if needed - if (!class_exists($controllerClassName, false)) { - if (!file_exists($controllerFileName)) { - return false; + //checking if this place should be secure + $this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action); + + $controllerClassName = $this->_validateControllerClassName($realModule, $controller); + if (!$controllerClassName) { + continue; } - include $controllerFileName; - if (!class_exists($controllerClassName, false)) { - throw Mage::exception('Mage_Core', Mage::helper('core')->__('Controller file was loaded but class does not exist')); + // instantiate controller class + $controllerInstance = new $controllerClassName($request, $front->getResponse()); + + if (!$controllerInstance->hasAction($action)) { + continue; } - } - // instantiate controller class - $controllerInstance = new $controllerClassName($request, $front->getResponse()); + $found = true; + break; + } - if (!$controllerInstance->hasAction($action)) { - return false; + /** + * if we did not found any siutibul + */ + if (!$found) { + if ($this->_noRouteShouldBeApplied()) { + $controller = 'index'; + $action = 'noroute'; + + $controllerClassName = $this->_validateControllerClassName($realModule, $controller); + if (!$controllerClassName) { + return false; + } + + // instantiate controller class + $controllerInstance = new $controllerClassName($request, $front->getResponse()); + + if (!$controllerInstance->hasAction($action)) { + return false; + } + } else { + return false; + } } // set values only after all the checks are done @@ -162,7 +246,66 @@ public function match(Zend_Controller_Request_Http $request) $request->setDispatched(true); $controllerInstance->dispatch($action); - return true;#$request->isDispatched(); + return true; + } + + /** + * Allow to control if we need to enable norout functionality in current router + * + * @return bool + */ + protected function _noRouteShouldBeApplied() + { + return false; + } + + /** + * Generating and validating class file name, + * class and if evrything ok do include if needed and return of class name + * + * @return mixed + */ + protected function _validateControllerClassName($realModule, $controller) + { + $controllerFileName = $this->getControllerFileName($realModule, $controller); + if (!$this->validateControllerFileName($controllerFileName)) { + return false; + } + + $controllerClassName = $this->getControllerClassName($realModule, $controller); + if (!$controllerClassName) { + return false; + } + + // include controller file if needed + if (!$this->_inludeControllerClass($controllerFileName, $controllerClassName)) { + return false; + } + + return $controllerClassName; + } + + + /** + * Including controller class if checking of existense class before include + * + * @param string $controllerFileName + * @param string $controllerClassName + * @return bool + */ + protected function _inludeControllerClass($controllerFileName, $controllerClassName) + { + if (!class_exists($controllerClassName, false)) { + if (!file_exists($controllerFileName)) { + return false; + } + include $controllerFileName; + + if (!class_exists($controllerClassName, false)) { + throw Mage::exception('Mage_Core', Mage::helper('core')->__('Controller file was loaded but class does not exist')); + } + } + return true; } public function addModule($frontName, $moduleName, $routeName) @@ -180,6 +323,17 @@ public function getModuleByFrontName($frontName) return false; } + public function getModuleByName($moduleName, $modules) + { + foreach ($modules as $module) { + if ($moduleName === $module || (is_array($module) + && $this->getModuleByName($moduleName, $module))) { + return true; + } + } + return false; + } + public function getFrontNameByRoute($routeName) { if (isset($this->_routes[$routeName])) { @@ -195,7 +349,12 @@ public function getRouteByFrontName($frontName) public function getControllerFileName($realModule, $controller) { + $parts = explode('_', $realModule); + $realModule = implode('_', array_splice($parts, 0, 2)); $file = Mage::getModuleDir('controllers', $realModule); + if (count($parts)) { + $file .= DS . implode(DS, $parts); + } $file .= DS.uc_words($controller, DS).'Controller.php'; return $file; } diff --git a/app/code/core/Mage/Core/Helper/Abstract.php b/app/code/core/Mage/Core/Helper/Abstract.php index 5b4bb95fc9..d8435178d8 100644 --- a/app/code/core/Mage/Core/Helper/Abstract.php +++ b/app/code/core/Mage/Core/Helper/Abstract.php @@ -157,13 +157,17 @@ public function htmlEscape($data, $allowedTags = null) } } else { // process single item - if (is_array($allowedTags) and !empty($allowedTags)) { - $allowed = implode('|', $allowedTags); - $result = preg_replace('/<([\/\s\r\n]*)(' . $allowed . ')([\/\s\r\n]*)>/si', '##$1$2$3##', $data); - $result = htmlspecialchars($result); - $result = preg_replace('/##([\/\s\r\n]*)(' . $allowed . ')([\/\s\r\n]*)##/si', '<$1$2$3>', $result); + if (strlen($data)) { + if (is_array($allowedTags) and !empty($allowedTags)) { + $allowed = implode('|', $allowedTags); + $result = preg_replace('/<([\/\s\r\n]*)(' . $allowed . ')([\/\s\r\n]*)>/si', '##$1$2$3##', $data); + $result = htmlspecialchars($result); + $result = preg_replace('/##([\/\s\r\n]*)(' . $allowed . ')([\/\s\r\n]*)##/si', '<$1$2$3>', $result); + } else { + $result = htmlspecialchars($data); + } } else { - $result = htmlspecialchars($data); + $result = $data; } } return $result; @@ -241,7 +245,8 @@ public function urlEncode($url) */ public function urlDecode($url) { - return base64_decode(strtr($url, '-_,', '+/=')); + $url = base64_decode(strtr($url, '-_,', '+/=')); + return Mage::getSingleton('core/url')->sessionUrlVar($url); } /** diff --git a/app/code/core/Mage/Core/Helper/Data.php b/app/code/core/Mage/Core/Helper/Data.php index 9bd2f7d54b..54bf76af4f 100644 --- a/app/code/core/Mage/Core/Helper/Data.php +++ b/app/code/core/Mage/Core/Helper/Data.php @@ -31,7 +31,28 @@ */ class Mage_Core_Helper_Data extends Mage_Core_Helper_Abstract { - protected $_crypt; + /** + * @var Mage_Core_Model_Encryption + */ + protected $_encryptor = null; + + /** + * @return Mage_Core_Model_Encryption + */ + public function getEncryptor() + { + if ($this->_encryptor === null) { + $encryptionModel = (string)Mage::getConfig()->getNode('global/helpers/core/encryption_model'); + if ($encryptionModel) { + $this->_encryptor = new $encryptionModel; + } else { + $this->_encryptor = Mage::getModel('core/encryption'); + } + + $this->_encryptor->setHelper($this); + } + return $this->_encryptor; + } /** * Convert and format price value for current application store @@ -160,8 +181,7 @@ public function encrypt($data) if (!Mage::isInstalled()) { return $data; } - $result = base64_encode($this->_getCrypt()->encrypt((string)$data)); - return $result; + return $this->getEncryptor()->encrypt($data); } /** @@ -175,25 +195,12 @@ public function decrypt($data) if (!Mage::isInstalled()) { return $data; } - $result = trim($this->_getCrypt()->decrypt(base64_decode((string)$data))); - $result = str_replace("\x0", '', $result); - return $result; + return $this->getEncryptor()->decrypt($data); } public function validateKey($key) { - return $this->_getCrypt($key); - } - - protected function _getCrypt($key=null) - { - if (!$this->_crypt) { - if (is_null($key)) { - $key = (string)Mage::getConfig()->getNode('global/crypt/key'); - } - $this->_crypt = Varien_Crypt::factory()->init($key); - } - return $this->_crypt; + return $this->getEncryptor()->validateKey($key); } public function getRandomString($len, $chars=null) @@ -214,25 +221,14 @@ public function getRandomString($len, $chars=null) * @param string $password * @param string|integer|boolean $salt */ - public function getHash($password, $salt=false) + public function getHash($password, $salt = false) { - if (is_integer($salt)) { - $salt = $this->getRandomString($salt); - } - return $salt===false ? md5($password) : md5($salt.$password).':'.$salt; + return $this->getEncryptor()->getHash($password, $salt); } public function validateHash($password, $hash) { - $hashArr = explode(':', $hash); - switch (count($hashArr)) { - case 1: - return md5($password) === $hash; - case 2: - return md5($hashArr[1].$password) === $hashArr[0]; - default: - Mage::throwException('Invalid hash: '.$hash); - } + return $this->getEncryptor()->validateHash($password, $hash); } /** diff --git a/app/code/core/Mage/Core/Helper/Js.php b/app/code/core/Mage/Core/Helper/Js.php index e665a39421..9650c41d68 100644 --- a/app/code/core/Mage/Core/Helper/Js.php +++ b/app/code/core/Mage/Core/Helper/Js.php @@ -36,69 +36,7 @@ class Mage_Core_Helper_Js extends Mage_Core_Helper_Abstract * * @var array */ - protected $_translateData = array(); - - public function __construct() - { - $this->_translateData = array( - 'Please select an option.' => $this->__('Please select an option.'), - 'This is a required field.' => $this->__('This is a required field.'), - 'Please enter a valid number in this field.' => $this->__('Please enter a valid number in this field.'), - 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.' => - $this->__('Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.'), - 'Please use letters only (a-z) in this field.' => $this->__('Please use letters only (a-z) in this field.'), - 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.' => - $this->__('Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.'), - 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.' => - $this->__('Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.'), - 'Please use only letters (a-z) or numbers (0-9) or spaces and # only in this field.' => - $this->__('Please use only letters (a-z) or numbers (0-9) or spaces and # only in this field.'), - 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.' => - $this->__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.'), - 'Please enter a valid date.' => $this->__('Please enter a valid date.'), - 'Please enter a valid email address. For example johndoe@domain.com.' => - $this->__('Please enter a valid email address. For example johndoe@domain.com.'), - 'Please enter 6 or more characters.' => $this->__('Please enter 6 or more characters.'), - 'Please make sure your passwords match.' => $this->__('Please make sure your passwords match.'), - 'Please enter a valid URL. http:// is required' => $this->__('Please enter a valid URL. http:// is required'), - 'Please enter a valid URL. For example http://www.example.com or www.example.com' => - $this->__('Please enter a valid URL. For example http://www.example.com or www.example.com'), - 'Please enter a valid social security number. For example 123-45-6789.' => - $this->__('Please enter a valid social security number. For example 123-45-6789.'), - 'Please enter a valid zip code. For example 90602 or 90602-1234.' => - $this->__('Please enter a valid zip code. For example 90602 or 90602-1234.'), - 'Please enter a valid zip code.' => $this->__('Please enter a valid zip code.'), - 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.' => - $this->__('Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.'), - 'Please enter a valid $ amount. For example $100.00.' => - $this->__('Please enter a valid $ amount. For example $100.00.'), - 'Please select one of the above options.' => $this->__('Please select one of the above options.'), - 'Please select one of the options.' => $this->__('Please select one of the options.'), - 'Please enter a valid number in this field.' => $this->__('Please enter a valid number in this field.'), - 'Please select State/Province.' => $this->__('Please select State/Province.'), - 'Please enter valid password.' => $this->__('Please enter valid password.'), - 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.' => - $this->__('Please enter 6 or more characters. Leading or trailing spaces will be ignored.'), - 'Please use letters only (a-z or A-Z) in this field.' => $this->__('Please use letters only (a-z or A-Z) in this field.'), - 'Please enter a number greater than 0 in this field.' => - $this->__('Please enter a number greater than 0 in this field.'), - 'Please enter a valid credit card number.' => $this->__('Please enter a valid credit card number.'), - 'Please wait, loading...' => $this->__('Please wait, loading...'), - 'Please choose to register or to checkout as a guest' => $this->__('Please choose to register or to checkout as a guest'), - 'Error: Passwords do not match' => $this->__('Error: Passwords do not match'), - 'Your order can not be completed at this time as there is no shipping methods available for it. Please make necessary changes in your shipping address.' => - $this->__('Your order can not be completed at this time as there is no shipping methods available for it. Please make neccessary changes in your shipping address.'), - 'Please specify shipping method.' => $this->__('Please specify shipping method.'), - 'Your order can not be completed at this time as there is no payment methods available for it.' => - $this->__('Your order can not be completed at this time as there is no payment methods available for it.'), - 'Please specify payment method.' => $this->__('Please specify payment method.'), - -//Mage_Rule - - 'Your session has been expired, you will be relogged in now.' => $this->__('Your session has been expired, you will be relogged in now.'), - 'Incorrect credit card expiration date' => $this->__('Incorrect credit card expiration date'), - ); - } + protected $_translateData = null; /** * Retrieve JSON of JS sentences translation @@ -183,6 +121,71 @@ public function getJsSkinUrl($file) */ protected function _getTranslateData() { + if ($this->_translateData ===null) { + $this->_translateData = array( + 'Please select an option.' => $this->__('Please select an option.'), + 'This is a required field.' => $this->__('This is a required field.'), + 'Please enter a valid number in this field.' => $this->__('Please enter a valid number in this field.'), + 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.' => + $this->__('Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.'), + 'Please use letters only (a-z) in this field.' => $this->__('Please use letters only (a-z) in this field.'), + 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.' => + $this->__('Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.'), + 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.' => + $this->__('Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.'), + 'Please use only letters (a-z) or numbers (0-9) or spaces and # only in this field.' => + $this->__('Please use only letters (a-z) or numbers (0-9) or spaces and # only in this field.'), + 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.' => + $this->__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.'), + 'Please enter a valid date.' => $this->__('Please enter a valid date.'), + 'Please enter a valid email address. For example johndoe@domain.com.' => + $this->__('Please enter a valid email address. For example johndoe@domain.com.'), + 'Please enter 6 or more characters.' => $this->__('Please enter 6 or more characters.'), + 'Please make sure your passwords match.' => $this->__('Please make sure your passwords match.'), + 'Please enter a valid URL. http:// is required' => $this->__('Please enter a valid URL. http:// is required'), + 'Please enter a valid URL. For example http://www.example.com or www.example.com' => + $this->__('Please enter a valid URL. For example http://www.example.com or www.example.com'), + 'Please enter a valid social security number. For example 123-45-6789.' => + $this->__('Please enter a valid social security number. For example 123-45-6789.'), + 'Please enter a valid zip code. For example 90602 or 90602-1234.' => + $this->__('Please enter a valid zip code. For example 90602 or 90602-1234.'), + 'Please enter a valid zip code.' => $this->__('Please enter a valid zip code.'), + 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.' => + $this->__('Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.'), + 'Please enter a valid $ amount. For example $100.00.' => + $this->__('Please enter a valid $ amount. For example $100.00.'), + 'Please select one of the above options.' => $this->__('Please select one of the above options.'), + 'Please select one of the options.' => $this->__('Please select one of the options.'), + 'Please enter a valid number in this field.' => $this->__('Please enter a valid number in this field.'), + 'Please select State/Province.' => $this->__('Please select State/Province.'), + 'Please enter valid password.' => $this->__('Please enter valid password.'), + 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.' => + $this->__('Please enter 6 or more characters. Leading or trailing spaces will be ignored.'), + 'Please use letters only (a-z or A-Z) in this field.' => $this->__('Please use letters only (a-z or A-Z) in this field.'), + 'Please enter a number greater than 0 in this field.' => + $this->__('Please enter a number greater than 0 in this field.'), + 'Please enter a valid credit card number.' => $this->__('Please enter a valid credit card number.'), + 'Please wait, loading...' => $this->__('Please wait, loading...'), + 'Please choose to register or to checkout as a guest' => $this->__('Please choose to register or to checkout as a guest'), + 'Error: Passwords do not match' => $this->__('Error: Passwords do not match'), + 'Your order can not be completed at this time as there is no shipping methods available for it. Please make necessary changes in your shipping address.' => + $this->__('Your order can not be completed at this time as there is no shipping methods available for it. Please make necessary changes in your shipping address.'), + 'Please specify shipping method.' => $this->__('Please specify shipping method.'), + 'Your order can not be completed at this time as there is no payment methods available for it.' => + $this->__('Your order can not be completed at this time as there is no payment methods available for it.'), + 'Please specify payment method.' => $this->__('Please specify payment method.'), + + //Mage_Rule + + 'Your session has been expired, you will be relogged in now.' => $this->__('Your session has been expired, you will be relogged in now.'), + 'Incorrect credit card expiration date' => $this->__('Incorrect credit card expiration date'), + ); + foreach ($this->_translateData as $key=>$value) { + if ($key == $value) { + unset($this->_translateData[$key]); + } + } + } return $this->_translateData; } diff --git a/app/code/core/Mage/Core/Helper/Url.php b/app/code/core/Mage/Core/Helper/Url.php index 3aec8c48e3..ca735a6afe 100644 --- a/app/code/core/Mage/Core/Helper/Url.php +++ b/app/code/core/Mage/Core/Helper/Url.php @@ -18,19 +18,22 @@ * 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_Core - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Core + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Core URL helper * + * @category Mage + * @package Mage_Core * @author Magento Core Team */ class Mage_Core_Helper_Url extends Mage_Core_Helper_Abstract { + /** * Retrieve current url * @@ -38,7 +41,7 @@ class Mage_Core_Helper_Url extends Mage_Core_Helper_Abstract */ public function getCurrentUrl() { - return $this->_getUrl('*/*/*', array('_current'=>true, '_use_rewrite'=>true)); + return $this->_getUrl('*/*/*', array('_current' => true, '_use_rewrite' => true)); } /** @@ -77,4 +80,5 @@ protected function _prepareString($string) return $string; } + } diff --git a/app/code/core/Mage/Core/Model/App.php b/app/code/core/Mage/Core/Model/App.php index 39845653af..6c4da35986 100644 --- a/app/code/core/Mage/Core/Model/App.php +++ b/app/code/core/Mage/Core/Model/App.php @@ -399,6 +399,7 @@ protected function _initStores() foreach ($storeCollection as $store) { /* @var $store Mage_Core_Model_Store */ + $store->initConfigCache(); $store->setWebsite($websiteCollection->getItemById($store->getWebsiteId())); $store->setGroup($groupCollection->getItemById($store->getGroupId())); @@ -1127,11 +1128,6 @@ public function addEventArea($area) public function dispatchEvent($eventName, $args) { - $event = new Varien_Event($args); - $event->setName($eventName); - - $observer = new Varien_Event_Observer(); - foreach ($this->_events as $area=>$events) { if (!isset($events[$eventName])) { $eventConfig = $this->getConfig()->getEventConfig($area, $eventName); @@ -1153,9 +1149,13 @@ public function dispatchEvent($eventName, $args) } if (false===$events[$eventName]) { continue; + } else { + $event = new Varien_Event($args); + $event->setName($eventName); + $observer = new Varien_Event_Observer(); } - foreach ($events[$eventName]['observers'] as $obsName=>$obs) { + foreach ($events[$eventName]['observers'] as $obsName=>$obs) { $observer->setData(array('event'=>$event)); Varien_Profiler::start('OBSERVER: '.$obsName); switch ($obs['type']) { diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index eace993716..bfce4904bf 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -36,38 +36,53 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base { - protected $_useCache; + const CACHE_TAG = 'config'; - protected $_options; + /** + * Flag which allow use cache logic + * + * @var bool + */ + protected $_useCache = false; - protected $_classNameCache = array(); + /** + * Instructions for spitting config cache + * array( + * $sectionName => $recursionLevel + * ) + * Recursion level provide availability cache subnodes separatly + * + * @var array + */ + protected $_cacheSections = array( +// 'admin' => 0, +// 'adminhtml' => 0, +// 'crontab' => 0, +// 'default' => 0, +// 'frontend' => 0, +// 'install' => 0, +// 'stores' => 1, +// 'websites' => 1 + ); - protected $_blockClassNameCache = array(); + /** + * Configuration by cached sections + * + * @var array + */ + protected $_cacheLoadedSections = array(); + protected $_options; + protected $_classNameCache = array(); + protected $_blockClassNameCache = array(); protected $_baseDirCache = array(); - protected $_secureUrlCache = array(); - protected $_customEtcDir = null; - protected $_distroServerVars; - protected $_substServerVars; - protected $_resourceModel; - /** - * Retrieve resource model - * - * @return Mage_Core_Store_Mysql4_Config - */ - public function getResourceModel() - { - if (is_null($this->_resourceModel)) { - $this->_resourceModel = Mage::getResourceModel('core/config'); - } - return $this->_resourceModel; - } + protected $_eventAreas; /** * Flag cache for existing or already created directories @@ -77,7 +92,7 @@ public function getResourceModel() protected $_dirExists = array(); /** - * Enter description here... + * Class construct * * @param mixed $sourceData */ @@ -88,7 +103,20 @@ public function __construct($sourceData=null) } /** - * Get configuration options + * Get config resource model + * + * @return Mage_Core_Store_Mysql4_Config + */ + public function getResourceModel() + { + if (is_null($this->_resourceModel)) { + $this->_resourceModel = Mage::getResourceModel('core/config'); + } + return $this->_resourceModel; + } + + /** + * Get configuration options object * * @return Mage_Core_Model_Config_Options */ @@ -108,41 +136,12 @@ public function getOptions() public function init($options=array()) { $this->setCacheChecksum(null); - $saveCache = true; - - $this->_options = new Mage_Core_Model_Config_Options($options); - - $etcDir = $this->getOptions()->getEtcDir(); - - $this->_customEtcDir = $etcDir; - - $localConfigLoaded = $this->loadFile($etcDir.DS.'local.xml'); - - // check if local modules are disabled - $disableLocalModules = (string)$this->getNode('global/disable_local_modules'); - $disableLocalModules = !empty($disableLocalModules) && (('true' === $disableLocalModules) || ('1' === $disableLocalModules)); - - if ($disableLocalModules) { - /** - * Reset include path - */ - $codeDir = $this->getOptions()->getCodeDir(); - $libDir = $this->getOptions()->getLibDir(); - - set_include_path( - // excluded '/app/code/local' - BP . DS . 'app' . DS . 'code' . DS . 'community' . PS . - BP . DS . 'app' . DS . 'code' . DS . 'core' . PS . - BP . DS . 'lib' . PS . - /** - * Problem with concatenate BP . $codeDir - */ - /*BP . $codeDir . DS .'community' . PS . - BP . $codeDir . DS .'core' . PS . - BP . $libDir . PS .*/ - Mage::registry('original_include_path') - ); - } + $this->_cacheLoadedSections = array(); + $this->_options = new Mage_Core_Model_Config_Options($options); + $etcDir = $this->getOptions()->getEtcDir(); + $this->_customEtcDir= $etcDir; + $localConfigLoaded = $this->loadFile($etcDir.DS.'local.xml'); + $disableLocalModules= !$this->_canUseLocalModules(); if (Mage::isInstalled()) { if (Mage::app()->useCache('config')) { @@ -150,6 +149,7 @@ public function init($options=array()) $loaded = $this->loadCache(); Varien_Profiler::stop('mage::app::init::config::load_cache'); if ($loaded) { + $this->_useCache = true; return $this; } } @@ -160,13 +160,8 @@ public function init($options=array()) /** * Load base configuration data */ - Varien_Profiler::start('config/load-base'); - $configFile = $etcDir.DS.'config.xml'; $this->loadFile($configFile); - - Varien_Profiler::stop('config/load-base'); - $this->_loadDeclaredModules($mergeConfig); /** @@ -202,9 +197,7 @@ public function init($options=array()) Varien_Profiler::stop('config/load-local'); - Varien_Profiler::start('config/apply-extends'); $this->applyExtends(); - Varien_Profiler::stop('config/apply-extends'); /** * Load configuration from DB @@ -221,23 +214,229 @@ public function init($options=array()) } if (Mage::app()->useCache('config')) { - Varien_Profiler::start('config/save-cache'); - $this->saveCache(array('config')); - Varien_Profiler::stop('config/save-cache'); + $this->saveCache(array(self::CACHE_TAG)); } return $this; } - public function saveCache($tags=array()) + /** + * Check local modules enable/disable flag + * If local modules are disbled remove local modules path from include dirs + * + * return true if local modules enabled and false if disabled + * + * @return bool + */ + protected function _canUseLocalModules() { + $disableLocalModules = (string)$this->getNode('global/disable_local_modules'); + if (!empty($disableLocalModules)) { + $disableLocalModules = (('true' === $disableLocalModules) || ('1' === $disableLocalModules)); + } else { + $disableLocalModules = false; + } + if ($disableLocalModules) { + set_include_path( + // excluded '/app/code/local' + BP . DS . 'app' . DS . 'code' . DS . 'community' . PS . + BP . DS . 'app' . DS . 'code' . DS . 'core' . PS . + BP . DS . 'lib' . PS . + Mage::registry('original_include_path') + ); + } + + return !$disableLocalModules; + } + + /** + * Save configuration cache + * + * @param array $tags cache tags + * @return Mage_Core_Model_Config + */ + public function saveCache($tags=array()) + { + if (!empty($this->_cacheSections)) { + $xml = clone $this->_xml; + foreach ($this->_cacheSections as $sectionName => $level) { + $this->_saveSectionCache($this->getCacheId(), $sectionName, $xml, $level, $tags); + unset($xml->$sectionName); + } + $xmlStr = $xml->asNiceXml('', false); + $this->_saveCache($xmlStr, $this->getCacheId(), $tags, $this->getCacheLifetime()); + } else { + parent::saveCache($tags); + } - parent::saveCache($tags); + return $this; + } + /** + * Save cache of specified + * + * @param string $idPrefix cache id prefix + * @param string $sectionName + * @param Varien_Simplexml_Element $source + * @param int $recursionLevel + * @return Mage_Core_Model_Config + */ + protected function _saveSectionCache($idPrefix, $sectionName, $source, $recursionLevel=0, $tags=array()) + { + if ($source && $source->$sectionName) { + $cacheId = $idPrefix . '_' . $sectionName; + if ($recursionLevel > 0) { + foreach ($source->$sectionName->children() as $subSectionName => $node) { + $this->_saveSectionCache($cacheId, $subSectionName, $source->$sectionName, $recursionLevel-1, $tags); + } + } + $xmlStr = $source->$sectionName->asNiceXml('', false); + $this->_saveCache($xmlStr, $cacheId, $tags, $this->getCacheLifetime()); + } return $this; } + /** + * Load config section cached data + * + * @param string $sectionName + * @return Varien_Simplexml_Element + */ + protected function _loadSectionCache($sectionName) + { + $cacheId = $this->getCacheId() . '_' . $sectionName; + $xmlString = $this->_loadCache($cacheId); + + /** + * If we can't load section cache (problems with cache storage) + */ + if (!$xmlString) { + $this->_useCache = false; + $this->reinit($this->_options); + return false; + } else { + $xml = simplexml_load_string($xmlString, $this->_elementClass); + return $xml; + } + } + + /** + * Load cached data by identifier + * + * @param string $id + * @return string + */ + protected function _loadCache($id) + { + return Mage::app()->loadCache($id); + } + + /** + * Save cache data + * + * @param string $data + * @param string $id + * @param array $tags + * @param false|int $lifetime + * @return Mage_Core_Model_Config + */ + protected function _saveCache($data, $id, $tags=array(), $lifetime=false) + { + return Mage::app()->saveCache($data, $id, $tags, $lifetime); + } + + /** + * Clear cache data by id + * + * @param string $id + * @return Mage_Core_Model_Config + */ + protected function _removeCache($id) + { + return Mage::app()->removeCache($id); + } + + /** + * Remove configuration cache + * + * @return Mage_Core_Model_Config + */ + public function removeCache() + { + Mage::app()->cleanCache(array(self::CACHE_TAG)); + return parent::removeCache();; + } + + /** + * Get node value from cached section data + * + * @param array $path + * @return Mage_Core_Model_Config + */ + public function getSectionNode($path) + { + $section = $path[0]; + $recursion = $this->_cacheSections[$section]; + $sectioPath = array_slice($path, 0, $recursion+1); + $path = array_slice($path, $recursion+1); + $sectionKey = implode('_', $sectioPath); + + if (!isset($this->_cacheLoadedSections[$sectionKey])) { + Varien_Profiler::start('mage::app::init::config::section::'.$sectionKey); + $this->_cacheLoadedSections[$sectionKey] = $this->_loadSectionCache($sectionKey); + Varien_Profiler::stop('mage::app::init::config::section::'.$sectionKey); + } + + if ($this->_cacheLoadedSections[$sectionKey] === false) { + return false; + } + return $this->_cacheLoadedSections[$sectionKey]->descend($path); + } + + /** + * Returns node found by the $path and scope info + * + * @param string $path + * @param string $scope + * @param string $scopeCode + * @return Mage_Core_Model_Config_Element + */ + public function getNode($path=null, $scope='', $scopeCode=null) + { + if ($scope !== '') { + if (('store' === $scope) || ('website' === $scope)) { + $scope .= 's'; + } + if (('default' !== $scope) && is_int($scopeCode)) { + if ('stores' == $scope) { + $scopeCode = Mage::app()->getStore($scopeCode)->getCode(); + } elseif ('websites' == $scope) { + $scopeCode = Mage::app()->getWebsite($scopeCode)->getCode(); + } else { + Mage::throwException(Mage::helper('core')->__('Unknown scope "%s"', $scope)); + } + } + $path = $scope . ($scopeCode ? '/' . $scopeCode : '' ) . (empty($path) ? '' : '/' . $path); + } + + /** + * Check path cache loading + */ +/* if ($this->_useCache && ($path !== null)) { + $path = explode('/', $path); + $section= $path[0]; + if (isset($this->_cacheSections[$section])) { + $res = $this->getSectionNode($path); + if ($res !== false) { + return $res; + } + } + } +*/ + return parent::getNode($path); + } + /** * Retrive Declared Module file list * @@ -272,6 +471,7 @@ protected function _getDeclaredModuleFiles() $collectModuleFiles['custom'][] = $v; } } + return array_merge( $collectModuleFiles['base'], $collectModuleFiles['mage'], @@ -279,6 +479,12 @@ protected function _getDeclaredModuleFiles() ); } + /** + * Load declared modules configuration + * + * @param $mergeConfig + * @return Mage_Core_Model_Config + */ protected function _loadDeclaredModules($mergeConfig) { $moduleFiles = $this->_getDeclaredModuleFiles(); @@ -333,6 +539,7 @@ protected function _loadDeclaredModules($mergeConfig) $this->extend($sortedConfig); Varien_Profiler::stop('config/load-modules-declaration'); + return $this; } /** @@ -400,21 +607,6 @@ public function getCache() return Mage::app()->getCache(); } - protected function _loadCache($id) - { - return Mage::app()->loadCache($id); - } - - protected function _saveCache($data, $id, $tags=array(), $lifetime=false) - { - return Mage::app()->saveCache($data, $id, $tags, $lifetime); - } - - protected function _removeCache($id) - { - return Mage::app()->removeCache($id); - } - /** * Retrieve temporary directory path * @@ -423,13 +615,13 @@ protected function _removeCache($id) public function getTempVarDir() { return $this->getOptions()->getVarDir(); -// $dir = dirname(Mage::getRoot()).DS.'var'; -// if (!is_writable($dir)) { -// $dir = (!empty($_ENV['TMP']) ? $_ENV['TMP'] : DS.'tmp').DS.'magento'.DS.'var'; -// } -// return $dir; } + /** + * Get default server variables values + * + * @return array + */ public function getDistroServerVars() { if (!$this->_distroServerVars) { @@ -529,6 +721,13 @@ public function getBaseDir($type='base') return $this->getOptions()->getDir($type); } + /** + * Get temporary data directory name + * + * @param string $path + * @param string $type + * @return string + */ public function getVarDir($path=null, $type='var') { $dir = Mage::getBaseDir($type).($path!==null ? DS.$path : ''); @@ -562,6 +761,13 @@ public function createDirIfNotExists($dir) return true; } + /** + * Get module directory by directory type + * + * @param string $type + * @param string $moduleName + * @return string + */ public function getModuleDir($type, $moduleName) { $codePool = (string)$this->getModuleConfig($moduleName)->codePool; @@ -586,38 +792,9 @@ public function getModuleDir($type, $moduleName) } $dir = str_replace('/', DS, $dir); - return $dir; } - /*public function getRouterInstance($routerName='', $singleton=true) - { - $routers = $this->getNode('front/routers'); - if (!empty($routerName)) { - $routerConfig = $routers->$routerName; - } else { - foreach ($routers as $routerConfig) { - if ($routerConfig->is('default')) { - break; - } - } - } - $className = $routerConfig->getClassName(); - $constructArgs = $routerConfig->args; - if (!$className) { - $className = 'Mage_Core_Controller_Front_Router'; - } - if ($singleton) { - $regKey = '_singleton_router/'.$routerName; - if (!Mage::registry($regKey)) { - Mage::register($regKey, new $className($constructArgs)); - } - return Mage::registry($regKey); - } else { - return new $className($constructArgs); - } - }*/ - /** * Load event observers for an area (front, admin) * @@ -723,7 +900,6 @@ public function getGroupedClassName($groupType, $classId, $groupRootNode=null) } $this->_classNameCache[$groupRootNode][$group][$class] = $className; - return $className; } @@ -786,7 +962,10 @@ public function getModelInstance($modelClass='', $constructArguments=array()) { $className = $this->getModelClassName($modelClass); if (class_exists($className)) { - return new $className($constructArguments); + Varien_Profiler::start('CORE::create_object_of::'.$className); + $obj = new $className($constructArguments); + Varien_Profiler::stop('CORE::create_object_of::'.$className); + return $obj; } else { #throw Mage::exception('Mage_Core', Mage::helper('core')->__('Model class does not exist: %s', $modelClass)); return false; @@ -804,6 +983,13 @@ public function getNodeClassInstance($path) } } + /** + * Get resource model object by alias + * + * @param string $modelClass + * @param array $constructArguments + * @return object + */ public function getResourceModelInstance($modelClass='', $constructArguments=array()) { $classArr = explode('/', $modelClass); @@ -839,10 +1025,15 @@ public function getResourceModelInstance($modelClass='', $constructArguments=arr */ public function getResourceConfig($name) { - //return $this->getNode("global/resources/$name"); return $this->_xml->global->resources->{$name}; } + /** + * Get connection configuration + * + * @param string $name + * @return Varien_Simplexml_Element + */ public function getResourceConnectionConfig($name) { $config = $this->getResourceConfig($name); @@ -865,7 +1056,6 @@ public function getResourceConnectionConfig($name) */ public function getResourceTypeConfig($type) { - //return $this->getNode("global/resource/connection/types/$type"); return $this->_xml->global->resource->connection->types->{$type}; } @@ -936,45 +1126,33 @@ public function shouldUrlBeSecure($url) } /** - * Returns node found by the $path and scope info + * Get DB table names prefix * - * @param string $path - * @param string $scope - * @param string $scopeCode - * @return Mage_Core_Model_Config_Element + * @return string */ - public function getNode($path=null, $scope='', $scopeCode=null) - { - if (!empty($scope)) { - if (('store' === $scope) || ('website' === $scope)) { - $scope .= 's'; - } - if (('default' !== $scope) && is_int($scopeCode)) { - if ('stores' == $scope) { - $scopeCode = Mage::app()->getStore($scopeCode)->getCode(); - } elseif ('websites' == $scope) { - $scopeCode = Mage::app()->getWebsite($scopeCode)->getCode(); - } else { - Mage::throwException(Mage::helper('core')->__('Unknown scope "%s"', $scope)); - } - } - $path = $scope . ($scopeCode ? '/' . $scopeCode : '' ) . (empty($path) ? '' : '/' . $path); - } - return parent::getNode($path); - } - public function getTablePrefix() { return $this->_xml->global->resources->db->table_prefix; } + /** + * Get events configuration + * + * @param string $area event area + * @param string $eventName event name + * @return Mage_Core_Model_Config_Element + */ public function getEventConfig($area, $eventName) { - return $this->_xml->{$area}->events->{$eventName}; + //return $this->getNode($area)->events->{$eventName}; + if (!isset($this->_eventAreas[$area])) { + $this->_eventAreas[$area] = $this->getNode($area)->events; + } + return $this->_eventAreas[$area]->{$eventName}; } /** - * Save config value + * Save config value to DB * * @param string $path * @param string $value @@ -990,6 +1168,14 @@ public function saveConfig($path, $value, $scope = 'default', $scopeId = 0) return $this; } + /** + * Delete config value from DB + * + * @param string $path + * @param string $scope + * @param int $scopeId + * @return Mage_Core_Model_Config + */ public function deleteConfig($path, $scope = 'default', $scopeId = 0) { $resource = $this->getResourceModel(); @@ -1012,4 +1198,4 @@ public function getFieldset($name, $root = 'global') } return $rootNode->$name ? $rootNode->$name->children() : null; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Core/Model/Config/Data.php b/app/code/core/Mage/Core/Model/Config/Data.php index b1f899c636..2df0086840 100644 --- a/app/code/core/Mage/Core/Model/Config/Data.php +++ b/app/code/core/Mage/Core/Model/Config/Data.php @@ -57,18 +57,25 @@ public function afterLoad() */ public function isValueChanged() { - $storeCode = $this->getStoreCode(); - $websiteCode = $this->getWebsiteCode(); - $path = $this->getPath(); + return $this->getValue() != $this->getOldValue(); + } - $newValue = $this->getValue(); + /** + * Get old value from existing config + * + * @return string + */ + public function getOldValue() + { + $storeCode = $this->getStoreCode(); + $websiteCode = $this->getWebsiteCode(); + $path = $this->getPath(); if ($websiteCode) { - $oldValue = Mage::app()->getWebsite($websiteCode)->getConfig($path); - } elseif ($storeCode) { - $oldValue = Mage::app()->getStore($storeCode)->getConfig($path); - } else { - $oldValue = (string) Mage::getConfig()->getNode('default/'.$path); + return Mage::app()->getWebsite($websiteCode)->getConfig($path); + } + if ($storeCode) { + return Mage::app()->getStore($storeCode)->getConfig($path); } - return $newValue != $oldValue; + return (string) Mage::getConfig()->getNode('default/' . $path); } } diff --git a/app/code/core/Mage/Core/Model/Convert/Adapter/Interactive.php b/app/code/core/Mage/Core/Model/Convert/Adapter/Interactive.php index b1a52c05a0..4a3146a8be 100644 --- a/app/code/core/Mage/Core/Model/Convert/Adapter/Interactive.php +++ b/app/code/core/Mage/Core/Model/Convert/Adapter/Interactive.php @@ -18,50 +18,50 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Varien - * @package Varien_Convert - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Core + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Convert HTTP adapter * - * @category Varien - * @package Varien_Convert + * @category Mage + * @package Mage_Core * @author Magento Core Team */ - class Mage_Core_Model_Convert_Adapter_Interactive extends Varien_Convert_Adapter_Abstract - { +class Mage_Core_Model_Convert_Adapter_Interactive extends Varien_Convert_Adapter_Abstract +{ - public function load() - { - if (!$_FILES) { + public function load() + { + if (!$_FILES) { ?>
File to upload: setData(file_get_contents($_FILES['io_file']['tmp_name'])); - } + exit; + } + if (!empty($_FILES['io_file']['tmp_name'])) { + //move_uploaded_file($_FILES['io_file']['tmp_name']) + $this->setData(file_get_contents($_FILES['io_file']['tmp_name'])); + } - return $this; - } + return $this; + } - public function save() - { - if ($this->getVars()) { - foreach ($this->getVars() as $key=>$value) { - header($key.': '.$value); - } - } - echo $this->getData(); - return $this; - } + public function save() + { + if ($this->getVars()) { + foreach ($this->getVars() as $key=>$value) { + header($key.': '.$value); + } + } + echo $this->getData(); + return $this; + } - } \ No newline at end of file +} diff --git a/app/code/core/Mage/Core/Model/Cookie.php b/app/code/core/Mage/Core/Model/Cookie.php index 005fd7f4eb..8129085435 100644 --- a/app/code/core/Mage/Core/Model/Cookie.php +++ b/app/code/core/Mage/Core/Model/Cookie.php @@ -39,6 +39,8 @@ class Mage_Core_Model_Cookie const XML_PATH_COOKIE_LIFETIME = 'web/cookie/cookie_lifetime'; const XML_PATH_COOKIE_HTTPONLY = 'web/cookie/cookie_httponly'; + protected $_lifetime; + /** * Store object * @@ -126,13 +128,30 @@ public function getPath() */ public function getLifetime() { - $lifetime = Mage::getStoreConfig(self::XML_PATH_COOKIE_LIFETIME, $this->getStore()); + if (null !== $this->_lifetime) { + $lifetime = $this->_lifetime; + } + else { + $lifetime = Mage::getStoreConfig(self::XML_PATH_COOKIE_LIFETIME, $this->getStore()); + } if (!is_numeric($lifetime)) { $lifetime = 3600; } return $lifetime; } + /** + * Set cookie lifetime + * + * @param int $lifetime + * @return Mage_Core_Model_Cookie + */ + public function setLifetime($lifetime) + { + $this->_lifetime = (int)$lifetime; + return $this; + } + /** * Retrieve use HTTP only flag * diff --git a/app/code/core/Mage/Core/Model/Encryption.php b/app/code/core/Mage/Core/Model/Encryption.php new file mode 100644 index 0000000000..5efacf4e46 --- /dev/null +++ b/app/code/core/Mage/Core/Model/Encryption.php @@ -0,0 +1,157 @@ + + */ +class Mage_Core_Model_Encryption +{ + /** + * @var Varien_Crypt_Mcrypt + */ + protected $_crypt; + /** + * @var Mage_Core_Helper_Data + */ + protected $_helper; + + /** + * Set helper instance + * + * @param Mage_Core_Helper_Data $helper + * @return Mage_Core_Model_Encryption + */ + public function setHelper($helper) + { + $this->_helper = $helper; + return $this; + } + + /** + * Generate a [salted] hash. + * + * $salt can be: + * false - a random will be generated + * integer - a random with specified length will be generated + * string + * + * @param string $password + * @param mixed $salt + * @return string + */ + public function getHash($password, $salt = false) + { + if (is_integer($salt)) { + $salt = $this->_helper->getRandomString($salt); + } + return $salt === false ? $this->hash($password) : $this->hash($salt . $password) . ':' . $salt; + } + + /** + * Hash a string + * + * @param string $data + * @return string + */ + public function hash($data) + { + return md5($data); + } + + /** + * Validate hash against hashing method (with or without salt) + * + * @param string $password + * @param string $hash + * @return bool + * @throws Exception + */ + public function validateHash($password, $hash) + { + $hashArr = explode(':', $hash); + switch (count($hashArr)) { + case 1: + return $this->hash($password) === $hash; + case 2: + return $this->hash($hashArr[1] . $password) === $hashArr[0]; + } + Mage::throwException('Invalid hash.'); + } + + /** + * Instantiate crypt model + * + * @param string $key + * @return Varien_Crypt_Mcrypt + */ + protected function _getCrypt($key = null) + { + if (!$this->_crypt) { + if (null === $key) { + $key = (string)Mage::getConfig()->getNode('global/crypt/key'); + } + $this->_crypt = Varien_Crypt::factory()->init($key); + } + return $this->_crypt; + } + + /** + * Encrypt a string + * + * @param string $data + * @return string + */ + public function encrypt($data) + { + return base64_encode($this->_getCrypt()->encrypt((string)$data)); + } + + /** + * Decrypt a string + * + * @param string $data + * @return string + */ + public function decrypt($data) + { + return str_replace("\x0", '', trim($this->_getCrypt()->decrypt(base64_decode((string)$data)))); + } + + /** + * Return crypt model, instantiate if it is empty + * + * @param string $key + * @return Varien_Crypt_Mcrypt + */ + public function validateKey($key) + { + return $this->_getCrypt($key); + } +} diff --git a/app/code/core/Mage/Core/Model/Flag.php b/app/code/core/Mage/Core/Model/Flag.php index 7f652341dd..9119ab7e98 100644 --- a/app/code/core/Mage/Core/Model/Flag.php +++ b/app/code/core/Mage/Core/Model/Flag.php @@ -20,19 +20,41 @@ * * @category Mage * @package Mage_Core - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ + +/** + * Core Flag model + * + * @category Mage + * @package Mage_Core + * @author Magento Core Team + */ class Mage_Core_Model_Flag extends Mage_Core_Model_Abstract { + /** + * Flag code + * + * @var string + */ protected $_flagCode = null; + /** + * Init resource model + * + */ protected function _construct() { $this->_init('core/flag'); } + /** + * Processing object before save data + * + * @return Mage_Core_Model_Flag + */ protected function _beforeSave() { if (is_null($this->_flagCode)) { @@ -45,6 +67,11 @@ protected function _beforeSave() return parent::_beforeSave(); } + /** + * Retrieve flag data + * + * @return mixed + */ public function getFlagData() { if ($this->hasFlagData()) { @@ -54,11 +81,22 @@ public function getFlagData() } } + /** + * Set flag data + * + * @param mixed $value + * @return Mage_Core_Model_Flag + */ public function setFlagData($value) { return $this->setData('flag_data', serialize($value)); } + /** + * load self (load by flag code) + * + * @return Mage_Core_Model_Flag + */ public function loadSelf() { if (is_null($this->_flagCode)) { diff --git a/app/code/core/Mage/Core/Model/Layout.php b/app/code/core/Mage/Core/Model/Layout.php index e708a1617b..0a8469f7a0 100644 --- a/app/code/core/Mage/Core/Model/Layout.php +++ b/app/code/core/Mage/Core/Model/Layout.php @@ -401,6 +401,7 @@ public function createBlock($type, $name='', array $attributes = array()) try { $block = $this->_getBlockInstance($type, $attributes); } catch (Exception $e) { + Mage::logException($e); return false; } diff --git a/app/code/core/Mage/Core/Model/Locale.php b/app/code/core/Mage/Core/Model/Locale.php index d3163bac83..02b7106764 100644 --- a/app/code/core/Mage/Core/Model/Locale.php +++ b/app/code/core/Mage/Core/Model/Locale.php @@ -70,6 +70,13 @@ class Mage_Core_Model_Locale */ protected $_locale; + /** + * Locale code + * + * @var string + */ + protected $_localeCode; + /** * Emulated locales stack * @@ -81,8 +88,10 @@ class Mage_Core_Model_Locale public function __construct($locale = null) { - Zend_Locale_Data::setCache(Mage::app()->getCache()); - $this->setLocale($locale); + if (empty($locale)) { + $locale = $this->getDefaultLocale(); + } + $this->_localeCode = $locale; } /** @@ -123,7 +132,11 @@ public function getDefaultLocale() public function setLocale($locale = null) { Mage::dispatchEvent('core_locale_set_locale', array('locale'=>$this)); - $this->_locale = new Zend_Locale($this->getDefaultLocale()); + Zend_Locale_Data::setCache(Mage::app()->getCache()); + if ($locale === null) { + $locale = $this->_localeCode; + } + $this->_locale = new Zend_Locale($locale); return $this; } @@ -156,6 +169,8 @@ public function getLocale() { if (!$this->_locale) { $this->setLocale(); + } elseif ($this->_locale->__toString() != $this->_localeCode) { + $this->setLocale($this->_localeCode); } return $this->_locale; @@ -168,7 +183,19 @@ public function getLocale() */ public function getLocaleCode() { - return $this->getLocale()->toString(); + return $this->_localeCode; + } + + /** + * Specify current locale code + * + * @param string $code + * @return Mage_Core_Model_Locale + */ + public function setLocaleCode($code) + { + $this->_localeCode = $code; + return $this; } /** @@ -452,10 +479,26 @@ public function storeDate($store=null, $date=null, $includeTime=false) ->setMinute(0) ->setSecond(0); } -// $date->getTimezone(); return $date; } + /** + * Get store timestamp + * Timstamp will be builded with store timezone settings + * + * @param mixed $store + * @return int + */ + public function storeTimeStamp($store=null) + { + $timezone = Mage::app()->getStore($store)->getConfig(self::XML_PATH_DEFAULT_TIMEZONE); + $currentTimezone = @date_default_timezone_get(); + @date_default_timezone_set($timezone); + $date = date('Y-m-d H:i:s'); + @date_default_timezone_set($currentTimezone); + return strtotime($date); + } + /** * Create Mage_Core_Model_Locale_Currency object for current locale * @@ -596,6 +639,7 @@ public function emulate($storeId) if ($storeId) { $this->_emulatedLocales[] = clone $this->getLocale(); $this->_locale = new Zend_Locale(Mage::getStoreConfig(self::XML_PATH_DEFAULT_LOCALE, $storeId)); + $this->_localeCode = $this->_locale->toString(); Mage::getSingleton('core/translate')->setLocale($this->_locale)->init('frontend', true); } else { @@ -611,6 +655,7 @@ public function revert() { if ($locale = array_pop($this->_emulatedLocales)) { $this->_locale = $locale; + $this->_localeCode = $this->_locale->toString(); Mage::getSingleton('core/translate')->setLocale($this->_locale)->init('adminhtml', true); } } diff --git a/app/code/core/Mage/Core/Model/Message/Abstract.php b/app/code/core/Mage/Core/Model/Message/Abstract.php index 4725465f95..2dba4b25b5 100644 --- a/app/code/core/Mage/Core/Model/Message/Abstract.php +++ b/app/code/core/Mage/Core/Model/Message/Abstract.php @@ -37,7 +37,9 @@ abstract class Mage_Core_Model_Message_Abstract protected $_code; protected $_class; protected $_method; - + protected $_identifier; + protected $_isSticky = false; + public function __construct($type, $code='') { $this->_type = $type; @@ -48,12 +50,12 @@ public function getCode() { return $this->_code; } - + public function getText() { return $this->getCode(); } - + public function getType() { return $this->_type; @@ -63,7 +65,7 @@ public function setClass($class) { $this->_class = $class; } - + public function setMethod($method) { $this->_method = $method; @@ -74,4 +76,48 @@ public function toString() $out = $this->getType().': '.$this->getText(); return $out; } -} \ No newline at end of file + + /** + * Set message identifier + * + * @param string $id + * @return Mage_Core_Model_Message_Abstract + */ + public function setIdentifier($id) + { + $this->_identifier = $id; + return $this; + } + + /** + * Get message identifier + * + * @return string + */ + public function getIdentifier() + { + return $this->_identifier; + } + + /** + * Set message sticky status + * + * @param bool $isSticky + * @return Mage_Core_Model_Message_Abstract + */ + public function setIsSticky($isSticky = true) + { + $this->_isSticky = $isSticky; + return $this; + } + + /** + * Get whether message is sticky + * + * @return bool + */ + public function getIsSticky() + { + return $this->_isSticky; + } +} diff --git a/app/code/core/Mage/Core/Model/Message/Collection.php b/app/code/core/Mage/Core/Model/Message/Collection.php index a36cabcb11..0087b3c8ff 100644 --- a/app/code/core/Mage/Core/Model/Message/Collection.php +++ b/app/code/core/Mage/Core/Model/Message/Collection.php @@ -39,7 +39,8 @@ class Mage_Core_Model_Message_Collection * @var array */ protected $_messages = array(); - + protected $_lastAddedMessage; + /** * Adding new message to collection * @@ -63,20 +64,71 @@ public function addMessage(Mage_Core_Model_Message_Abstract $message) $this->_messages[$message->getType()] = array(); } $this->_messages[$message->getType()][] = $message; + $this->_lastAddedMessage = $message; return $this; } - + /** - * Clear all messages + * Clear all messages except sticky * * @return Mage_Core_Model_Message_Collection */ public function clear() { - $this->_messages = array(); + foreach ($this->_messages as $type => $messages) { + foreach ($messages as $id => $message) { + if (!$message->getIsSticky()) { + unset($this->_messages[$type][$id]); + } + } + if (empty($this->_messages[$type])) { + unset($this->_messages[$type]); + } + } return $this; } - + + /** + * Get last added message if any + * + * @return Mage_Core_Model_Message_Abstract|null + */ + public function getLastAddedMessage() + { + return $this->_lastAddedMessage; + } + + /** + * Get first even message by identifier + * + * @param string $identifier + * @return Mage_Core_Model_Message_Abstract|null + */ + public function getMessageByIdentifier($identifier) + { + foreach ($this->_messages as $type => $messages) { + foreach ($messages as $id => $message) { + if ($identifier === $message->getIdentifier()) { + return $message; + } + } + } + } + + public function deleteMessageByIdentifier($identifier) + { + foreach ($this->_messages as $type => $messages) { + foreach ($messages as $id => $message) { + if ($identifier === $message->getIdentifier()) { + unset($this->_messages[$type][$id]); + } + if (empty($this->_messages[$type])) { + unset($this->_messages[$type]); + } + } + } + } + /** * Retrieve messages collection items * @@ -88,15 +140,15 @@ public function getItems($type=null) if ($type) { return isset($this->_messages[$type]) ? $this->_messages[$type] : array(); } - + $arrRes = array(); foreach ($this->_messages as $messageType => $messages) { $arrRes = array_merge($arrRes, $messages); } - + return $arrRes; } - + /** * Retrieve all messages by type * @@ -107,7 +159,7 @@ public function getItemsByType($type) { return isset($this->_messages[$type]) ? $this->_messages[$type] : array(); } - + /** * Retrieve all error messages * @@ -117,7 +169,7 @@ public function getErrors() { return $this->getItemsByType(Mage_Core_Model_Message::ERROR); } - + public function toString() { $out = ''; @@ -125,10 +177,10 @@ public function toString() foreach ($arrItems as $item) { $out.= $item->toString(); } - + return $out; } - + /** * Retrieve messages count * diff --git a/app/code/core/Mage/Core/Model/Mysql4/Design/Collection.php b/app/code/core/Mage/Core/Model/Mysql4/Design/Collection.php index fdd13014e8..31510016e1 100644 --- a/app/code/core/Mage/Core/Model/Mysql4/Design/Collection.php +++ b/app/code/core/Mage/Core/Model/Mysql4/Design/Collection.php @@ -54,7 +54,7 @@ public function addDateFilter($date = null) public function addStoreFilter($storeId) { $this->getSelect() - ->where('main_table.store_id = ?', $storeId); + ->where('main_table.store_id IN(?)', $storeId); return $this; } diff --git a/app/code/core/Mage/Core/Model/Resource.php b/app/code/core/Mage/Core/Model/Resource.php index 52a59104bb..9e302f3f12 100644 --- a/app/code/core/Mage/Core/Model/Resource.php +++ b/app/code/core/Mage/Core/Model/Resource.php @@ -57,6 +57,8 @@ class Mage_Core_Model_Resource * @var array */ protected $_entities = array(); + + protected $_mappedTableNames; /** * Creates a connection to resource whenever needed @@ -142,12 +144,36 @@ public function getTableName($modelEntity) } else { $tableName = $modelEntity; } + + Mage::dispatchEvent('resource_get_tablename', array('resource' => $this, 'model_entity' => $modelEntity, 'table_name' => $tableName)); + $mappedTableName = $this->getMappedTableName($tableName); + if ($mappedTableName) { + $tableName = $mappedTableName; + } else { + $tablePrefix = (string)Mage::getConfig()->getTablePrefix(); + $tableName = $tablePrefix . $tableName; + } - $tablePrefix = (string)Mage::getConfig()->getTablePrefix(); - return $tablePrefix . $tableName; + return $tableName; } - public function cleanDbRow(&$row) { + public function setMappedTableName($tableName, $mappedName) + { + $this->_mappedTableNames[$tableName] = $mappedName; + return $this; + } + + public function getMappedTableName($tableName) + { + if (isset($this->_mappedTableNames[$tableName])) { + return $this->_mappedTableNames[$tableName]; + } else { + return false; + } + } + + public function cleanDbRow(&$row) + { if (!empty($row) && is_array($row)) { foreach ($row as $key=>&$value) { if (is_string($value) && $value==='0000-00-00 00:00:00') { @@ -158,7 +184,6 @@ public function cleanDbRow(&$row) { return $this; } - public function createConnection($name, $type, $config) { if (!isset($this->_connections[$name])) { @@ -168,7 +193,6 @@ public function createConnection($name, $type, $config) return $this->_connections[$name]; } - public function checkDbConnection() { if (!$this->getConnection('core_read')) { @@ -189,4 +213,3 @@ public function setAutoUpdate($value) } } - diff --git a/app/code/core/Mage/Core/Model/Resource/Setup.php b/app/code/core/Mage/Core/Model/Resource/Setup.php index 877c49b576..f659646485 100644 --- a/app/code/core/Mage/Core/Model/Resource/Setup.php +++ b/app/code/core/Mage/Core/Model/Resource/Setup.php @@ -504,7 +504,6 @@ public function deleteConfigData($path, $scope=null) public function run($sql) { - @set_time_limit(120); $this->_conn->multi_query($sql); return $this; } diff --git a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php index 0c862e47d7..f39eb5ce88 100644 --- a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php +++ b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php @@ -67,6 +67,8 @@ public function start($sessionName=null) break; } + Mage::dispatchEvent('core_session_before_set_cookie_params'); + // set session cookie params session_set_cookie_params( $this->getCookie()->getLifetime(), diff --git a/app/code/core/Mage/Core/Model/Store.php b/app/code/core/Mage/Core/Model/Store.php index b75e9cbc2b..a4d9a38bdb 100644 --- a/app/code/core/Mage/Core/Model/Store.php +++ b/app/code/core/Mage/Core/Model/Store.php @@ -58,6 +58,16 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract protected $_cacheTag = true; + /** + * @var string + */ + protected $_eventPrefix = 'store'; + + /** + * @var string + */ + protected $_eventObject = 'store'; + protected $_priceFilter; /** @@ -74,7 +84,8 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract */ protected $_group; - protected $_configCache = array(); + protected $_configCache = null; + protected $_configCacheBaseNodes = array(); protected $_dirCache = array(); @@ -84,9 +95,24 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract protected $_session; + protected $_isAdminSecure = null; + protected $_isFrontSecure = null; + protected function _construct() { $this->_init('core/store'); + $this->_configCacheBaseNodes = array( + self::XML_PATH_PRICE_SCOPE, + self::XML_PATH_SECURE_BASE_URL, + self::XML_PATH_SECURE_IN_ADMINHTML, + self::XML_PATH_SECURE_IN_FRONTEND, + self::XML_PATH_STORE_IN_URL, + self::XML_PATH_UNSECURE_BASE_URL, + self::XML_PATH_USE_REWRITES, + 'web/unsecure/base_link_url', + 'web/secure/base_link_url', + 'general/locale/code' + ); } /** @@ -146,19 +172,6 @@ public function loadConfig($code) return $this; } - /** - * Retrieve store identifier - * - * @return int - */ -// public function getId() -// { -// if (is_null(parent::getId())) { -// $this->setId($this->getConfig('system/store/id')); -// } -// return parent::getId(); -// } - /** * Retrieve Store code * @@ -176,7 +189,8 @@ public function getCode() * @param string $scope * @return string|null */ - public function getConfig($path) { + public function getConfig($path) + { if (isset($this->_configCache[$path])) { return $this->_configCache[$path]; } @@ -194,6 +208,44 @@ public function getConfig($path) { return $this->_processConfigValue($fullPath, $path, $data); } + /** + * Initialize base store configuration data + * Method provide cache configuration data without loading store config XML + * + * @return Mage_Core_Model_Config + */ + public function initConfigCache() + { + return $this; + /** + * Funtionality related with config separation + */ + if ($this->_configCache === null) { + $code = $this->getCode(); + if ($code) { + if (Mage::app()->useCache('config')) { + $cacheId = 'store_' . $code . '_config_cache'; + $data = Mage::app()->loadCache($cacheId); + if ($data) { + $data = unserialize($data); + } else { + $data = array(); + foreach ($this->_configCacheBaseNodes as $node) { + $data[$node] = $this->getConfig($node); + } + Mage::app()->saveCache( + serialize($data), + $cacheId, + array(self::CACHE_TAG, Mage_Core_Model_Config::CACHE_TAG) + ); + } + $this->_configCache = $data; + } + } + } + return $this; + } + /** * Set config value for CURRENT model * This value don't save in config @@ -388,9 +440,47 @@ protected function _updatePathUseStoreView($url) return $url; } + /** + * Get store identifier + * + * @return int + */ + public function getId() + { + return $this->_getData('store_id'); + } + + /** + * Check if store is admin store + * + * @return unknown + */ public function isAdmin() { - return !$this->getId(); + return $this->getId() == Mage_Core_Model_App::ADMIN_STORE_ID; + } + + + public function isAdminUrlSecure() + { + if ($this->_isAdminSecure === null) { + $this->_isAdminSecure = Mage::getStoreConfigFlag( + Mage_Core_Model_Url::XML_PATH_SECURE_IN_ADMIN, + $this->getId() + ); + } + return $this->_isAdminSecure; + } + + public function isFrontUrlSecure() + { + if ($this->_isFrontSecure === null) { + $this->_isFrontSecure = Mage::getStoreConfigFlag( + Mage_Core_Model_Url::XML_PATH_SECURE_IN_FRONT, + $this->getId() + ); + } + return $this->_isFrontSecure; } public function isCurrentlySecure() @@ -791,4 +881,11 @@ public function resetConfig() return $this; } + +// public function __destruct() +// { +// echo '
';
+//        print_r($this->_configCache);
+//        echo '
'; +// } } diff --git a/app/code/core/Mage/Core/Model/Store/Group.php b/app/code/core/Mage/Core/Model/Store/Group.php index 2ed9daf77c..9371918097 100644 --- a/app/code/core/Mage/Core/Model/Store/Group.php +++ b/app/code/core/Mage/Core/Model/Store/Group.php @@ -35,8 +35,19 @@ class Mage_Core_Model_Store_Group extends Mage_Core_Model_Abstract { const CACHE_TAG = 'store_group'; + protected $_cacheTag = true; + /** + * @var string + */ + protected $_eventPrefix = 'store_group'; + + /** + * @var string + */ + protected $_eventObject = 'store_group'; + /** * Group Store collection array * diff --git a/app/code/core/Mage/Core/Model/Translate.php b/app/code/core/Mage/Core/Model/Translate.php index 4c07c44cf9..aa16ff4556 100644 --- a/app/code/core/Mage/Core/Model/Translate.php +++ b/app/code/core/Mage/Core/Model/Translate.php @@ -116,9 +116,12 @@ public function init($area, $forceReload = false) $this->_translateInline = Mage::getSingleton('core/translate_inline') ->isAllowed($area=='adminhtml' ? 'admin' : null); - if (!$forceReload && ($this->_data = $this->_loadCache())) { + if (!$forceReload) { if ($this->_canUseCache()) { - return $this; + $this->_data = $this->_loadCache(); + if ($this->_data !== false) { + return $this; + } } Mage::app()->removeCache($this->getCacheId()); } diff --git a/app/code/core/Mage/Core/Model/Url.php b/app/code/core/Mage/Core/Model/Url.php index 4ad451dcd2..4651b9a5dd 100644 --- a/app/code/core/Mage/Core/Model/Url.php +++ b/app/code/core/Mage/Core/Model/Url.php @@ -254,10 +254,12 @@ public function getSecure() return $this->getData('secure'); } - if ($this->getStore()->isAdmin() && !Mage::getStoreConfigFlag(self::XML_PATH_SECURE_IN_ADMIN, $this->getStore()->getId())) { + $store = $this->getStore(); + + if ($store->isAdmin() && !$store->isAdminUrlSecure()) { //!Mage::getStoreConfigFlag(self::XML_PATH_SECURE_IN_ADMIN, $this->getStore()->getId()) return false; } - if (!$this->getStore()->isAdmin() && !Mage::getStoreConfigFlag(self::XML_PATH_SECURE_IN_FRONT)) { + if (!$store->isAdmin() && !$store->isFrontUrlSecure()) {//!Mage::getStoreConfigFlag(self::XML_PATH_SECURE_IN_FRONT return false; } @@ -266,7 +268,7 @@ public function getSecure() $pathSecure = Mage::getConfig()->shouldUrlBeSecure('/'.$this->getActionPath()); $this->setData('secure', $pathSecure); } else { - $this->setData('secure', Mage::app()->getStore()->isCurrentlySecure()); + $this->setData('secure', $store->isCurrentlySecure()); } } return $this->getData('secure'); @@ -763,9 +765,7 @@ public function getUrl($routePath=null, $routeParams=null) $query = $routeParams['_query']; unset($routeParams['_query']); } - $url = $this->getRouteUrl($routePath, $routeParams); - /** * Apply query params, need call after getRouteUrl for rewrite _current values */ @@ -789,6 +789,7 @@ public function getUrl($routePath=null, $routeParams=null) if ($this->getFragment()) { $url .= '#'.$this->getFragment(); } + return $this->escape($url); } diff --git a/app/code/core/Mage/Core/Model/Website.php b/app/code/core/Mage/Core/Model/Website.php index da88d529d7..57780820e0 100644 --- a/app/code/core/Mage/Core/Model/Website.php +++ b/app/code/core/Mage/Core/Model/Website.php @@ -1,512 +1,522 @@ - - */ - -class Mage_Core_Model_Website extends Mage_Core_Model_Abstract -{ - const CACHE_TAG = 'website'; - protected $_cacheTag = true; - - /** - * Cache configuration array - * - * @var array - */ - protected $_configCache = array(); - - /** - * Website Group Coleection array - * - * @var array - */ - protected $_groups; - - /** - * Website group ids array - * - * @var array - */ - protected $_groupIds = array(); - - /** - * The number of groups in a website - * - * @var int - */ - protected $_groupsCount; - - /** - * Website Store collection array - * - * @var array - */ - protected $_stores; - - /** - * Website store ids array - * - * @var array - */ - protected $_storeIds = array(); - - /** - * Website store codes array - * - * @var array - */ - protected $_storeCodes = array(); - - /** - * The number of stores in a website - * - * @var int - */ - protected $_storesCount = 0; - - /** - * Website default group - * - * @var Mage_Core_Model_Store_Group - */ - protected $_defaultGroup; - - /** - * Website default store - * - * @var Mage_Core_Model_Store - */ - protected $_defaultStore; - - /** - * is can delete website - * - * @var bool - */ - protected $_isCanDelete; - - /** - * init model - * - */ - protected function _construct() - { - $this->_init('core/website'); - } - - /** - * Custom load - * - * @param int|string $id - * @param string $field - * @return Mage_Core_Model_Website - */ - public function load($id, $field = null) - { - if (!is_numeric($id) && is_null($field)) { - $this->_getResource()->load($this, $id, 'code'); - return $this; - } - return parent::load($id, $field); - } - - /** - * Load website configuration - * - * @param string $code - * @return Mage_Core_Model_Website - */ - public function loadConfig($code) - { - if (!Mage::getConfig()->getNode('websites')) { - return $this; - } - if (is_numeric($code)) { - foreach (Mage::getConfig()->getNode('websites')->children() as $websiteCode=>$website) { - if ((int)$website->system->website->id==$code) { - $code = $websiteCode; - break; - } - } - } else { - $website = Mage::getConfig()->getNode('websites/'.$code); - } - if (!empty($website)) { - $this->setCode($code); - $id = (int)$website->system->website->id; - $this->setId($id)->setStoreId($id); - } - return $this; - } - - /** - * Get website config data - * - * @param string $path - * @return mixed - */ - public function getConfig($path) { - if (!isset($this->_configCache[$path])) { - - $config = Mage::getConfig()->getNode('websites/'.$this->getCode().'/'.$path); - if (!$config) { - return false; - #throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid websites configuration path: %s', $path)); - } - if (!$config->children()) { - $value = (string)$config; - } else { - $value = array(); - foreach ($config->children() as $k=>$v) { - $value[$k] = $v; - } - } - $this->_configCache[$path] = $value; - } - return $this->_configCache[$path]; - } - - /** - * Load group collection and set internal data - * - */ - protected function _loadGroups() - { - $this->_groups = array(); - $this->_groupsCount = 0; - foreach ($this->getGroupCollection() as $group) { - $this->_groups[$group->getId()] = $group; - $this->_groupIds[$group->getId()] = $group->getId(); - if ($this->getDefaultGroupId() == $group->getId()) { - $this->_defaultGroup = $group; - } - $this->_groupsCount ++; - } - } - - /** - * Set website groups - * - * @param array $groups - */ - public function setGroups($groups) - { - $this->_groups = array(); - $this->_groupsCount = 0; - foreach ($groups as $group) { - $this->_groups[$group->getId()] = $group; - $this->_groupIds[$group->getId()] = $group->getId(); - if ($this->getDefaultGroupId() == $group->getId()) { - $this->_defaultGroup = $group; - } - $this->_groupsCount ++; - } - return $this; - } - - /** - * Retrieve new (not loaded) Group collection object with website filter - * - * @return Mage_Core_Model_Mysql4_Store_Group_Collection - */ - public function getGroupCollection() - { - return Mage::getModel('core/store_group') - ->getCollection() - ->addWebsiteFilter($this->getId()); - } - - /** - * Retrieve website groups - * - * @return array - */ - public function getGroups() - { - if (is_null($this->_groups)) { - $this->_loadGroups(); - } - return $this->_groups; - } - - /** - * Retrieve website group ids - * - * @return array - */ - public function getGroupIds() - { - if (is_null($this->_groups)) { - $this->_loadGroups(); - } - return $this->_groupIds; - } - - /** - * Retrieve number groups in a website - * - * @return int - */ - public function getGroupsCount() - { - if (is_null($this->_groups)) { - $this->_loadGroups(); - } - return $this->_groupsCount; - } - - /** - * Retrieve default group model - * - * @return Mage_Core_Model_Store_Group - */ - public function getDefaultGroup() - { - if (!$this->getDefaultGroupId()) { - return false; - } - if (is_null($this->_groups)) { - $this->_loadGroups(); - } - return $this->_defaultGroup; - } - - /** - * Load store collection and set internal data - * - */ - protected function _loadStores() - { - $this->_stores = array(); - $this->_storesCount = 0; - foreach ($this->getStoreCollection() as $store) { - $this->_stores[$store->getId()] = $store; - $this->_storeIds[$store->getId()] = $store->getId(); - $this->_storeCodes[$store->getId()] = $store->getCode(); - if ($this->getDefaultGroup() && $this->getDefaultGroup()->getDefaultStoreId() == $store->getId()) { - $this->_defaultStore = $store; - } - $this->_storesCount ++; - } - } - - /** - * Set website stores - * - * @param array $stores - */ - public function setStores($stores) - { - $this->_stores = array(); - $this->_storesCount = 0; - foreach ($stores as $store) { - $this->_stores[$store->getId()] = $store; - $this->_storeIds[$store->getId()] = $store->getId(); - $this->_storeCodes[$store->getId()] = $store->getCode(); - if ($this->getDefaultGroup() && $this->getDefaultGroup()->getDefaultStoreId() == $store->getId()) { - $this->_defaultStore = $store; - } - $this->_storesCount ++; - } - } - - /** - * Retrieve new (not loaded) Store collection object with website filter - * - * @return Mage_Core_Model_Mysql4_Store_Collection - */ - public function getStoreCollection() - { - return Mage::getModel('core/store') - ->getCollection() - ->addWebsiteFilter($this->getId()); - } - - /** - * Retrieve wersite store objects - * - * @return array - */ - public function getStores() - { - if (is_null($this->_stores)) { - $this->_loadStores(); - } - return $this->_stores; - } - - /** - * Retrieve website store ids - * - * @return array - */ - public function getStoreIds() - { - if (is_null($this->_stores)) { - $this->_loadStores(); - } - return $this->_storeIds; - } - - /** - * Retrieve website store codes - * - * @return array - */ - public function getStoreCodes() - { - if (is_null($this->_stores)) { - $this->_loadStores(); - } - return $this->_storeCodes; - } - - /** - * Retrieve number stores in a website - * - * @return int - */ - public function getStoresCount() - { - if (is_null($this->_stores)) { - $this->_loadStores(); - } - return $this->_storesCount; - } - - /** - * is can delete website - * - * @return bool - */ - public function isCanDelete() - { - if (!$this->getId()) { - return false; - } - if (is_null($this->_isCanDelete)) { - $this->_isCanDelete = (Mage::getModel('core/website')->getCollection()->getSize() > 2) - && !$this->getIsDefault(); - } - return $this->_isCanDelete; - } - - /** - * Retrieve unique website-group-store key for collection with groups and stores - * - * @return string - */ - public function getWebsiteGroupStore() - { - return join('-', array($this->getWebsiteId(), $this->getGroupId(), $this->getStoreId())); - } - - public function getDefaultGroupId() - { - return $this->_getData('default_group_id'); - } - - public function getCode() - { - return $this->_getData('code'); - } - - protected function _beforeDelete() - { - $this->_protectFromNonAdmin(); - return parent::_beforeDelete(); - } - - /** - * rewrite in order to clear configuration cache - * - * @return Mage_Core_Model_Website - */ - protected function _afterDelete() - { - parent::_afterDelete(); - Mage::getConfig()->removeCache(); - return $this; - } - - /** - * Retrieve website base currency code - * - * @return string - */ - public function getBaseCurrencyCode() - { - if ($this->getConfig(Mage_Core_Model_Store::XML_PATH_PRICE_SCOPE) == Mage_Core_Model_Store::PRICE_SCOPE_GLOBAL) { - return Mage::app()->getBaseCurrencyCode(); - } else { - return $this->getConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE); - } - } - - /** - * Retrieve website base currency - * - * @return Mage_Directory_Model_Currency - */ - public function getBaseCurrency() - { - $currency = $this->getData('base_currency'); - if (is_null($currency)) { - $currency = Mage::getModel('directory/currency')->load($this->getBaseCurrencyCode()); - $this->setData('base_currency', $currency); - } - return $currency; - } - - /** - * Retrieve Default Website Store or null - * - * @return Mage_Core_Model_Store - */ - public function getDefaultStore() - { - // init stores if not loaded - $this->getStores(); - return $this->_defaultStore; - } - - /** - * Retrieve default stores select object - * Select fields website_id, store_id - * - * @param $withDefault include/exclude default admin website - * @return Varien_Db_Select - */ - public function getDefaultStoresSelect($withDefault = false) { - return $this->getResource()->getDefaultStoresSelect($withDefault); - } -} + + */ + +class Mage_Core_Model_Website extends Mage_Core_Model_Abstract +{ + const CACHE_TAG = 'website'; + protected $_cacheTag = true; + + /** + * @var string + */ + protected $_eventPrefix = 'website'; + + /** + * @var string + */ + protected $_eventObject = 'website'; + + /** + * Cache configuration array + * + * @var array + */ + protected $_configCache = array(); + + /** + * Website Group Coleection array + * + * @var array + */ + protected $_groups; + + /** + * Website group ids array + * + * @var array + */ + protected $_groupIds = array(); + + /** + * The number of groups in a website + * + * @var int + */ + protected $_groupsCount; + + /** + * Website Store collection array + * + * @var array + */ + protected $_stores; + + /** + * Website store ids array + * + * @var array + */ + protected $_storeIds = array(); + + /** + * Website store codes array + * + * @var array + */ + protected $_storeCodes = array(); + + /** + * The number of stores in a website + * + * @var int + */ + protected $_storesCount = 0; + + /** + * Website default group + * + * @var Mage_Core_Model_Store_Group + */ + protected $_defaultGroup; + + /** + * Website default store + * + * @var Mage_Core_Model_Store + */ + protected $_defaultStore; + + /** + * is can delete website + * + * @var bool + */ + protected $_isCanDelete; + + /** + * init model + * + */ + protected function _construct() + { + $this->_init('core/website'); + } + + /** + * Custom load + * + * @param int|string $id + * @param string $field + * @return Mage_Core_Model_Website + */ + public function load($id, $field = null) + { + if (!is_numeric($id) && is_null($field)) { + $this->_getResource()->load($this, $id, 'code'); + return $this; + } + return parent::load($id, $field); + } + + /** + * Load website configuration + * + * @param string $code + * @return Mage_Core_Model_Website + */ + public function loadConfig($code) + { + if (!Mage::getConfig()->getNode('websites')) { + return $this; + } + if (is_numeric($code)) { + foreach (Mage::getConfig()->getNode('websites')->children() as $websiteCode=>$website) { + if ((int)$website->system->website->id==$code) { + $code = $websiteCode; + break; + } + } + } else { + $website = Mage::getConfig()->getNode('websites/'.$code); + } + if (!empty($website)) { + $this->setCode($code); + $id = (int)$website->system->website->id; + $this->setId($id)->setStoreId($id); + } + return $this; + } + + /** + * Get website config data + * + * @param string $path + * @return mixed + */ + public function getConfig($path) { + if (!isset($this->_configCache[$path])) { + + $config = Mage::getConfig()->getNode('websites/'.$this->getCode().'/'.$path); + if (!$config) { + return false; + #throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid websites configuration path: %s', $path)); + } + if ($config->hasChildren()) { + $value = array(); + foreach ($config->children() as $k=>$v) { + $value[$k] = $v; + } + } else { + $value = (string)$config; + } + $this->_configCache[$path] = $value; + } + return $this->_configCache[$path]; + } + + /** + * Load group collection and set internal data + * + */ + protected function _loadGroups() + { + $this->_groups = array(); + $this->_groupsCount = 0; + foreach ($this->getGroupCollection() as $group) { + $this->_groups[$group->getId()] = $group; + $this->_groupIds[$group->getId()] = $group->getId(); + if ($this->getDefaultGroupId() == $group->getId()) { + $this->_defaultGroup = $group; + } + $this->_groupsCount ++; + } + } + + /** + * Set website groups + * + * @param array $groups + */ + public function setGroups($groups) + { + $this->_groups = array(); + $this->_groupsCount = 0; + foreach ($groups as $group) { + $this->_groups[$group->getId()] = $group; + $this->_groupIds[$group->getId()] = $group->getId(); + if ($this->getDefaultGroupId() == $group->getId()) { + $this->_defaultGroup = $group; + } + $this->_groupsCount ++; + } + return $this; + } + + /** + * Retrieve new (not loaded) Group collection object with website filter + * + * @return Mage_Core_Model_Mysql4_Store_Group_Collection + */ + public function getGroupCollection() + { + return Mage::getModel('core/store_group') + ->getCollection() + ->addWebsiteFilter($this->getId()); + } + + /** + * Retrieve website groups + * + * @return array + */ + public function getGroups() + { + if (is_null($this->_groups)) { + $this->_loadGroups(); + } + return $this->_groups; + } + + /** + * Retrieve website group ids + * + * @return array + */ + public function getGroupIds() + { + if (is_null($this->_groups)) { + $this->_loadGroups(); + } + return $this->_groupIds; + } + + /** + * Retrieve number groups in a website + * + * @return int + */ + public function getGroupsCount() + { + if (is_null($this->_groups)) { + $this->_loadGroups(); + } + return $this->_groupsCount; + } + + /** + * Retrieve default group model + * + * @return Mage_Core_Model_Store_Group + */ + public function getDefaultGroup() + { + if (!$this->getDefaultGroupId()) { + return false; + } + if (is_null($this->_groups)) { + $this->_loadGroups(); + } + return $this->_defaultGroup; + } + + /** + * Load store collection and set internal data + * + */ + protected function _loadStores() + { + $this->_stores = array(); + $this->_storesCount = 0; + foreach ($this->getStoreCollection() as $store) { + $this->_stores[$store->getId()] = $store; + $this->_storeIds[$store->getId()] = $store->getId(); + $this->_storeCodes[$store->getId()] = $store->getCode(); + if ($this->getDefaultGroup() && $this->getDefaultGroup()->getDefaultStoreId() == $store->getId()) { + $this->_defaultStore = $store; + } + $this->_storesCount ++; + } + } + + /** + * Set website stores + * + * @param array $stores + */ + public function setStores($stores) + { + $this->_stores = array(); + $this->_storesCount = 0; + foreach ($stores as $store) { + $this->_stores[$store->getId()] = $store; + $this->_storeIds[$store->getId()] = $store->getId(); + $this->_storeCodes[$store->getId()] = $store->getCode(); + if ($this->getDefaultGroup() && $this->getDefaultGroup()->getDefaultStoreId() == $store->getId()) { + $this->_defaultStore = $store; + } + $this->_storesCount ++; + } + } + + /** + * Retrieve new (not loaded) Store collection object with website filter + * + * @return Mage_Core_Model_Mysql4_Store_Collection + */ + public function getStoreCollection() + { + return Mage::getModel('core/store') + ->getCollection() + ->addWebsiteFilter($this->getId()); + } + + /** + * Retrieve wersite store objects + * + * @return array + */ + public function getStores() + { + if (is_null($this->_stores)) { + $this->_loadStores(); + } + return $this->_stores; + } + + /** + * Retrieve website store ids + * + * @return array + */ + public function getStoreIds() + { + if (is_null($this->_stores)) { + $this->_loadStores(); + } + return $this->_storeIds; + } + + /** + * Retrieve website store codes + * + * @return array + */ + public function getStoreCodes() + { + if (is_null($this->_stores)) { + $this->_loadStores(); + } + return $this->_storeCodes; + } + + /** + * Retrieve number stores in a website + * + * @return int + */ + public function getStoresCount() + { + if (is_null($this->_stores)) { + $this->_loadStores(); + } + return $this->_storesCount; + } + + /** + * is can delete website + * + * @return bool + */ + public function isCanDelete() + { + if (!$this->getId()) { + return false; + } + if (is_null($this->_isCanDelete)) { + $this->_isCanDelete = (Mage::getModel('core/website')->getCollection()->getSize() > 2) + && !$this->getIsDefault(); + } + return $this->_isCanDelete; + } + + /** + * Retrieve unique website-group-store key for collection with groups and stores + * + * @return string + */ + public function getWebsiteGroupStore() + { + return join('-', array($this->getWebsiteId(), $this->getGroupId(), $this->getStoreId())); + } + + public function getDefaultGroupId() + { + return $this->_getData('default_group_id'); + } + + public function getCode() + { + return $this->_getData('code'); + } + + protected function _beforeDelete() + { + $this->_protectFromNonAdmin(); + return parent::_beforeDelete(); + } + + /** + * rewrite in order to clear configuration cache + * + * @return Mage_Core_Model_Website + */ + protected function _afterDelete() + { + parent::_afterDelete(); + Mage::getConfig()->removeCache(); + return $this; + } + + /** + * Retrieve website base currency code + * + * @return string + */ + public function getBaseCurrencyCode() + { + if ($this->getConfig(Mage_Core_Model_Store::XML_PATH_PRICE_SCOPE) == Mage_Core_Model_Store::PRICE_SCOPE_GLOBAL) { + return Mage::app()->getBaseCurrencyCode(); + } else { + return $this->getConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE); + } + } + + /** + * Retrieve website base currency + * + * @return Mage_Directory_Model_Currency + */ + public function getBaseCurrency() + { + $currency = $this->getData('base_currency'); + if (is_null($currency)) { + $currency = Mage::getModel('directory/currency')->load($this->getBaseCurrencyCode()); + $this->setData('base_currency', $currency); + } + return $currency; + } + + /** + * Retrieve Default Website Store or null + * + * @return Mage_Core_Model_Store + */ + public function getDefaultStore() + { + // init stores if not loaded + $this->getStores(); + return $this->_defaultStore; + } + + /** + * Retrieve default stores select object + * Select fields website_id, store_id + * + * @param $withDefault include/exclude default admin website + * @return Varien_Db_Select + */ + public function getDefaultStoresSelect($withDefault = false) { + return $this->getResource()->getDefaultStoresSelect($withDefault); + } +} diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml index 3f90c0cb3e..26c47f672e 100644 --- a/app/code/core/Mage/Core/etc/config.xml +++ b/app/code/core/Mage/Core/etc/config.xml @@ -40,6 +40,7 @@
Code ProfilerTimeCntRealMemEmalloc
Code ProfilerTimeCntEmallocRealMem
'.$name.''.number_format($sum,4).''.$count.''.number_format($realmem).''.number_format($emalloc).''.number_format($realmem).'
core_store_group
core_store
core_config_field
+ core_config_data
core_email_template
core_translate
core_session
@@ -60,6 +61,11 @@ Mage_Core_Block + + + Mage_Core_Model_Encryption + + @@ -224,7 +230,7 @@ 3600 1 - + 1 1 @@ -241,6 +247,9 @@ 0 + + 1 + diff --git a/app/code/core/Mage/Core/etc/system.xml b/app/code/core/Mage/Core/etc/system.xml index 825d6eaa92..67e32bfbec 100644 --- a/app/code/core/Mage/Core/etc/system.xml +++ b/app/code/core/Mage/Core/etc/system.xml @@ -776,6 +776,26 @@ + + + text + 35 + 1 + 0 + 0 + + + + select + adminhtml/system_config_source_yesno + adminhtml/system_config_backend_admin_usesecretkey + 1 + 1 + 0 + 0 + + + diff --git a/app/code/core/Mage/Customer/Block/Account/Dashboard/Info.php b/app/code/core/Mage/Customer/Block/Account/Dashboard/Info.php index 55ae0d5cc6..8a875c1aa4 100644 --- a/app/code/core/Mage/Customer/Block/Account/Dashboard/Info.php +++ b/app/code/core/Mage/Customer/Block/Account/Dashboard/Info.php @@ -71,7 +71,6 @@ public function getIsSubscribed() /** * Newsletter module availability * - * @param none * @return boolean */ public function isNewsletterEnabled() diff --git a/app/code/core/Mage/Customer/Block/Form/Register.php b/app/code/core/Mage/Customer/Block/Form/Register.php index 9755926464..16c63729e9 100644 --- a/app/code/core/Mage/Customer/Block/Form/Register.php +++ b/app/code/core/Mage/Customer/Block/Form/Register.php @@ -108,7 +108,6 @@ public function getRegion() /** * Newsletter module availability * - * @param none * @return boolean */ public function isNewsletterEnabled() diff --git a/app/code/core/Mage/Customer/Model/Address/Api/V2.php b/app/code/core/Mage/Customer/Model/Address/Api/V2.php new file mode 100644 index 0000000000..c3416caa40 --- /dev/null +++ b/app/code/core/Mage/Customer/Model/Address/Api/V2.php @@ -0,0 +1,187 @@ + + */ +class Mage_Customer_Model_Address_Api_V2 extends Mage_Customer_Model_Address_Api +{ + /** + * Create new address for customer + * + * @param int $customerId + * @param array $addressData + * @return int + */ + public function create($customerId, $addressData) + { + $customer = Mage::getModel('customer/customer') + ->load($customerId); + /* @var $customer Mage_Customer_Model_Customer */ + + if (!$customer->getId()) { + $this->_fault('customer_not_exists'); + } + + $address = Mage::getModel('customer/address'); + + foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { + if (isset($addressData->$attributeCode)) { + $address->setData($attributeCode, $addressData->$attributeCode); + } + } + + if (isset($addressData->is_default_billing)) { + $address->setIsDefaultBilling($addressData->is_default_billing); + } + + if (isset($addressData->is_default_shipping)) { + $address->setIsDefaultShipping($addressData->is_default_shipping); + } + + $address->setCustomerId($customer->getId()); + + $valid = $address->validate(); + + if (is_array($valid)) { + $this->_fault('data_invalid', implode("\n", $valid)); + } + + try { + $address->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $address->getId(); + } + + /** + * Retrieve address data + * + * @param int $addressId + * @return array + */ + public function info($addressId) + { + $address = Mage::getModel('customer/address') + ->load($addressId); + + if (!$address->getId()) { + $this->_fault('not_exists'); + } + + $result = array(); + + foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { + $result[$attributeAlias] = $address->getData($attributeCode); + } + + foreach ($this->getAllowedAttributes($address) as $attributeCode => $attribute) { + $result[$attributeCode] = $address->getData($attributeCode); + } + + + if ($customer = $address->getCustomer()) { + $result['is_default_billing'] = $customer->getDefaultBillingAddress() == $address->getId(); + $result['is_default_shipping'] = $customer->getDefaultShippingAddress() == $address->getId(); + } + + return $result; + } + + /** + * Update address data + * + * @param int $addressId + * @param array $addressData + * @return boolean + */ + public function update($addressId, $addressData) + { + $address = Mage::getModel('customer/address') + ->load($addressId); + + if (!$address->getId()) { + $this->_fault('not_exists'); + } + + foreach ($this->getAllowedAttributes($address) as $attributeCode=>$attribute) { + if (isset($addressData->$attributeCode)) { + $address->setData($attributeCode, $addressData->$attributeCode); + } + } + + if (isset($addressData->is_default_billing)) { + $address->setIsDefaultBilling($addressData->is_default_billing); + } + + if (isset($addressData->is_default_shipping)) { + $address->setIsDefaultShipping($addressData->is_default_shipping); + } + + $valid = $address->validate(); + if (is_array($valid)) { + $this->_fault('data_invalid', implode("\n", $valid)); + } + + try { + $address->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return true; + } + + /** + * Delete address + * + * @param int $addressId + * @return boolean + */ + public function delete($addressId) + { + $address = Mage::getModel('customer/address') + ->load($addressId); + + if (!$address->getId()) { + $this->_fault('not_exists'); + } + + try { + $address->delete(); + } catch (Mage_Core_Exception $e) { + $this->_fault('not_deleted', $e->getMessage()); + } + + return true; + } +} // Class Mage_Customer_Model_Address_Api End \ No newline at end of file diff --git a/app/code/core/Mage/Customer/Model/Customer.php b/app/code/core/Mage/Customer/Model/Customer.php index 0089cbf699..d44939e7fa 100644 --- a/app/code/core/Mage/Customer/Model/Customer.php +++ b/app/code/core/Mage/Customer/Model/Customer.php @@ -87,6 +87,10 @@ public function authenticate($login, $password) if (!$this->validatePassword($password)) { throw new Exception(Mage::helper('customer')->__('Invalid login or password.'), self::EXCEPTION_INVALID_EMAIL_OR_PASSWORD); } + Mage::dispatchEvent('customer_customer_authenticated', array( + 'model' => $this, + 'password' => $password, + )); return true; } @@ -123,19 +127,13 @@ protected function _beforeSave() /** * Change customer password - * $data = array( - * ['password'] - * ['confirmation'] - * ['current_password'] - * ) - * - * @param array $data - * @param bool $checkCurrent + * + * @param string $newPassword * @return this */ - public function changePassword($newPassword, $checkCurrent=true) + public function changePassword($newPassword) { - $this->_getResource()->changePassword($this, $newPassword, $checkCurrent); + $this->_getResource()->changePassword($this, $newPassword); return $this; } @@ -943,4 +941,17 @@ protected function _beforeDelete() $this->_protectFromNonAdmin(); return parent::_beforeDelete(); } + + /** + * Get customer created at date timestamp + * + * @return int + */ + public function getCreatedAtTimestamp() + { + if ($date = $this->getCreatedAt()) { + return $this->_getResource()->mktime($date); + } + return null; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Customer/Model/Customer/Api.php b/app/code/core/Mage/Customer/Model/Customer/Api.php index d3fed4cdf3..c5faffb19d 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Api.php +++ b/app/code/core/Mage/Customer/Model/Customer/Api.php @@ -148,7 +148,7 @@ public function update($customerId, $customerData) $this->_fault('not_exists'); } - foreach ($this->getAllowedAttributes($customer, $attributes) as $attributeCode=>$attribute) { + foreach ($this->getAllowedAttributes($customer) as $attributeCode=>$attribute) { if (isset($customerData[$attributeCode])) { $customer->setData($attributeCode, $customerData[$attributeCode]); } diff --git a/app/code/core/Mage/Customer/Model/Customer/Api/V2.php b/app/code/core/Mage/Customer/Model/Customer/Api/V2.php new file mode 100644 index 0000000000..abab42c5b8 --- /dev/null +++ b/app/code/core/Mage/Customer/Model/Customer/Api/V2.php @@ -0,0 +1,154 @@ + + */ +class Mage_Customer_Model_Customer_Api_V2 extends Mage_Customer_Model_Customer_Api +{ + /** + * Prepare data to insert/update. + * Creating array for stdClass Object + * + * @param stdClass $data + * @return array + */ + protected function _prepareData($data) + { + if (null !== ($_data = get_object_vars($data))) { + return $_data; + } + return array(); + } + + /** + * Create new customer + * + * @param array $customerData + * @return int + */ + public function create($customerData) + { + $customerData = $this->_prepareData($customerData); + try { + $customer = Mage::getModel('customer/customer') + ->setData($customerData) + ->save(); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + return $customer->getId(); + } + + /** + * Retrieve cutomers data + * + * @param array $filters + * @return array + */ + public function items($filters) + { + $collection = Mage::getModel('customer/customer')->getCollection() + ->addAttributeToSelect('*'); + + $preparedFilters = array(); + if (isset($filters->filter)) { + foreach ($filters->filter as $_filter) { + $preparedFilters[$_filter->key] = $_filter->value; + } + } + if (isset($filters->complex_filter)) { + foreach ($filters->complex_filter as $_filter) { + $_value = $_filter->value; + $preparedFilters[$_filter->key] = array( + $_value->key => $_value->value + ); + } + } + + if (!empty($preparedFilters)) { + try { + foreach ($preparedFilters as $field => $value) { + if (isset($this->_mapAttributes[$field])) { + $field = $this->_mapAttributes[$field]; + } + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + foreach ($collection as $customer) { + $data = $customer->toArray(); + $row = array(); + + foreach ($this->_mapAttributes as $attributeAlias => $attributeCode) { + $row[$attributeAlias] = (isset($data[$attributeCode]) ? $data[$attributeCode] : null); + } + + foreach ($this->getAllowedAttributes($customer) as $attributeCode => $attribute) { + if (isset($data[$attributeCode])) { + $row[$attributeCode] = $data[$attributeCode]; + } + } + + $result[] = $row; + } + + return $result; + } + + /** + * Update customer data + * + * @param int $customerId + * @param array $customerData + * @return boolean + */ + public function update($customerId, $customerData) + { + $customer = Mage::getModel('customer/customer')->load($customerId); + + if (!$customer->getId()) { + $this->_fault('not_exists'); + } + + foreach ($this->getAllowedAttributes($customer) as $attributeCode=>$attribute) { + if (isset($customerData->$attributeCode)) { + $customer->setData($attributeCode, $customerData->$attributeCode); + } + } + + $customer->save(); + return true; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php index ac73e7d8f6..dae6d54066 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php @@ -38,6 +38,7 @@ public function getAllOptions() if (!$this->_options) { $this->_options = Mage::getSingleton('adminhtml/system_store')->getWebsiteValuesForForm(true, true); } + return $this->_options; } diff --git a/app/code/core/Mage/Customer/Model/Entity/Customer.php b/app/code/core/Mage/Customer/Model/Entity/Customer.php index b697fd3e93..8b45b76bc8 100644 --- a/app/code/core/Mage/Customer/Model/Entity/Customer.php +++ b/app/code/core/Mage/Customer/Model/Entity/Customer.php @@ -186,24 +186,18 @@ public function loadByEmail(Mage_Customer_Model_Customer $customer, $email, $tes /** * Change customer password - * $data = array( - * ['password'] - * ['confirmation'] - * ['current_password'] - * ) * * @param Mage_Customer_Model_Customer - * @param array $data - * @param bool $checkCurrent + * @param string $newPassword * @return this */ - public function changePassword(Mage_Customer_Model_Customer $customer, $newPassword, $checkCurrent=true) + public function changePassword(Mage_Customer_Model_Customer $customer, $newPassword) { $customer->setPassword($newPassword); $this->saveAttribute($customer, 'password_hash'); return $this; } - + /** * Check whether there are email duplicates of customers in global scope * @@ -213,11 +207,29 @@ public function findEmailDuplicates() { $lookup = $this->_getReadAdapter()->fetchRow("SELECT email, COUNT(*) AS `qty` FROM `{$this->getTable('customer/entity')}` - GROUP BY 1 ORDER BY 2 DESC LIMIT 1 + GROUP BY 1 ORDER BY 2 DESC LIMIT 1 "); if (empty($lookup)) { return false; } return $lookup['qty'] > 1; } + + /** + * Check customer by id + * + * @param int $customerId + * @return bool + */ + public function checkCustomerId($customerId) + { + $select = $this->_getReadAdapter()->select() + ->from($this->getTable('customer/entity'), 'entity_id') + ->where('entity_id=?', $customerId) + ->limit(1); + if ($this->_getReadAdapter()->fetchOne($select)) { + return true; + } + return false; + } } diff --git a/app/code/core/Mage/Customer/Model/Group.php b/app/code/core/Mage/Customer/Model/Group.php index ffbc03e3cd..fb67b289c4 100644 --- a/app/code/core/Mage/Customer/Model/Group.php +++ b/app/code/core/Mage/Customer/Model/Group.php @@ -1,86 +1,102 @@ - - */ -class Mage_Customer_Model_Group extends Mage_Core_Model_Abstract -{ - const XML_PATH_DEFAULT_ID = 'customer/create_account/default_group'; - const NOT_LOGGED_IN_ID = 0; - const CUST_GROUP_ALL = 32000; - - protected static $_taxClassIds = array(); - - protected function _construct() - { - $this->_init('customer/group'); - } - - /** - * Alias for setCustomerGroupCode - * - * @param string $value - */ - public function setCode($value) - { - return $this->setCustomerGroupCode($value); - } - - /** - * Alias for getCustomerGroupCode - * - * @return string - */ - public function getCode() - { - return $this->getCustomerGroupCode(); - } - - public function getTaxClassId($groupId=null) - { - if (!is_null($groupId)) { - if (empty(self::$_taxClassIds[$groupId])) { - $this->load($groupId); - self::$_taxClassIds[$groupId] = $this->getData('tax_class_id'); - } - $this->setData('tax_class_id', self::$_taxClassIds[$groupId]); - } - return $this->getData('tax_class_id'); - } - - - public function usesAsDefault() - { - $data = Mage::getConfig()->getStoresConfigByPath(self::XML_PATH_DEFAULT_ID); - if (in_array($this->getId(), $data)) { - return true; - } - return false; - } + + */ +class Mage_Customer_Model_Group extends Mage_Core_Model_Abstract +{ + const XML_PATH_DEFAULT_ID = 'customer/create_account/default_group'; + const NOT_LOGGED_IN_ID = 0; + const CUST_GROUP_ALL = 32000; + + /** + * Prefix of model events names + * + * @var string + */ + protected $_eventPrefix = 'customer_group'; + + /** + * Parameter name in event + * + * In observe method you can use $observer->getEvent()->getObject() in this case + * + * @var string + */ + protected $_eventObject = 'object'; + + protected static $_taxClassIds = array(); + + protected function _construct() + { + $this->_init('customer/group'); + } + + /** + * Alias for setCustomerGroupCode + * + * @param string $value + */ + public function setCode($value) + { + return $this->setCustomerGroupCode($value); + } + + /** + * Alias for getCustomerGroupCode + * + * @return string + */ + public function getCode() + { + return $this->getCustomerGroupCode(); + } + + public function getTaxClassId($groupId=null) + { + if (!is_null($groupId)) { + if (empty(self::$_taxClassIds[$groupId])) { + $this->load($groupId); + self::$_taxClassIds[$groupId] = $this->getData('tax_class_id'); + } + $this->setData('tax_class_id', self::$_taxClassIds[$groupId]); + } + return $this->getData('tax_class_id'); + } + + + public function usesAsDefault() + { + $data = Mage::getConfig()->getStoresConfigByPath(self::XML_PATH_DEFAULT_ID); + if (in_array($this->getId(), $data)) { + return true; + } + return false; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Customer/Model/Group/Api/V2.php b/app/code/core/Mage/Customer/Model/Group/Api/V2.php new file mode 100644 index 0000000000..9a2f69e154 --- /dev/null +++ b/app/code/core/Mage/Customer/Model/Group/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Customer_Model_Group_Api_V2 extends Mage_Customer_Model_Group_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Customer/Model/Session.php b/app/code/core/Mage/Customer/Model/Session.php index c6a7c6b534..da5ba9b783 100644 --- a/app/code/core/Mage/Customer/Model/Session.php +++ b/app/code/core/Mage/Customer/Model/Session.php @@ -135,7 +135,19 @@ public function getCustomerGroupId() */ public function isLoggedIn() { - return (bool)$this->getId() && (bool)$this->getCustomer()->getId(); + return (bool)$this->getId() && (bool)$this->checkCustomerId($this->getId()); + } + + /** + * Check exists customer (light check) + * + * @param int $customerId + * @return bool + */ + public function checkCustomerId($customerId) + { + return Mage::getResourceSingleton('customer/customer') + ->checkCustomerId($customerId); } /** diff --git a/app/code/core/Mage/Customer/etc/api.xml b/app/code/core/Mage/Customer/etc/api.xml index 3b5f7df932..04f14f7bbf 100644 --- a/app/code/core/Mage/Customer/etc/api.xml +++ b/app/code/core/Mage/Customer/etc/api.xml @@ -132,6 +132,13 @@ + + + customerCustomer + customerGroup + customerAddress + + diff --git a/app/code/core/Mage/Customer/etc/config.xml b/app/code/core/Mage/Customer/etc/config.xml index 3e1c6701e5..ba90c893e8 100644 --- a/app/code/core/Mage/Customer/etc/config.xml +++ b/app/code/core/Mage/Customer/etc/config.xml @@ -28,7 +28,7 @@ - 0.8.9 + 0.8.10 diff --git a/app/code/core/Mage/Customer/etc/wsdl.xml b/app/code/core/Mage/Customer/etc/wsdl.xml new file mode 100644 index 0000000000..047dc34719 --- /dev/null +++ b/app/code/core/Mage/Customer/etc/wsdl.xml @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Retrieve customers + + + + + Create customer + + + + + Retrieve customer data + + + + + Update customer data + + + + + Delete customer + + + + + Retrieve customer’s groups + + + + + Retrieve customer addresses + + + + + Create customer address + + + + + Retrieve customer address data + + + + + Update customer address data + + + + + Delete customer address + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/Customer/sql/customer_setup/mysql4-upgrade-0.8.9-0.8.10.php b/app/code/core/Mage/Customer/sql/customer_setup/mysql4-upgrade-0.8.9-0.8.10.php new file mode 100644 index 0000000000..44cede0737 --- /dev/null +++ b/app/code/core/Mage/Customer/sql/customer_setup/mysql4-upgrade-0.8.9-0.8.10.php @@ -0,0 +1,63 @@ +getTable('customer/address_entity'); + +$types = array('datetime', 'decimal', 'int', 'text', 'varchar'); + +$tables = array($this->getTable('customer/entity'), + $this->getTable('customer/address_entity')); + +foreach ($tables as $table) { + foreach ($types as $type) { + $tableName = $table . '_' . $type; + + $select = $installer->getConnection()->select() + ->from($tableName, array( + 'entity_id' => 'entity_id', + 'attribute_id' => 'attribute_id', + 'rows_count' => 'COUNT(*)')) + ->group(array('entity_id', 'attribute_id')) + ->having('rows_count > 1'); + $query = $installer->getConnection()->query($select); + + while ($row = $query->fetch()) { + $sql = 'DELETE FROM `' . $tableName . '`' + . ' WHERE entity_id=? AND attribute_id=?' + . ' LIMIT ' . ($row['rows_count'] - 1); + $installer->getConnection()->query($sql, array( + $row['entity_id'], + $row['attribute_id'] + )); + } + + $installer->getConnection()->addKey($tableName, 'IDX_ATTRIBUTE_VALUE', array('entity_id', 'attribute_id'), 'unique'); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php b/app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php index 2f33cd6f99..b559dd14a1 100644 --- a/app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php +++ b/app/code/core/Mage/Dataflow/Model/Session/Adapter/Http.php @@ -18,18 +18,18 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Varien - * @package Mage_Dataflow_Model_Convert - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Dataflow + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Convert HTTP adapter * - * @category Varien - * @package Mage_Dataflow_Model_Convert + * @category Mage + * @package Mage_Dataflow * @author Magento Core Team */ class Mage_Dataflow_Model_Session_Adapter_Http extends Mage_Dataflow_Model_Convert_Adapter_Abstract @@ -82,5 +82,7 @@ public function load() } } return $this; - } // end - } \ No newline at end of file + } + + } + \ No newline at end of file diff --git a/app/code/core/Mage/Dataflow/Model/Session/Parser/Csv.php b/app/code/core/Mage/Dataflow/Model/Session/Parser/Csv.php index a6f2e81eaf..669b5cb81c 100644 --- a/app/code/core/Mage/Dataflow/Model/Session/Parser/Csv.php +++ b/app/code/core/Mage/Dataflow/Model/Session/Parser/Csv.php @@ -18,22 +18,23 @@ * versions in the future. If you wish to customize Magento for your * needs please refer to http://www.magentocommerce.com for more information. * - * @category Varien - * @package Varien_Convert - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Dataflow + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Convert csv parser * - * @category Varien - * @package Varien_Convert + * @category Mage + * @package Mage_Dataflow * @author Magento Core Team */ class Mage_Dataflow_Model_Session_Parser_Csv extends Mage_Dataflow_Model_Convert_Parser_Abstract { + public function parse() { $fDel = $this->getVar('delimiter', ','); @@ -137,4 +138,5 @@ public function unparse() return $this; } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/Directory/Block/Currency.php b/app/code/core/Mage/Directory/Block/Currency.php index be95b0dfd1..99e0e2adda 100644 --- a/app/code/core/Mage/Directory/Block/Currency.php +++ b/app/code/core/Mage/Directory/Block/Currency.php @@ -35,6 +35,7 @@ class Mage_Directory_Block_Currency extends Mage_Core_Block_Template { /** * Retrieve count of currencies + * Return 0 if only one currency * * @return int */ @@ -43,13 +44,20 @@ public function getCurrencyCount() return count($this->getCurrencies()); } + /** + * Retrieve currencies array + * Return array: code => currency name + * Return empty array if only one currency + * + * @return array + */ public function getCurrencies() { $currencies = $this->getData('currencies'); if (is_null($currencies)) { $currencies = array(); $codes = Mage::app()->getStore()->getAvailableCurrencyCodes(true); - if (is_array($codes) && count($codes)) { + if (is_array($codes) && count($codes) > 1) { $rates = Mage::getModel('directory/currency')->getCurrencyRates( Mage::app()->getStore()->getBaseCurrency(), $codes @@ -68,11 +76,21 @@ public function getCurrencies() return $currencies; } + /** + * Retrieve Currency Swith URL + * + * @return string + */ public function getSwitchUrl() { return $this->getUrl('directory/currency/switch'); } + /** + * Retrieve Current Currency code + * + * @return string + */ public function getCurrentCurrencyCode() { $code = $this->getData('current_currency_code'); diff --git a/app/code/core/Mage/Directory/Model/Country/Api/V2.php b/app/code/core/Mage/Directory/Model/Country/Api/V2.php new file mode 100644 index 0000000000..7e81432ca6 --- /dev/null +++ b/app/code/core/Mage/Directory/Model/Country/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Directory_Model_Country_Api_V2 extends Mage_Directory_Model_Country_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Directory/Model/Currency.php b/app/code/core/Mage/Directory/Model/Currency.php index 74a33372cf..e792a120a6 100644 --- a/app/code/core/Mage/Directory/Model/Currency.php +++ b/app/code/core/Mage/Directory/Model/Currency.php @@ -42,6 +42,13 @@ class Mage_Directory_Model_Currency extends Mage_Core_Model_Abstract protected $_filter; + /** + * Currency Rates + * + * @var array + */ + protected $_rates; + protected function _construct() { @@ -63,9 +70,26 @@ public function getCurrencyCode() return $this->_getData('currency_code'); } + /** + * Currency Rates getter + * + * @return array + */ public function getRates() { - return $this->_getData('rates'); + return $this->_rates; + } + + /** + * Currency Rates setter + * + * @param array Currency Rates + * @return Mage_Directory_Model_Currency + */ + public function setRates(array $rates) + { + $this->_rates = $rates; + return $this; } /** @@ -155,7 +179,9 @@ public function format($price, $options=array(), $includeContainer = true, $addB public function formatTxt($price, $options=array()) { - $price = Mage::app()->getLocale()->getNumber($price); + if (!is_numeric($price)) { + $price = Mage::app()->getLocale()->getNumber($price); + } /** * Fix problem with 12 000 000, 1 200 000 */ diff --git a/app/code/core/Mage/Directory/Model/Region/Api/V2.php b/app/code/core/Mage/Directory/Model/Region/Api/V2.php new file mode 100644 index 0000000000..4696f7ae67 --- /dev/null +++ b/app/code/core/Mage/Directory/Model/Region/Api/V2.php @@ -0,0 +1,36 @@ + + */ +class Mage_Directory_Model_Region_Api_V2 extends Mage_Directory_Model_Region_Api +{ +} \ No newline at end of file diff --git a/app/code/core/Mage/Directory/etc/api.xml b/app/code/core/Mage/Directory/etc/api.xml index 9b8b423872..2f06f91f8a 100644 --- a/app/code/core/Mage/Directory/etc/api.xml +++ b/app/code/core/Mage/Directory/etc/api.xml @@ -61,6 +61,12 @@ directory_country directory_region + + + directoryCountry + directoryRegion + + diff --git a/app/code/core/Mage/Directory/etc/config.xml b/app/code/core/Mage/Directory/etc/config.xml index fe0ffd0a1a..0e19e4e068 100644 --- a/app/code/core/Mage/Directory/etc/config.xml +++ b/app/code/core/Mage/Directory/etc/config.xml @@ -139,7 +139,7 @@ - AZN,AZM,AFN,ALL,DZD,AOA,ARS,AMD,AWG,AUD,BSD,BHD,BDT,BBD,BYR,BZD,BMD,BTN,BOB,BAM,BWP,BRL,GBP,BND,BGN,BUK,BIF,KHR,CAD,CVE,CZK,KYD,CLP,CNY,COP,KMF,CDF,CRC,HRK,CUP,DKK,DJF,DOP,XCD,EGP,SVC,GQE,ERN,EEK,ETB,EUR,FKP,FJD,GMD,GEK,GHS,GIP,GTQ,GNF,GYD,HTG,HNL,HKD,HUF,ISK,INR,IDR,IRR,IQD,ILS,JMD,JPY,JOD,KZT,KES,KWD,KGS,LAK,LVL,LBP,LSL,LRD,LYD,LTL,MOP,MKD,MGA,MWK,MYR,MVR,LSM,MRO,MUR,MXN,MDL,MNT,MAD,MZN,MMK,NAD,NPR,ANG,TRL,TRY,NZD,NIC,NGN,KPW,NOK,OMR,PKR,PAB,PGK,PYG,PEN,PHP,PLN,QAR,RHD,RON,ROL,RUB,RWF,SHP,STD,SAR,RSD,SCR,SLL,SGD,SKK,SBD,SOS,ZAR,KRW,LKR,SDG,SRD,SZL,SEK,CHF,SYP,TWD,TJS,TZS,THB,TOP,TTD,TND,TMM,USD,UGX,UAH,AED,UYU,UZS,VUV,VEB,VND,CHE,CHW,XOF,WST,YER,ZMK,ZWD + AZN,AZM,AFN,ALL,DZD,AOA,ARS,AMD,AWG,AUD,BSD,BHD,BDT,BBD,BYR,BZD,BMD,BTN,BOB,BAM,BWP,BRL,GBP,BND,BGN,BUK,BIF,KHR,CAD,CVE,CZK,KYD,CLP,CNY,COP,KMF,CDF,CRC,HRK,CUP,DKK,DJF,DOP,XCD,EGP,SVC,GQE,ERN,EEK,ETB,EUR,FKP,FJD,GMD,GEK,GHS,GIP,GTQ,GNF,GYD,HTG,HNL,HKD,HUF,ISK,INR,IDR,IRR,IQD,ILS,JMD,JPY,JOD,KZT,KES,KWD,KGS,LAK,LVL,LBP,LSL,LRD,LYD,LTL,MOP,MKD,MGA,MWK,MYR,MVR,LSM,MRO,MUR,MXN,MDL,MNT,MAD,MZN,MMK,NAD,NPR,ANG,TRL,TRY,NZD,NIC,NGN,KPW,NOK,OMR,PKR,PAB,PGK,PYG,PEN,PHP,PLN,QAR,RHD,RON,ROL,RUB,RWF,SHP,STD,SAR,RSD,SCR,SLL,SGD,SKK,SBD,SOS,ZAR,KRW,LKR,SDG,SRD,SZL,SEK,CHF,SYP,TWD,TJS,TZS,THB,TOP,TTD,TND,TMM,USD,UGX,UAH,AED,UYU,UZS,VUV,VEB,VND,CHE,CHW,XOF,XPF,WST,YER,ZMK,ZWD diff --git a/app/code/core/Mage/Directory/etc/wsdl.xml b/app/code/core/Mage/Directory/etc/wsdl.xml new file mode 100644 index 0000000000..ae6021f176 --- /dev/null +++ b/app/code/core/Mage/Directory/etc/wsdl.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + List of countries + + + + + List of regions in specified country + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php index 9520c2194b..63c5342763 100644 --- a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php +++ b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php @@ -141,7 +141,7 @@ public function getIsPriceWebsiteScope() public function getLinkData() { $linkArr = array(); - $links = $this->getProduct()->getTypeInstance()->getLinks(); + $links = $this->getProduct()->getTypeInstance(true)->getLinks($this->getProduct()); $priceWebsiteScope = $this->getIsPriceWebsiteScope(); foreach ($links as $item) { $tmpLinkItem = array( diff --git a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Samples.php b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Samples.php index d10f05c43c..0b15ed805b 100644 --- a/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Samples.php +++ b/app/code/core/Mage/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Samples.php @@ -71,7 +71,7 @@ public function getAddButtonHtml() public function getSampleData() { $samplesArr = array(); - $samples = $this->getProduct()->getTypeInstance()->getSamples(); + $samples = $this->getProduct()->getTypeInstance(true)->getSamples($this->getProduct()); foreach ($samples as $item) { $tmpSampleItem = array( 'sample_id' => $item->getId(), diff --git a/app/code/core/Mage/Downloadable/Block/Catalog/Product/Links.php b/app/code/core/Mage/Downloadable/Block/Catalog/Product/Links.php index ad90ac57ad..4b81214cf4 100644 --- a/app/code/core/Mage/Downloadable/Block/Catalog/Product/Links.php +++ b/app/code/core/Mage/Downloadable/Block/Catalog/Product/Links.php @@ -33,7 +33,6 @@ */ class Mage_Downloadable_Block_Catalog_Product_Links extends Mage_Catalog_Block_Product_Abstract { - /** * Enter description here... * @@ -51,7 +50,8 @@ public function getLinksPurchasedSeparately() */ public function getLinkSelectionRequired() { - return $this->getProduct()->getTypeInstance()->getLinkSelectionRequired(); + return $this->getProduct()->getTypeInstance(true) + ->getLinkSelectionRequired($this->getProduct()); } /** @@ -61,7 +61,8 @@ public function getLinkSelectionRequired() */ public function hasLinks() { - return $this->getProduct()->getTypeInstance()->hasLinks(); + return $this->getProduct()->getTypeInstance(true) + ->hasLinks($this->getProduct()); } /** @@ -71,7 +72,8 @@ public function hasLinks() */ public function getLinks() { - return $this->getProduct()->getTypeInstance()->getLinks(); + return $this->getProduct()->getTypeInstance(true) + ->getLinks($this->getProduct()); } /** diff --git a/app/code/core/Mage/Downloadable/Block/Catalog/Product/Samples.php b/app/code/core/Mage/Downloadable/Block/Catalog/Product/Samples.php index 94de13c22c..95524f67a7 100644 --- a/app/code/core/Mage/Downloadable/Block/Catalog/Product/Samples.php +++ b/app/code/core/Mage/Downloadable/Block/Catalog/Product/Samples.php @@ -41,7 +41,8 @@ class Mage_Downloadable_Block_Catalog_Product_Samples extends Mage_Catalog_Block */ public function hasSamples() { - return $this->getProduct()->getTypeInstance()->hasSamples(); + return $this->getProduct()->getTypeInstance(true) + ->hasSamples($this->getProduct()); } /** @@ -51,7 +52,8 @@ public function hasSamples() */ public function getSamples() { - return $this->getProduct()->getTypeInstance()->getSamples(); + return $this->getProduct()->getTypeInstance(true) + ->getSamples($this->getProduct()); } public function getSampleUrl($sample) diff --git a/app/code/core/Mage/Downloadable/Block/Checkout/Cart/Item/Renderer.php b/app/code/core/Mage/Downloadable/Block/Checkout/Cart/Item/Renderer.php index c917088b19..e3c5eef04e 100644 --- a/app/code/core/Mage/Downloadable/Block/Checkout/Cart/Item/Renderer.php +++ b/app/code/core/Mage/Downloadable/Block/Checkout/Cart/Item/Renderer.php @@ -43,7 +43,8 @@ public function getLinks() { $itemLinks = array(); if ($linkIds = $this->getItem()->getOptionByCode('downloadable_link_ids')) { - $productLinks = $this->getProduct()->getTypeInstance()->getLinks(); + $productLinks = $this->getProduct()->getTypeInstance(true) + ->getLinks($this->getProduct()); foreach (explode(',', $linkIds->getValue()) as $linkId) { if (isset($productLinks[$linkId])) { $itemLinks[] = $productLinks[$linkId]; diff --git a/app/code/core/Mage/Downloadable/Block/Checkout/Success.php b/app/code/core/Mage/Downloadable/Block/Checkout/Success.php index 74254c5ae7..e83cc362bd 100644 --- a/app/code/core/Mage/Downloadable/Block/Checkout/Success.php +++ b/app/code/core/Mage/Downloadable/Block/Checkout/Success.php @@ -46,6 +46,12 @@ public function getOrderHasDownloadable() if (!$this->isOrderVisible()) { return false; } + /** + * if use guest checkout + */ + if (!Mage::getSingleton('customer/session')->getCustomerId()) { + return false; + } return $hasDownloadableFlag; } diff --git a/app/code/core/Mage/Downloadable/Helper/File.php b/app/code/core/Mage/Downloadable/Helper/File.php index 70b6223cf5..86f5b75c78 100644 --- a/app/code/core/Mage/Downloadable/Helper/File.php +++ b/app/code/core/Mage/Downloadable/Helper/File.php @@ -33,15 +33,41 @@ */ class Mage_Downloadable_Helper_File extends Mage_Core_Helper_Abstract { - /** - * Move file from tmp path to base path - * - * @param string $baseTmpPath - * @param string $basePath - * @param string $file - * @return string - */ + /** + * Checking file for moving and move it + * + * @param string $baseTmpPath + * @param string $basePath + * @param array $file + * @return string + */ public function moveFileFromTmp($baseTmpPath, $basePath, $file) + { + if (isset($file[0])) { + $fileName = $file[0]['file']; + if ($file[0]['status'] == 'new') { + try { + $fileName = $this->_moveFileFromTmp( + $baseTmpPath, $basePath, $file[0]['file'] + ); + } catch (Exception $e) { + Mage::throwException(Mage::helper('downloadable')->__('An error occurred while saving the file(s).')); + } + } + return $fileName; + } + return ''; + } + + /** + * Move file from tmp path to base path + * + * @param string $baseTmpPath + * @param string $basePath + * @param string $file + * @return string + */ + protected function _moveFileFromTmp($baseTmpPath, $basePath, $file) { $ioObject = new Varien_Io_File(); $destDirectory = dirname($this->getFilePath($basePath, $file)); @@ -60,7 +86,7 @@ public function moveFileFromTmp($baseTmpPath, $basePath, $file) . Varien_File_Uploader::getNewFileName($this->getFilePath($basePath, $file)); $result = $ioObject->mv( $this->getFilePath($baseTmpPath, $file), - $this->getFilePath($basePath, $file) + $this->getFilePath($basePath, $destFile) ); return str_replace($ioObject->dirsep(), '/', $destFile); } diff --git a/app/code/core/Mage/Downloadable/Model/Observer.php b/app/code/core/Mage/Downloadable/Model/Observer.php index 7b781db486..bbe79ae365 100644 --- a/app/code/core/Mage/Downloadable/Model/Observer.php +++ b/app/code/core/Mage/Downloadable/Model/Observer.php @@ -69,7 +69,7 @@ public function saveDownloadableOrderItem($observer) ->setStoreId($orderItem->getOrder()->getStoreId()) ->load($orderItem->getProductId()); if ($product->getTypeId() == Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) { - $links = $product->getTypeInstance()->getLinks(); + $links = $product->getTypeInstance(true)->getLinks($product); if ($linkIds = $orderItem->getProductOptionByCode('links')) { $linkPurchased = Mage::getModel('downloadable/link_purchased'); Mage::helper('core')->copyFieldset( @@ -86,7 +86,7 @@ public function saveDownloadableOrderItem($observer) ); $linkSectionTitle = ( $product->getLinksTitle()? - $product->getLinksTitle():Mage::getStoreConfig(Mage_Downloadable_Model_Link::XML_PATH_LINKS_TITLE) + $product->getLinksTitle():Mage::getStoreConfig(Mage_Downloadable_Model_Link::XML_PATH_LINKS_TITLE) ); $linkPurchased->setLinkSectionTitle($linkSectionTitle) ->save(); @@ -131,7 +131,7 @@ public function setHasDownloadableProducts($observer) $order = $observer->getEvent()->getOrder(); foreach ($order->getAllItems() as $item) { if ($item->getProductType() == Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE - || $item->getProductOptionByCode('is_downloadable')) { + || $item->getProductOptionByCode('is_downloadable')) { $session->setHasDownloadableProducts(true); break; } @@ -156,7 +156,7 @@ public function setLinkStatus($observer) if ($order->getState() == Mage_Sales_Model_Order::STATE_HOLDED) { $status = Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_PENDING; } elseif ($order->getState() == Mage_Sales_Model_Order::STATE_CANCELED - || $order->getState() == Mage_Sales_Model_Order::STATE_CLOSED) { + || $order->getState() == Mage_Sales_Model_Order::STATE_CLOSED) { $status = Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_EXPIRED; } elseif ($order->getState() == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) { $status = Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_PENDING_PAYMENT; @@ -182,11 +182,11 @@ public function setLinkStatus($observer) if ($orderItemsIds) { $linkPurchased = Mage::getResourceModel('downloadable/link_purchased_item_collection') - ->addFieldToFilter('order_item_id', array('in'=>$orderItemsIds)); + ->addFieldToFilter('order_item_id', array('in'=>$orderItemsIds)); foreach ($linkPurchased as $link) { if ($link->getStatus() != Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_EXPIRED) { $link->setStatus($status) - ->save(); + ->save(); } } } @@ -210,7 +210,7 @@ public function isAllowedGuestCheckout(Varien_Event_Observer $observer) foreach ($quote->getAllItems() as $item) { if (($product = $item->getProduct()) && - $product->getTypeId() == Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) { + $product->getTypeId() == Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) { $isContain = true; } } diff --git a/app/code/core/Mage/Downloadable/Model/Product/Price.php b/app/code/core/Mage/Downloadable/Model/Product/Price.php index 0c6f344fc0..6e5fa18d97 100644 --- a/app/code/core/Mage/Downloadable/Model/Product/Price.php +++ b/app/code/core/Mage/Downloadable/Model/Product/Price.php @@ -33,9 +33,8 @@ */ class Mage_Downloadable_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Price { - /** - * Enter description here... + * Retrieve product final price * * @param integer $qty * @param Mage_Catalog_Model_Product $product @@ -55,7 +54,8 @@ public function getFinalPrice($qty=null, $product) if ($product->getLinksPurchasedSeparately()) { if ($linksIds = $product->getCustomOption('downloadable_link_ids')) { $linkPrice = 0; - $links = $product->getTypeInstance()->getLinks(); + $links = $product->getTypeInstance(true) + ->getLinks($product); foreach (explode(',', $linksIds->getValue()) as $linkId) { if (isset($links[$linkId])) { $linkPrice += $links[$linkId]->getPrice(); @@ -68,5 +68,4 @@ public function getFinalPrice($qty=null, $product) $product->setData('final_price', $finalPrice); return max(0, $product->getData('final_price')); } - } diff --git a/app/code/core/Mage/Downloadable/Model/Product/Type.php b/app/code/core/Mage/Downloadable/Model/Product/Type.php index dfcb8477c5..39433edb3f 100644 --- a/app/code/core/Mage/Downloadable/Model/Product/Type.php +++ b/app/code/core/Mage/Downloadable/Model/Product/Type.php @@ -33,17 +33,17 @@ */ class Mage_Downloadable_Model_Product_Type extends Mage_Catalog_Model_Product_Type_Virtual { - const TYPE_DOWNLOADABLE = 'downloadable'; /** * Get downloadable product links * + * @param Mage_Catalog_Model_Product $product * @return array */ - public function getLinks() + public function getLinks($product = null) { - $product = $this->getProduct(); + $product = $this->getProduct($product); /* @var Mage_Catalog_Model_Product $product */ if (is_null($product->getDownloadableLinks())) { $_linkCollection = Mage::getModel('downloadable/link')->getCollection() @@ -53,6 +53,7 @@ public function getLinks() $linksCollectionById = array(); foreach ($_linkCollection as $link) { /* @var Mage_Downloadable_Model_Link $link */ + $link->setProduct($product); $linksCollectionById[$link->getId()] = $link; } @@ -64,32 +65,36 @@ public function getLinks() /** * Check if product has links * + * @param Mage_Catalog_Model_Product $product * @return boolean */ - public function hasLinks() + public function hasLinks($product = null) { - return count($this->getLinks()) > 0; + return count($this->getLinks($product)) > 0; } /** * Check if product has options * + * @param Mage_Catalog_Model_Product $product * @return boolean */ - public function hasOptions() + public function hasOptions($product = null) { //return true; - return $this->getProduct()->getLinksPurchasedSeparately() || parent::hasOptions(); + return $this->getProduct($product)->getLinksPurchasedSeparately() + || parent::hasOptions($product); } /** * Check if product has required options * + * @param Mage_Catalog_Model_Product $product * @return bool */ - public function hasRequiredOptions() + public function hasRequiredOptions($product = null) { - if (parent::hasRequiredOptions() || $this->getProduct()->getLinksPurchasedSeparately()) { + if (parent::hasRequiredOptions($product) || $this->getProduct($product)->getLinksPurchasedSeparately()) { return true; } return false; @@ -98,21 +103,23 @@ public function hasRequiredOptions() /** * Check if product cannot be purchased with no links selected * + * @param Mage_Catalog_Model_Product $product * @return boolean */ - public function getLinkSelectionRequired() + public function getLinkSelectionRequired($product = null) { - return $this->getProduct()->getLinksPurchasedSeparately(); + return $this->getProduct($product)->getLinksPurchasedSeparately(); } /** * Get downloadable product samples * + * @param Mage_Catalog_Model_Product $product * @return Mage_Downloadable_Model_Mysql4_Sample_Collection */ - public function getSamples() + public function getSamples($product = null) { - $product = $this->getProduct(); + $product = $this->getProduct($product); /* @var Mage_Catalog_Model_Product $product */ if (is_null($product->getDownloadableSamples())) { $_sampleCollection = Mage::getModel('downloadable/sample')->getCollection() @@ -127,23 +134,25 @@ public function getSamples() /** * Check if product has samples * + * @param Mage_Catalog_Model_Product $product * @return boolean */ - public function hasSamples() + public function hasSamples($product = null) { - return count($this->getSamples()) > 0; + return count($this->getSamples($product)) > 0; } /** * Enter description here... * + * @param Mage_Catalog_Model_Product $product * @return Mage_Downloadable_Model_Product_Type */ - public function save() + public function save($product = null) { - parent::save(); + parent::save($product); - $product = $this->getProduct(); + $product = $this->getProduct($product); /* @var Mage_Catalog_Model_Product $product */ if ($data = $product->getDownloadableData()) { @@ -170,26 +179,16 @@ public function save() ->setSampleType($sampleItem['type']) ->setProductId($product->getId()) ->setStoreId($product->getStoreId()); - $fileStatusNew = false; - if (isset($files[0]) && $sampleModel->getSampleType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE) { - $sampleModel->setSampleFile($files[0]['file']); - if ($files[0]['status'] == 'new') { - $fileStatusNew = true; - } - } - $sampleModel->save(); - if ($sampleModel->getSampleType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE && $fileStatusNew) { - try { - Mage::helper('downloadable/file')->moveFileFromTmp( - Mage_Downloadable_Model_Sample::getBaseTmpPath(), - Mage_Downloadable_Model_Sample::getBasePath(), - $files[0]['file'] - ); - } catch (Exception $e) { - Mage::throwException(Mage::helper('downloadable')->__('An error occurred while saving the file(s).')); - } + if ($sampleModel->getSampleType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE) { + $sampleFileName = Mage::helper('downloadable/file')->moveFileFromTmp( + Mage_Downloadable_Model_Sample::getBaseTmpPath(), + Mage_Downloadable_Model_Sample::getBasePath(), + $files + ); + $sampleModel->setSampleFile($sampleFileName); } + $sampleModel->save(); } } if ($_deleteItems) { @@ -230,51 +229,31 @@ public function save() if ($linkModel->getIsUnlimited()) { $linkModel->setNumberOfDownloads(0); } - $fileStatusNew = false; - if (isset($files[0]) && $linkModel->getLinkType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE) { - $linkModel->setLinkFile($files[0]['file']); - if ($files[0]['status'] == 'new') { - $fileStatusNew = true; - } - } - $sampleFileNew = false; + $sampleFile = array(); if ($sample && isset($sample['type'])) { if ($sample['type'] == 'url' && $sample['url'] != '') { - $linkModel->setSampleUrl($sample['url']) - ->setSampleType($sample['type']); + $linkModel->setSampleUrl($sample['url']); } + $linkModel->setSampleType($sample['type']); $sampleFile = Zend_Json::decode($sample['file']); - if ($sample['type'] == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE && isset($sampleFile[0])) { - $linkModel->setSampleFile($sampleFile[0]['file']) - ->setSampleType($sample['type']); - if ($sampleFile[0]['status'] == 'new') { - $sampleFileNew = true; - } - } } - $linkModel->save(); - if ($linkModel->getLinkType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE && $fileStatusNew) { - try { - Mage::helper('downloadable/file')->moveFileFromTmp( - Mage_Downloadable_Model_Link::getBaseTmpPath(), - Mage_Downloadable_Model_Link::getBasePath(), - $files[0]['file'] - ); - } catch (Exception $e) { - Mage::throwException(Mage::helper('downloadable')->__('An error occurred while saving the file(s).')); - } + if ($linkModel->getLinkType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE) { + $linkFileName = Mage::helper('downloadable/file')->moveFileFromTmp( + Mage_Downloadable_Model_Link::getBaseTmpPath(), + Mage_Downloadable_Model_Link::getBasePath(), + $files + ); + $linkModel->setLinkFile($linkFileName); } - if ($linkModel->getSampleType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE && $sampleFileNew) { - try { - Mage::helper('downloadable/file')->moveFileFromTmp( - Mage_Downloadable_Model_Link::getBaseSampleTmpPath(), - Mage_Downloadable_Model_Link::getBaseSamplePath(), - $sampleFile[0]['file'] - ); - } catch (Exception $e) { - Mage::throwException(Mage::helper('downloadable')->__('An error occurred while saving the file(s).')); - } + if ($linkModel->getSampleType() == Mage_Downloadable_Helper_Download::LINK_TYPE_FILE) { + $linkSampleFileName = Mage::helper('downloadable/file')->moveFileFromTmp( + Mage_Downloadable_Model_Link::getBaseSampleTmpPath(), + Mage_Downloadable_Model_Link::getBaseSamplePath(), + $sampleFile + ); + $linkModel->setSampleFile($linkSampleFileName); } + $linkModel->save(); } } if ($_deleteItems) { @@ -290,49 +269,57 @@ public function save() * Enter description here... * * @param Varien_Object $buyRequest + * @param Mage_Catalog_Model_Product $product * @return array|string */ - public function prepareForCart(Varien_Object $buyRequest) + public function prepareForCart(Varien_Object $buyRequest, $product = null) { - $result = parent::prepareForCart($buyRequest); + $result = parent::prepareForCart($buyRequest, $product); if (is_string($result)) { return $result; } // if adding product from admin area we add all links to product - if ($this->getProduct()->getSkipCheckRequiredOption()) { - $this->getProduct()->setLinksPurchasedSeparately(false); + if ($this->getProduct($product)->getSkipCheckRequiredOption()) { + $this->getProduct($product)->setLinksPurchasedSeparately(false); } $preparedLinks = array(); - if ($this->getProduct()->getLinksPurchasedSeparately()) { + if ($this->getProduct($product)->getLinksPurchasedSeparately()) { if ($links = $buyRequest->getLinks()) { - foreach ($this->getLinks() as $link) { + foreach ($this->getLinks($product) as $link) { if (in_array($link->getId(), $links)) { $preparedLinks[] = $link->getId(); } } } } else { - foreach ($this->getLinks() as $link) { + foreach ($this->getLinks($product) as $link) { $preparedLinks[] = $link->getId(); } } if ($preparedLinks) { - $this->getProduct()->addCustomOption('downloadable_link_ids', implode(',', $preparedLinks)); + $this->getProduct($product)->addCustomOption('downloadable_link_ids', implode(',', $preparedLinks)); return $result; } - if ($this->getLinkSelectionRequired()) { + if ($this->getLinkSelectionRequired($product)) { return Mage::helper('downloadable')->__('Please specify product link(s).'); } return $result; } - public function getOrderOptions() + /** + * Prepare additional options/information for order item which will be + * created from this product + * + * @param Mage_Catalog_Model_Product $product + * @return array + */ + public function getOrderOptions($product = null) { - $options = parent::getOrderOptions(); - if ($linkIds = $this->getProduct()->getCustomOption('downloadable_link_ids')) { + $options = parent::getOrderOptions($product); + if ($linkIds = $this->getProduct($product)->getCustomOption('downloadable_link_ids')) { $linkOptions = array(); - $links = $this->getLinks(); + $links = $this->getLinks($product); foreach (explode(',', $linkIds->getValue()) as $linkId) { if (isset($links[$linkId])) { $linkOptions[] = $linkId; @@ -353,18 +340,19 @@ public function getOrderOptions() * Setting flag if dowenloadable product can be or not in complex product * based on link can be purchased separately or not * + * @param Mage_Catalog_Model_Product $product */ - public function beforeSave() + public function beforeSave($product = null) { - parent::beforeSave(); + parent::beforeSave($product); - if ($this->getLinkSelectionRequired()) { - $this->getProduct()->setTypeHasOptions(true); - $this->getProduct()->setTypeHasRequiredOptions(true); + if ($this->getLinkSelectionRequired($product)) { + $this->getProduct($product)->setTypeHasOptions(true); + $this->getProduct($product)->setTypeHasRequiredOptions(true); } else { - $this->getProduct()->setTypeHasOptions(false); - $this->getProduct()->setTypeHasRequiredOptions(false); + $this->getProduct($product)->setTypeHasOptions(false); + $this->getProduct($product)->setTypeHasRequiredOptions(false); } } } diff --git a/app/code/core/Mage/Downloadable/controllers/DownloadController.php b/app/code/core/Mage/Downloadable/controllers/DownloadController.php index db9c5f1a45..da5204a601 100644 --- a/app/code/core/Mage/Downloadable/controllers/DownloadController.php +++ b/app/code/core/Mage/Downloadable/controllers/DownloadController.php @@ -110,7 +110,7 @@ public function sampleAction() } try { $this->_processDownload($resource, $resourceType); - exit(); + exit(0); } catch (Mage_Core_Exception $e) { $this->_getSession()->addError(Mage::helper('downloadable')->__('Sorry, there was an error getting requested content. Please contact store owner.')); } @@ -140,6 +140,7 @@ public function linkSampleAction() } try { $this->_processDownload($resource, $resourceType); + exit(0); } catch (Mage_Core_Exception $e) { $this->_getCustomerSession()->addError(Mage::helper('downloadable')->__('Sorry, there was an error getting requested content. Please contact store owner.')); } @@ -205,6 +206,7 @@ public function linkAction() $linkPurchasedItem->setStatus(Mage_Downloadable_Model_Link_Purchased_Item::LINK_STATUS_EXPIRED); } $linkPurchasedItem->save(); + exit(0); } catch (Exception $e) { $this->_getCustomerSession()->addError( diff --git a/app/code/core/Mage/Downloadable/etc/config.xml b/app/code/core/Mage/Downloadable/etc/config.xml index 27234781b0..f0ed76b0eb 100644 --- a/app/code/core/Mage/Downloadable/etc/config.xml +++ b/app/code/core/Mage/Downloadable/etc/config.xml @@ -815,6 +815,15 @@ + + + + singleton + downloadable/observer + saveDownloadableOrderItem + + + diff --git a/app/code/core/Mage/Eav/Model/Config.php b/app/code/core/Mage/Eav/Model/Config.php index b2a3fefe4f..58ffbc37a7 100644 --- a/app/code/core/Mage/Eav/Model/Config.php +++ b/app/code/core/Mage/Eav/Model/Config.php @@ -40,7 +40,7 @@ class Mage_Eav_Model_Config /** * Attributes data * - * @var unknown_type + * @var array */ protected $_attributeData; @@ -58,6 +58,13 @@ class Mage_Eav_Model_Config */ protected $_initializedAttributes = array(); + /** + * Attribute codes cache array + * + * @var array + */ + protected $_attributeCodes = array(); + /** * Initialized objects * @@ -86,6 +93,13 @@ class Mage_Eav_Model_Config */ protected $_isCacheEnabled = null; + /** + * Array of attributes objects used in collections + * + * @var array + */ + protected $_collectionAttributes = array(); + /** * Reset object state * @@ -139,17 +153,38 @@ protected function _addEntityTypeReference($id, $code) return $this; } + /** + * Get entity type code by id + * + * @param int $id + * @return string + */ protected function _getEntityTypeReference($id) { return isset($this->_references['entity'][$id]) ? $this->_references['entity'][$id] : null; } + /** + * Specify reference between entity attribute id and attribute code + * + * @param int $id + * @param string $code + * @param string $entityTypeCode + * @return Mage_Eav_Model_Config + */ protected function _addAttributeReference($id, $code, $entityTypeCode) { $this->_references['attribute'][$entityTypeCode][$id] = $code; return $this; } + /** + * Get attribute code by attribute id + * + * @param int $id + * @param string $entityTypeCode + * @return string + */ protected function _getAttributeReference($id, $entityTypeCode) { if (isset($this->_references['attribute'][$entityTypeCode][$id])) { @@ -158,11 +193,24 @@ protected function _getAttributeReference($id, $entityTypeCode) return null; } + /** + * Get internal cache key for entity type code + * + * @param string $code + * @return string + */ protected function _getEntityKey($code) { return 'ENTITY/'.$code; } + /** + * Get internal cache key for attribute object cache + * + * @param string $entityTypeCode + * @param string $attributeCode + * @return string + */ protected function _getAttributeKey($entityTypeCode, $attributeCode) { return 'ATTRIBUTE/'. $entityTypeCode .'/' . $attributeCode; @@ -249,12 +297,13 @@ public function getEntityType($code) return $code; } Varien_Profiler::start('EAV: '.__METHOD__); - $this->_initEntityTypes(); + //$this->_initEntityTypes(); if (is_numeric($code)) { - $code = $this->_getEntityTypeReference($code); - if ($code === null) { - Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code)); + $entityCode = $this->_getEntityTypeReference($code); + if ($entityCode !== null) { + $code = $entityCode; + //Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code)); } } @@ -270,11 +319,17 @@ public function getEntityType($code) $entityType->setData($this->_entityData[$code]); } else { - $entityType->loadByCode($code); + if (is_numeric($code)) { + $entityType->load($code); + } else { + $entityType->loadByCode($code); + } + if (!$entityType->getId()) { Mage::throwException(Mage::helper('eav')->__('Invalid entity_type specified: %s', $code)); } } + $this->_addEntityTypeReference($entityType->getId(), $entityType->getEntityTypeCode()); $this->_save($entityType, $entityKey); Varien_Profiler::stop('EAV: '.__METHOD__); @@ -347,9 +402,9 @@ public function getAttribute($entityType, $code) * Validate attribute code */ if (is_numeric($code)) { - $code = $this->_getAttributeReference($code, $entityTypeCode); - if (!$code) { - return false; + $attributeCode = $this->_getAttributeReference($code, $entityTypeCode); + if ($attributeCode) { + $code = $attributeCode; } } $attributeKey = $this->_getAttributeKey($entityTypeCode, $code); @@ -362,22 +417,32 @@ public function getAttribute($entityType, $code) return $attribute; } - if (!isset($this->_preloadedAttributes[$entityTypeCode]) - || !in_array($code, $this->_preloadedAttributes[$entityTypeCode])) { - $this->_initAttributes($entityType); - } +// if (!isset($this->_preloadedAttributes[$entityTypeCode]) +// || !in_array($code, $this->_preloadedAttributes[$entityTypeCode])) { +// $this->_initAttributes($entityType); +// } $attribute = false; if (isset($this->_attributeData[$entityTypeCode][$code])) { $data = $this->_attributeData[$entityTypeCode][$code]; + unset($this->_attributeData[$entityTypeCode][$code]); $attribute = Mage::getModel($data['attribute_model'], $data); } else { - $attribute = Mage::getModel($entityType->getAttributeModel())->loadByCode($entityType, $code); + if (is_numeric($code)) { + $attribute = Mage::getModel($entityType->getAttributeModel())->load($code); + if ($attribute->getEntityTypeId() != $entityType->getId()) { + return false; + } + $attributeKey = $this->_getAttributeKey($entityTypeCode, $attribute->getAttributeCode()); + } else { + $attribute = Mage::getModel($entityType->getAttributeModel())->loadByCode($entityType, $code); + } } if ($attribute) { $attribute->setEntityType($entityType); + $this->_addAttributeReference($attribute->getId(), $attribute->getAttributeCode(), $entityTypeCode); $this->_save($attribute, $attributeKey); } Varien_Profiler::stop('EAV: '.__METHOD__); @@ -387,28 +452,41 @@ public function getAttribute($entityType, $code) /** * Get codes of all entity type attributes * - * @param string $entityType - * @return array + * @param mixed $entityType + * @param Varien_Object $object + * @return array */ public function getEntityAttributeCodes($entityType, $object=null) { + $entityType = $this->getEntityType($entityType); + $attributeSetId = 0; if (($object instanceof Varien_Object) && $object->getAttributeSetId()) { + $attributeSetId = $object->getAttributeSetId(); + } + $cacheKey = sprintf('%d-%d', $entityType->getId(), $attributeSetId); + if (isset($this->_attributeCodes[$cacheKey])) { + return $this->_attributeCodes[$cacheKey]; + } + + if ($attributeSetId) { $attributesInfo = Mage::getResourceModel('eav/entity_attribute_collection') - ->setEntityTypeFilter($this->getEntityType($entityType)->getId()) - ->setAttributeSetFilter($object->getAttributeSetId()) + ->setEntityTypeFilter($entityType->getId()) + ->setAttributeSetFilter($attributeSetId) + ->addSetInfo() ->getData(); $attributes = array(); foreach ($attributesInfo as $attributeData) { $attributes[] = $attributeData['attribute_code']; + $this->_createAttribute($entityType, $attributeData); } - - $this->preloadAttributes($entityType, $attributes); - return $attributes; } else { $this->_initAttributes($entityType); + $attributes = $this->getEntityType($entityType)->getAttributeCodes(); } - return $this->getEntityType($entityType)->getAttributeCodes(); + + $this->_attributeCodes[$cacheKey] = $attributes; + return $attributes; } /** @@ -471,5 +549,97 @@ public function preloadAttributes($entityType, $attributes) Varien_Profiler::stop('EAV: '.__METHOD__ . ':'.$entityTypeCode); return $this; - } -} \ No newline at end of file + } + + /** + * Get attribute object for colection usage + * + * @param mixed $entityType + * @param string $attribute + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + public function getCollectionAttribute($entityType, $attribute) + { + $entityType = $this->getEntityType($entityType); + $entityTypeCode = $entityType->getEntityTypeCode(); + + if (is_numeric($attribute)) { + $attribute = $this->_getAttributeReference($attribute, $entityTypeCode); + if (!$attribute) { + return null; + } + } + + if (isset($this->_collectionAttributes[$entityTypeCode][$attribute])) { + $attribute = $this->_collectionAttributes[$entityTypeCode][$attribute]; + } else { + $attribute = $this->getAttribute($entityType, $attribute); + } + + return $attribute; + } + + /** + * Prepare attributes for usage in EAV collection + * + * @param mixed $entityType + * @param array $attributes + * @return Mage_Eav_Model_Config + */ + public function loadCollectionAttributes($entityType, $attributes) + { + $entityType = $this->getEntityType($entityType); + $entityTypeCode = $entityType->getEntityTypeCode(); + + if (!isset($this->_collectionAttributes[$entityTypeCode])) { + $this->_collectionAttributes[$entityTypeCode] = array(); + } + $loadedAttributes = array_keys($this->_collectionAttributes[$entityTypeCode]); + $attributes = array_diff($attributes, $loadedAttributes); + + if (empty($attributes)) { + return $this; + } + + $attributesInfo = Mage::getResourceModel('eav/entity_attribute_collection') + ->useLoadDataFields() + ->setEntityTypeFilter($entityType->getId()) + ->setCodeFilter($attributes) + ->getData(); + + foreach ($attributesInfo as $attributeData) { + $attribute = $this->_createAttribute($entityType, $attributeData); + $this->_collectionAttributes[$entityTypeCode][$attribute->getAttributeCode()] =$attribute; + } + + return $this; + } + + /** + * Create attribute from attribute data array + * + * @param string $entityType + * @param array $attributeData + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ + protected function _createAttribute($entityType, $attributeData) + { + $entityType = $this->getEntityType($entityType); + $entityTypeCode = $entityType->getEntityTypeCode(); + if (isset($attributeData['attribute_model'])) { + $model = $attributeData['attribute_model']; + } + else { + $model = $entityType->getAttributeModel(); + } + $attribute = Mage::getModel($model)->setData($attributeData); + $this->_addAttributeReference( + $attributeData['attribute_id'], + $attributeData['attribute_code'], + $entityTypeCode + ); + $attributeKey = $this->_getAttributeKey($entityTypeCode, $attributeData['attribute_code']); + $this->_save($attribute, $attributeKey); + return $attribute; + } +} diff --git a/app/code/core/Mage/Eav/Model/Entity/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Abstract.php index ea46f83b76..39b499d2b4 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Abstract.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Eav - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -30,13 +30,12 @@ * * @category Mage * @package Mage_Eav - * @author Magento Core Team + * @author Magento Core Team */ abstract class Mage_Eav_Model_Entity_Abstract extends Mage_Core_Model_Resource_Abstract implements Mage_Eav_Model_Entity_Interface { - /** * Read connection * @@ -211,7 +210,7 @@ public function getWriteConnection() */ public function getIdFieldName() { - return $this->_entityIdField; + return $this->getEntityIdField(); } /** @@ -321,7 +320,7 @@ public function unsetAttributes($attributes=null) * If attribute is not found false is returned * * @param string|integer|Mage_Core_Model_Config_Element $attribute - * @return boolean|Mage_Eav_Model_Entity_Attribute_Abstract + * @return Mage_Eav_Model_Entity_Attribute_Abstract */ public function getAttribute($attribute) { @@ -337,14 +336,22 @@ public function getAttribute($attribute) } } elseif (is_string($attribute)) { - $attributeCode = $attribute; if (isset($this->_attributesByCode[$attributeCode])) { return $this->_attributesByCode[$attributeCode]; } - $attributeInstance = Mage::getSingleton('eav/config')->getAttribute($this->getEntityType(), $attributeCode); - + $attributeInstance = Mage::getSingleton('eav/config') + ->getAttribute($this->getEntityType(), $attributeCode); + if (!$attributeInstance->getAttributeCode() && in_array($attribute, $this->getDefaultAttributes())) { + $attributeInstance + ->setAttributeCode($attribute) + ->setBackendType(Mage_Eav_Model_Entity_Attribute_Abstract::TYPE_STATIC) + ->setIsGlobal(1) + ->setEntity($this) + ->setEntityType($this->getEntityType()) + ->setEntityTypeId($this->getEntityType()->getId()); + } } elseif ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) { $attributeInstance = $attribute; @@ -356,8 +363,8 @@ public function getAttribute($attribute) if (empty($attributeInstance) || !($attributeInstance instanceof Mage_Eav_Model_Entity_Attribute_Abstract) - || !$attributeInstance->getId() - ) { + || (!$attributeInstance->getId() && !in_array($attributeInstance->getAttributeCode(), $this->getDefaultAttributes())) + ) { return false; } @@ -392,13 +399,11 @@ public function addAttribute(Mage_Eav_Model_Entity_Attribute_Abstract $attribute $this->_attributesByCode[$attributeCode] = $attribute; - if ($attribute->getBackend()->isStatic()) { + if ($attribute->isStatic()) { $this->_staticAttributes[$attributeCode] = $attribute; } else { $this->_attributesById[$attribute->getId()] = $attribute; - - $attributeTable = $attribute->getBackend()->getTable(); - $this->_attributesByTable[$attributeTable][$attributeCode] = $attribute; + $this->_attributesByTable[$attribute->getBackendTable()][$attributeCode] = $attribute; } return $this; } @@ -441,9 +446,29 @@ public function isPartialSave($flag=null) public function loadAllAttributes($object=null) { $attributeCodes = Mage::getSingleton('eav/config')->getEntityAttributeCodes($this->getEntityType(), $object); + /** + * Check and init default attributes + */ + $defaultAttributes = $this->getDefaultAttributes(); + foreach ($defaultAttributes as $attributeCode) { + $attributeIndex = array_search($attributeCode, $attributeCodes); + if ($attributeIndex !== false) { + $this->getAttribute($attributeCodes[$attributeIndex]); + unset($attributeCodes[$attributeIndex]); + } else { + $attribute = Mage::getModel($this->getEntityType()->getAttributeModel()); + $attribute->setAttributeCode($attributeCode) + ->setBackendType('static') + ->setEntityType($this->getEntityType()) + ->setEntityTypeId($this->getEntityType()->getId()); + $this->addAttribute($attribute); + } + } + foreach ($attributeCodes as $code) { - $this->getAttribute($code); + $this->getAttribute($code); } + return $this; } @@ -751,6 +776,7 @@ public function getDefaultAttributeSourceModel() */ public function load($object, $entityId, $attributes=array()) { + Varien_Profiler::start('__EAV_LOAD_MODEL__'); /** * Load object base row data */ @@ -772,6 +798,7 @@ public function load($object, $entityId, $attributes=array()) /** * Load data for entity attributes */ + Varien_Profiler::start('__EAV_LOAD_MODEL_ATTRIBUTES__'); foreach ($this->getAttributesByTable() as $table=>$attributes) { $select = $this->_getLoadAttributesSelect($object, $table); $values = $this->_getReadAdapter()->fetchAll($select); @@ -780,9 +807,14 @@ public function load($object, $entityId, $attributes=array()) $this->_setAttribteValue($object, $valueRow); } } + Varien_Profiler::stop('__EAV_LOAD_MODEL_ATTRIBUTES__'); $object->setOrigData(); + Varien_Profiler::start('__EAV_LOAD_MODEL_AFTER_LOAD__'); $this->_afterLoad($object); + Varien_Profiler::stop('__EAV_LOAD_MODEL_AFTER_LOAD__'); + + Varien_Profiler::stop('__EAV_LOAD_MODEL__'); return $this; } @@ -1142,7 +1174,7 @@ protected function _deleteAttributes($object, $table, $info) } /** - * Enter description here... + * Save attribute * * @param Varien_Object $object * @param string $attributeCode @@ -1228,7 +1260,7 @@ public function delete($object) } /** - * Enter description here... + * After Load Entity process * * @param Varien_Object $object */ @@ -1238,7 +1270,7 @@ protected function _afterLoad(Varien_Object $object) } /** - * Enter description here... + * Before delete Entity process * * @param Varien_Object $object */ @@ -1248,7 +1280,7 @@ protected function _beforeSave(Varien_Object $object) } /** - * Enter description here... + * After Save Entity process * * @param Varien_Object $object */ @@ -1258,7 +1290,7 @@ protected function _afterSave(Varien_Object $object) } /** - * Enter description here... + * Before Delete Entity process * * @param Varien_Object $object */ @@ -1268,7 +1300,7 @@ protected function _beforeDelete(Varien_Object $object) } /** - * Enter description here... + * After delete entity process * * @param Varien_Object $object */ @@ -1278,7 +1310,7 @@ protected function _afterDelete(Varien_Object $object) } /** - * Enter description here... + * Retrieve Default attribute model * * @return string */ @@ -1288,7 +1320,7 @@ protected function _getDefaultAttributeModel() } /** - * Enter description here... + * Retrieve default entity attributes * * @return array */ @@ -1298,26 +1330,40 @@ protected function _getDefaultAttributes() } /** - * Enter description here... + * Retrieve default entity static attributes + * + * @return array + */ + public function getDefaultAttributes() { + return array_unique(array_merge($this->_getDefaultAttributes(), array($this->getEntityIdField()))); + } + + /** + * After set config process * + * @deprecated + * @return Mage_Eav_Model_Entity_Abstract */ protected function _afterSetConfig() { - //return; - $defaultAttributes = $this->_getDefaultAttributes(); - $defaultAttributes[] = $this->getEntityIdField(); - - $attributes = $this->getAttributesByCode(); - foreach ($defaultAttributes as $attr) { - if (empty($attributes[$attr]) && !$this->getAttribute($attr)) { - $attribute = Mage::getModel($this->getEntityType()->getAttributeModel()); - $attribute->setAttributeCode($attr) - ->setBackendType('static') - ->setEntityType($this->getEntityType()) - ->setEntityTypeId($this->getEntityType()->getId()); - $this->addAttribute($attribute); - } - } + return $this; +// Varien_Profiler::start(__METHOD__); +// +// $defaultAttributes = $this->_getDefaultAttributes(); +// $defaultAttributes[] = $this->getEntityIdField(); +// +// $attributes = $this->getAttributesByCode(); +// foreach ($defaultAttributes as $attr) { +// if (empty($attributes[$attr]) && !$this->getAttribute($attr)) { +// $attribute = Mage::getModel($this->getEntityType()->getAttributeModel()); +// $attribute->setAttributeCode($attr) +// ->setBackendType('static') +// ->setEntityType($this->getEntityType()) +// ->setEntityTypeId($this->getEntityType()->getId()); +// $this->addAttribute($attribute); +// } +// } +// Varien_Profiler::stop(__METHOD__); +// return $this; } - } diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php index 0c15b8cbc1..b2dd65e3c9 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php @@ -32,8 +32,7 @@ * @package Mage_Eav * @author Magento Core Team */ -abstract class Mage_Eav_Model_Entity_Attribute_Abstract - extends Mage_Core_Model_Abstract +abstract class Mage_Eav_Model_Entity_Attribute_Abstract extends Mage_Core_Model_Abstract implements Mage_Eav_Model_Entity_Attribute_Interface { const TYPE_STATIC = 'static'; @@ -80,6 +79,13 @@ abstract class Mage_Eav_Model_Entity_Attribute_Abstract */ protected $_attributeIdCache = array(); + /** + * Attribute data table name + * + * @var string + */ + protected $_dataTable = null; + /** * Initialize resource model */ @@ -97,6 +103,7 @@ protected function _construct() */ public function loadByCode($entityType, $code) { + Varien_Profiler::start('_LOAD_ATTRIBUTE_BY_CODE__'); if (is_numeric($entityType)) { $entityTypeId = $entityType; } elseif (is_string($entityType)) { @@ -110,6 +117,7 @@ public function loadByCode($entityType, $code) } $this->_getResource()->loadByCode($this, $entityTypeId, $code); $this->_afterLoad(); + Varien_Profiler::stop('_LOAD_ATTRIBUTE_BY_CODE__'); return $this; } @@ -130,18 +138,29 @@ public function getConfig() */ public function getName() { - return (isset($this->_data['attribute_code'])) ? $this->_data['attribute_code'] : null; + return $this->_getData('attribute_code'); } + /** + * Specify attribute identifier + * + * @param int $data + * @return Mage_Eav_Model_Entity_Attribute_Abstract + */ public function setAttributeId($data) { $this->_data['attribute_id'] = $data; return $this; } + /** + * Get attribute identifuer + * + * @return int | null + */ public function getAttributeId() { - return (isset($this->_data['attribute_id'])) ? $this->_data['attribute_id'] : null; + return $this->_getData('attribute_id'); } public function setAttributeCode($data) @@ -151,7 +170,7 @@ public function setAttributeCode($data) public function getAttributeCode() { - return (isset($this->_data['attribute_code'])) ? $this->_data['attribute_code'] : null; + return $this->_getData('attribute_code'); } public function setAttributeModel($data) @@ -161,7 +180,7 @@ public function setAttributeModel($data) public function getAttributeModel() { - return (isset($this->_data['attribute_model'])) ? $this->_data['attribute_model'] : null; + return $this->_getData('attribute_model'); } public function setBackendType($data) @@ -171,7 +190,7 @@ public function setBackendType($data) public function getBackendType() { - return (isset($this->_data['backend_type'])) ? $this->_data['backend_type'] : null; + return $this->_getData('backend_type'); } public function setBackendModel($data) @@ -181,7 +200,7 @@ public function setBackendModel($data) public function getBackendModel() { - return (isset($this->_data['backend_model'])) ? $this->_data['backend_model'] : null; + return $this->_getData('backend_model'); } public function setBackendTable($data) @@ -189,24 +208,19 @@ public function setBackendTable($data) return $this->setData('backend_table', $data); } - public function getBackendTable() - { - return (isset($this->_data['backend_table'])) ? $this->_data['backend_table'] : null; - } - public function getIsVisibleOnFront() { - return (isset($this->_data['is_visible_on_front'])) ? $this->_data['is_visible_on_front'] : null; + return $this->_getData('is_visible_on_front'); } public function getDefaultValue() { - return (isset($this->_data['default_value'])) ? $this->_data['default_value'] : null; + return $this->_getData('default_value'); } public function getAttributeSetId() { - return isset($this->_data['attribute_set_id'] ) ? $this->_data['attribute_set_id'] : null; + return $this->_getData('attribute_set_id'); } public function setAttributeSetId($id) @@ -217,7 +231,7 @@ public function setAttributeSetId($id) public function getEntityTypeId() { - return $this->getData('entity_type_id'); + return $this->_getData('entity_type_id'); } public function setEntityTypeId($id) @@ -266,6 +280,9 @@ public function setName($name) public function getEntityType() { + /*if ($this->hasData('entity_type')) { + return $this->_getData('entity_type'); + }*/ return Mage::getSingleton('eav/config')->getEntityType($this->getEntityTypeId()); } @@ -447,6 +464,194 @@ public function getIdByCode($entityType, $code) */ public function isStatic() { - return $this->getBackendType() == self::TYPE_STATIC; + return $this->getBackendType() == self::TYPE_STATIC || $this->getBackendType() == ''; + } + + /** + * Get attribute backend table name + * + * @return string + */ + public function getBackendTable() + { + if ($this->_dataTable === null) { + if ($this->isStatic()) { + $this->_dataTable = $this->getEntityType()->getValueTablePrefix(); + } elseif ($this->_getData('backend_table')) { + $this->_dataTable = $this->_getData('backend_table'); + } else { + $this->_dataTable = $this->getEntity()->getValueTablePrefix().'_'.$this->getBackendType(); + } + } + return $this->_dataTable; + } + + /** + * Retrieve Flat Column(s) + * + * @return array + */ + public function getFlatColumns() { + if ($this->usesSource() && $this->getBackendType() != 'static') { + return $this->getSource()->getFlatColums(); + } + + $columns = array(); + switch ($this->getBackendType()) { + case 'static': + $describe = $this->_getResource() + ->describeTable($this->getBackend()->getTable()); + if (!isset($describe[$this->getAttributeCode()])) { + break; + } + $prop = $describe[$this->getAttributeCode()]; + $columns[$this->getAttributeCode()] = array( + 'type' => $prop['DATA_TYPE'] . ($prop['LENGTH'] ? "({$prop['LENGTH']})" : ""), + 'unsigned' => $prop['UNSIGNED'] ? true: false, + 'is_null' => $prop['NULLABLE'], + 'default' => $prop['DEFAULT'], + 'extra' => null + ); + break; + case 'datetime': + $columns[$this->getAttributeCode()] = array( + 'type' => 'datetime', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + break; + case 'decimal': + $columns[$this->getAttributeCode()] = array( + 'type' => 'decimal(12,4)', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + break; + case 'int': + $columns[$this->getAttributeCode()] = array( + 'type' => 'int', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + break; + case 'text': + $columns[$this->getAttributeCode()] = array( + 'type' => 'text', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + break; + case 'varchar': + $columns[$this->getAttributeCode()] = array( + 'type' => 'varchar(255)', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + break; + } + return $columns; + } + + /** + * Retrieve index data for Flat table + * + * @return array + */ + public function getFlatIndexes() + { + if ($this->getIsFilterable() or $this->getIsFilterableInSearch() or $this->getUsedForSortBy()) { + if ($this->usesSource() && $this->getBackendType() != 'static') { + return $this->getSource()->getFlatIndexes(); + } + $indexes = array(); + + switch ($this->getBackendType()) { + case 'static': + $describe = $this->_getResource() + ->describeTable($this->getBackend()->getTable()); + if (!isset($describe[$this->getAttributeCode()])) { + break; + } + $indexDataTypes = array( + 'varchar', + 'varbinary', + 'char', + 'date', + 'datetime', + 'timestamp', + 'time', + 'year', + 'enum', + 'set', + 'bit', + 'bool', + 'tinyint', + 'smallint', + 'mediumint', + 'int', + 'bigint', + 'float', + 'double', + 'decimal', + ); + $prop = $describe[$this->getAttributeCode()]; + if (in_array($prop['DATA_TYPE'], $indexDataTypes)) { + $indexName = 'IDX_' . strtoupper($this->getAttributeCode()); + $indexes[$indexName] = array( + 'type' => $this->getIsUnique() ? 'unique' : 'index', + 'fields' => array($this->getAttributeCode()) + ); + } + + break; + case 'datetime': + case 'decimal': + case 'int': + case 'varchar': + $indexName = 'IDX_' . strtoupper($this->getAttributeCode()); + $indexes[$indexName] = array( + 'type' => $this->getIsUnique() ? 'unique' : 'index', + 'fields' => array($this->getAttributeCode()) + ); + break; + } + + return $indexes; + } + return array(); + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param int $store + * @return Varien_Db_Select + */ + public function getFlatUpdateSelect($store = null) { + if (is_null($store)) { + foreach (Mage::app()->getStores() as $store) { + $this->getFlatUpdateSelect($store->getId()); + } + return $this; + } + + if ($this->getBackendType() == 'static') { + return null; + } + + if ($this->usesSource()) { + return $this->getSource()->getFlatUpdateSelect($store); + } + return $this->_getResource()->getFlatUpdateSelect($this, $store); } } diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Abstract.php index 6e789e51ca..acd4a8cc6a 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Abstract.php @@ -108,7 +108,7 @@ public function getType() */ public function isStatic() { - return (string)$this->getType()==='' || $this->getType()==='static'; + return $this->getAttribute()->isStatic(); } /** @@ -183,7 +183,7 @@ public function validate($object) if ($this->getAttribute()->getIsUnique() && !$this->getAttribute()->getIsRequired() && ($value == '' || $this->getAttribute()->isValueEmpty($value))) { return true; } - + if ($this->getAttribute()->getIsUnique()) { if (!$this->getAttribute()->getEntity()->checkAttributeUniqueValue($this->getAttribute(), $object)) { $label = $this->getAttribute()->getFrontend()->getLabel(); diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Datetime.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Datetime.php index 02fc66386a..ce3354d68e 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Datetime.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Datetime.php @@ -26,10 +26,19 @@ class Mage_Eav_Model_Entity_Attribute_Backend_Datetime extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract { + /** + * Flag to prevent double generating of GMT date + * + * @var boolean + */ + protected $_formated = false; + public function beforeSave($object) { - $value = $this->formatDate($object->getData($this->getAttribute()->getName())); - $object->setData($this->getAttribute()->getName(), $value); + if (!$this->_formated) { + $value = $this->formatDate($object->getData($this->getAttribute()->getName())); + $object->setData($this->getAttribute()->getName(), $value); + } } /** @@ -57,6 +66,7 @@ public function formatDate($date) null, false ); } + $this->_formated = true; return $date->toString(Varien_Date::DATETIME_INTERNAL_FORMAT); } diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php index 0e17167f36..c206591980 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php @@ -151,4 +151,16 @@ public function getOption($optionId) return false; } + /** + * Retrieve Input Renderer Class + * + * @return string + */ + public function getInputRendererClass() { + if ($className = $this->getAttribute()->getData('frontend_input_renderer')) { + return Mage::getConfig()->getBlockClassName($className); + } + return null; + } + } diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Abstract.php index 2a19a853a4..c9e04e535d 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Abstract.php @@ -100,4 +100,46 @@ public function getOptionId($value) } return null; } + + /** + * Add Value Sort To Collection Select + * + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @param string $dir direction + * @return Mage_Eav_Model_Entity_Attribute_Source_Abstract + */ + public function addValueSortToCollection($collection, $dir = 'asc') { + return $this; + } + + /** + * Retrieve Column(s) for Flat + * + * @return array + */ + public function getFlatColums() + { + return array(); + } + + /** + * Retrieve Indexes(s) for Flat + * + * @return array + */ + public function getFlatIndexes() + { + return array(); + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return null; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Boolean.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Boolean.php index a0095db0a9..e301998819 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Boolean.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Boolean.php @@ -27,6 +27,11 @@ class Mage_Eav_Model_Entity_Attribute_Source_Boolean extends Mage_Eav_Model_Entity_Attribute_Source_Abstract { + /** + * Retrieve all options array + * + * @return array + */ public function getAllOptions() { if (is_null($this->_options)) { @@ -44,6 +49,20 @@ public function getAllOptions() return $this->_options; } + /** + * Retrieve option array + * + * @return array + */ + public function getOptionArray() + { + $_options = array(); + foreach ($this->getAllOptions() as $option) { + $_options[$option['value']] = $option['label']; + } + return $_options; + } + /** * Get a text for option value * @@ -60,4 +79,45 @@ public function getOptionText($value) } return false; } -} \ No newline at end of file + + /** + * Retrieve Column(s) for Flat + * + * @return array + */ + public function getFlatColums() + { + $columns = array(); + $columns[$this->getAttribute()->getAttributeCode()] = array( + 'type' => 'int', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + + return $columns; + } + + /** + * Retrieve Indexes(s) for Flat + * + * @return array + */ + public function getFlatIndexes() + { + return array(); + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return Mage::getResourceModel('eav/entity_attribute') + ->getFlatUpdateSelect($this->getAttribute(), $store); + } +} diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Interface.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Interface.php index f78e59813e..a82956b745 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Interface.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Interface.php @@ -27,13 +27,24 @@ /** * Entity attribute select source interface - * + * * Source is providing the selection options for user interface * */ interface Mage_Eav_Model_Entity_Attribute_Source_Interface { + /** + * Retrieve All options + * + * @return array + */ public function getAllOptions(); + /** + * Retrieve Option value text + * + * @param string $value + * @return mixed + */ public function getOptionText($value); } \ No newline at end of file diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php index 9cd5db8fc6..0dadda2c00 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Table.php @@ -100,4 +100,115 @@ public function getOptionText($value) return false; } } + + /** + * Add Value Sort To Collection Select + * + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @param string $dir + * + * @return Mage_Eav_Model_Entity_Attribute_Source_Table + */ + public function addValueSortToCollection($collection, $dir = 'asc') + { + $valueTable1 = $this->getAttribute()->getAttributeCode() . '_t1'; + $valueTable2 = $this->getAttribute()->getAttributeCode() . '_t2'; + $collection->getSelect() + ->joinLeft( + array($valueTable1 => $this->getAttribute()->getBackend()->getTable()), + "`e`.`entity_id`=`{$valueTable1}`.`entity_id`" + . " AND `{$valueTable1}`.`attribute_id`='{$this->getAttribute()->getId()}'" + . " AND `{$valueTable1}`.`store_id`='0'", + array()) + ->joinLeft( + array($valueTable2 => $this->getAttribute()->getBackend()->getTable()), + "`e`.`entity_id`=`{$valueTable2}`.`entity_id`" + . " AND `{$valueTable2}`.`attribute_id`='{$this->getAttribute()->getId()}'" + . " AND `{$valueTable2}`.`store_id`='{$collection->getStoreId()}'", + array() + ); + $valueExpr = new Zend_Db_Expr("IFNULL(`{$valueTable2}`.`value`, `{$valueTable1}`.`value`)"); + + Mage::getResourceModel('eav/entity_attribute_option') + ->addOptionValueToCollection($collection, $this->getAttribute(), $valueExpr); + + $collection->getSelect() + ->order("{$this->getAttribute()->getAttributeCode()} {$dir}"); + + return $this; + } + + /** + * Retrieve Column(s) for Flat + * + * @return array + */ + public function getFlatColums() + { + $columns = array(); + $columns[$this->getAttribute()->getAttributeCode()] = array( + 'type' => 'int', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + if ($this->getAttribute()->getFrontend()->getInputType() != 'multiselect') { + $columns[$this->getAttribute()->getAttributeCode() . '_value'] = array( + 'type' => 'varchar(255)', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + } + + return $columns; + } + + /** + * Retrieve Indexes for Flat + * + * @return array + */ + public function getFlatIndexes() + { + $indexes = array(); + + $filterable = $this->getAttribute()->getIsFilterable() + or $this->getAttribute()->getIsFilterableInSearch(); + $sortable = $this->getAttribute()->getUsedForSortBy(); + + if ($filterable or $sortable) { + if ($sortable and $this->getAttribute()->getFrontend()->getInputType() != 'multiselect') { + $index = 'IDX_' . strtoupper($this->getAttribute()->getAttributeCode()) . '_VALUE'; + $indexes[$index] = array( + 'type' => 'index', + 'fields' => array($this->getAttribute()->getAttributeCode() . '_value') + ); + } + if ($filterable) { + $index = 'IDX_' . strtoupper($this->getAttribute()->getAttributeCode()); + $indexes[$index] = array( + 'type' => 'index', + 'fields' => array($this->getAttribute()->getAttributeCode()) + ); + } + } + + return $indexes; + } + + /** + * Retrieve Select For Flat Attribute update + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return Mage::getResourceModel('eav/entity_attribute_option') + ->getFlatUpdateSelect($this->getAttribute(), $store); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php b/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php index 4a01e6b781..d51934b7b8 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php +++ b/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php @@ -34,7 +34,20 @@ */ class Mage_Eav_Model_Entity_Collection_Abstract extends Varien_Data_Collection_Db { - protected $_itemsById = array(); + /** + * Array of items with item id key + * + * @var array + */ + protected $_itemsById = array(); + + /** + * Entity static fields + * + * @var array + */ + protected $_staticFields = array(); + /** * Entity object to define collection's attributes * @@ -42,7 +55,12 @@ class Mage_Eav_Model_Entity_Collection_Abstract extends Varien_Data_Collection_D */ protected $_entity; - protected $_selectEntityTypes=array(); + /** + * Entity types to be fetched for objects in collection + * + * @var array + */ + protected $_selectEntityTypes = array(); /** * Attributes to be fetched for objects in collection @@ -58,8 +76,25 @@ class Mage_Eav_Model_Entity_Collection_Abstract extends Varien_Data_Collection_D */ protected $_filterAttributes=array(); + /** + * Joined entities + * + * @var array + */ protected $_joinEntities = array(); + + /** + * Joined attributes + * + * @var array + */ protected $_joinAttributes = array(); + + /** + * Joined fields data + * + * @var array + */ protected $_joinFields = array(); /** @@ -72,6 +107,7 @@ public function __construct($resource=null) parent::__construct(); $this->_construct(); $this->setConnection($this->getEntity()->getReadConnection()); + $this->_prepareStaticFields(); $this->_initSelect(); } @@ -88,6 +124,19 @@ public function getTable($table) return $this->getResource()->getTable($table); } + /** + * Prepare static entity fields + * + * @return Mage_Eav_Model_Entity_Collection_Abstract + */ + protected function _prepareStaticFields() + { + foreach ($this->getEntity()->getDefaultAttributes() as $field) { + $this->_staticFields[$field] = $field; + } + return $this; + } + protected function _initSelect() { $this->getSelect()->from(array('e'=>$this->getEntity()->getEntityTable())); @@ -109,7 +158,7 @@ protected function _init($model, $entityModel=null) if (is_null($entityModel)) { $entityModel = $model; } - $entity = Mage::getResourceModel($entityModel); + $entity = Mage::getResourceSingleton($entityModel); $this->setEntity($entity); return $this; } @@ -158,8 +207,8 @@ public function getResource() /** * Set template object for the collection * - * @param Varien_Object $object - * @return Mage_Eav_Model_Entity_Collection_Abstract + * @param Varien_Object $object + * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function setObject($object=null) { @@ -260,7 +309,8 @@ public function addAttributeToFilter($attribute, $condition=null, $joinType='inn * @param mixed $attribute * @param mixed $condition */ - public function addFieldToFilter($attribute, $condition=null){ + public function addFieldToFilter($attribute, $condition=null) + { return $this->addAttributeToFilter($attribute, $condition); } @@ -277,6 +327,9 @@ public function addAttributeToSort($attribute, $dir='asc') $this->getSelect()->order($this->_getAttributeFieldName($attribute).' '.$dir); return $this; } + if (isset($this->_staticFields[$attribute])) { + $this->getSelect()->order("e.{$attribute} {$dir}"); + } if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; $entityField = $this->_getAttributeTableAlias($attribute).'.'.$attrInstance->getAttributeCode(); @@ -291,11 +344,9 @@ public function addAttributeToSort($attribute, $dir='asc') $this->_addAttributeJoin($attribute, 'left'); if (isset($this->_joinAttributes[$attribute])) { $this->getSelect()->order($attribute.' '.$dir); - } - else { + } else { $this->getSelect()->order($this->_getAttributeTableAlias($attribute).'.value '.$dir); } - // } } return $this; @@ -306,18 +357,20 @@ public function addAttributeToSort($attribute, $dir='asc') * * If $attribute=='*' select all attributes * - * @param array|string|integer|Mage_Core_Model_Config_Element $attribute - * @return Mage_Eav_Model_Entity_Collection_Abstract + * @param array|string|integer|Mage_Core_Model_Config_Element $attribute + * @param false|string $joinType flag for joining attribute + * @return Mage_Eav_Model_Entity_Collection_Abstract */ public function addAttributeToSelect($attribute, $joinType=false) { if (is_array($attribute)) { + Mage::getSingleton('eav/config')->loadCollectionAttributes($this->getEntity()->getType(), $attribute); foreach ($attribute as $a) { $this->addAttributeToSelect($a, $joinType); } return $this; } - if ($joinType!==false && !$this->getEntity()->getAttribute($attribute)->getBackend()->isStatic()) { + if ($joinType!==false && !$this->getEntity()->getAttribute($attribute)->isStatic()) { $this->_addAttributeJoin($attribute, $joinType); } elseif ('*'===$attribute) { $attributes = $this->getEntity() @@ -330,7 +383,8 @@ public function addAttributeToSelect($attribute, $joinType=false) if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; } else { - $attrInstance = $this->getEntity()->getAttribute($attribute); + //$attrInstance = $this->getEntity()->getAttribute($attribute); + $attrInstance = Mage::getSingleton('eav/config')->getCollectionAttribute($this->getEntity()->getType(), $attribute); } if (empty($attrInstance)) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid attribute requested: %s', (string)$attribute)); @@ -348,6 +402,20 @@ public function addEntityTypeToSelect($entityType, $prefix) return $this; } + /** + * Add field to static + * + * @param string $field + * @return Mage_Eav_Model_Entity_Collection_Abstract + */ + public function addStaticField($field) + { + if (!isset($this->_staticFields[$field])) { + $this->_staticFields[$field] = $field; + } + return $this; + } + /** * Add attribute expression (SUM, COUNT, etc) * @@ -374,13 +442,18 @@ public function addExpressionAttributeToSelect($alias, $expression, $attribute) $fullExpression = $expression; // Replacing multiple attributes foreach($attribute as $attributeItem) { - $attributeInstance = $this->getAttribute($attributeItem); + if (isset($this->_staticFields[$attributeItem])) { + $attrField = sprintf('e.%s', $attributeItem); + } + else { + $attributeInstance = $this->getAttribute($attributeItem); - if ($attributeInstance->getBackend()->isStatic()) { - $attrField = 'e.' . $attributeItem; - } else { - $this->_addAttributeJoin($attributeItem, 'left'); - $attrField = $this->_getAttributeFieldName($attributeItem); + if ($attributeInstance->getBackend()->isStatic()) { + $attrField = 'e.' . $attributeItem; + } else { + $this->_addAttributeJoin($attributeItem, 'left'); + $attrField = $this->_getAttributeFieldName($attributeItem); + } } $fullExpression = str_replace('{{attribute}}', $attrField, $fullExpression); @@ -415,6 +488,11 @@ public function groupByAttribute($attribute) return $this; } + if (isset($this->_staticFields[$attribute])) { + $this->getSelect()->group(sprintf('e.%s', $attribute)); + return $this; + } + if (isset($this->_joinAttributes[$attribute])) { $attrInstance = $this->_joinAttributes[$attribute]['attribute']; $entityField = $this->_getAttributeTableAlias($attribute).'.'.$attrInstance->getAttributeCode(); @@ -467,7 +545,7 @@ public function joinAttribute($alias, $attribute, $bind, $filter=null, $joinType $bindAttribute = $this->getAttribute($bind); } - if (!$bindAttribute || (!$bindAttribute->getBackend()->isStatic() && !$bindAttribute->getId())) { + if (!$bindAttribute || (!$bindAttribute->isStatic() && !$bindAttribute->getId())) { throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid foreign key')); } @@ -697,17 +775,27 @@ public function load($printQuery = false, $logQuery = false) if ($this->isLoaded()) { return $this; } + Varien_Profiler::start('__EAV_COLLECTION_BEFORE_LOAD__'); $this->_beforeLoad(); + Varien_Profiler::stop('__EAV_COLLECTION_BEFORE_LOAD__'); + Varien_Profiler::start('__EAV_COLLECTION_LOAD_ENT__'); $this->_loadEntities($printQuery, $logQuery); + Varien_Profiler::stop('__EAV_COLLECTION_LOAD_ENT__'); + Varien_Profiler::start('__EAV_COLLECTION_LOAD_ATTR__'); $this->_loadAttributes($printQuery, $logQuery); + Varien_Profiler::stop('__EAV_COLLECTION_LOAD_ATTR__'); + Varien_Profiler::start('__EAV_COLLECTION_ORIG_DATA__'); foreach ($this->_items as $item) { $item->setOrigData(); } + Varien_Profiler::stop('__EAV_COLLECTION_ORIG_DATA__'); $this->_setIsLoaded(); + Varien_Profiler::start('__EAV_COLLECTION_AFTER_LOAD__'); $this->_afterLoad(); + Varien_Profiler::stop('__EAV_COLLECTION_AFTER_LOAD__'); return $this; } @@ -833,7 +921,7 @@ public function setRowIdFieldName($fieldName) public function _loadEntities($printQuery = false, $logQuery = false) { $entity = $this->getEntity(); - $entityIdField = $entity->getEntityIdField(); +// $entityIdField = $entity->getEntityIdField(); if ($this->_pageSize) { $this->getSelect()->limitPage($this->getCurPage(), $this->_pageSize); @@ -877,10 +965,18 @@ public function _loadAttributes($printQuery = false, $logQuery = false) $entity = $this->getEntity(); $entityIdField = $entity->getEntityIdField(); - foreach ($entity->getAttributesByTable() as $table=>$attributes) { + $tableAttributes = array(); + foreach ($this->_selectAttributes as $attributeCode => $attributeId) { + $attribute = Mage::getSingleton('eav/config')->getCollectionAttribute($entity->getType(), $attributeCode); + if ($attribute && !$attribute->isStatic()) { + $tableAttributes[$attribute->getBackendTable()][] = $attributeId; + } + } + + foreach ($tableAttributes as $table=>$attributes) { $select = $this->_getLoadAttributesSelect($table); try { - $values = $this->_fetchAll($select); + $values = $this->_fetchAll($select, $attributes); } catch (Exception $e) { Mage::printException($e, $select); $this->printLogQuery(true, true, $select); @@ -901,14 +997,17 @@ public function _loadAttributes($printQuery = false, $logQuery = false) * @param string $table * @return Mage_Eav_Model_Entity_Collection_Abstract */ - protected function _getLoadAttributesSelect($table) + protected function _getLoadAttributesSelect($table, $attributeIds=array()) { + if (empty($attributeIds)) { + $attributeIds = $this->_selectAttributes; + } $entityIdField = $this->getEntity()->getEntityIdField(); $select = $this->getConnection()->select() ->from($table, array($entityIdField, 'attribute_id', 'value')) ->where('entity_type_id=?', $this->getEntity()->getTypeId()) ->where("$entityIdField in (?)", array_keys($this->_itemsById)) - ->where('attribute_id in (?)', $this->_selectAttributes); + ->where('attribute_id in (?)', $attributeIds); return $select; } @@ -929,8 +1028,15 @@ protected function _setItemAttributeValue($valueInfo) Mage::helper('eav')->__('Data integrity: No header row found for attribute') ); } - $attributeCode = $this->getEntity()->getAttribute($valueInfo['attribute_id']) - ->getAttributeCode(); + $attributeCode = array_search($valueInfo['attribute_id'], $this->_selectAttributes); + if (!$attributeCode) { + $attribute = Mage::getSingleton('eav/config')->getCollectionAttribute( + $this->getEntity()->getType(), + $valueInfo['attribute_id'] + ); + $attributeCode = $attribute->getAttributeCode(); + } + foreach ($this->_itemsById[$entityId] as $object) { $object->setData($attributeCode, $valueInfo['value']); } @@ -953,6 +1059,9 @@ protected function _getAttributeFieldName($attributeCode) if (isset($this->_joinAttributes[$attributeCode]['condition_alias'])) { return $this->_joinAttributes[$attributeCode]['condition_alias']; } + if (isset($this->_staticFields[$attributeCode])) { + return sprintf('e.%s', $attributeCode); + } if (isset($this->_joinFields[$attributeCode])) { $attr = $this->_joinFields[$attributeCode]; return $attr['table'] ? $attr['table'] .'.'.$attr['field'] : $attr['field']; @@ -963,7 +1072,7 @@ protected function _getAttributeFieldName($attributeCode) throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Invalid attribute name: %s', $attributeCode)); } - if ($attribute->getBackend()->isStatic()) { + if ($attribute->isStatic()) { if (isset($this->_joinAttributes[$attributeCode])) { $fieldName = $this->_getAttributeTableAlias($attributeCode).'.'.$attributeCode; } else { @@ -1086,6 +1195,9 @@ protected function _getAttributeConditionSql($attribute, $condition, $joinType=' if (isset($this->_joinFields[$attribute])) { return $this->_getConditionSql($this->_getAttributeFieldName($attribute), $condition); } + if (isset($this->_staticFields[$attribute])) { + return $this->_getConditionSql(sprintf('e.%s', $attribute), $condition); + } // process linked attribute if (isset($this->_joinAttributes[$attribute])) { $entity = $this->getAttribute($attribute)->getEntity(); diff --git a/app/code/core/Mage/Eav/Model/Entity/Setup.php b/app/code/core/Mage/Eav/Model/Entity/Setup.php index f1e63bc2e4..384aa72526 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Setup.php +++ b/app/code/core/Mage/Eav/Model/Entity/Setup.php @@ -20,23 +20,41 @@ * * @category Mage * @package Mage_Eav - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ +/** + * EAV Entity Setup Model + * + * @category Mage + * @package Mage_Eav + * @author Magento Core Team + */ class Mage_Eav_Model_Entity_Setup extends Mage_Core_Model_Resource_Setup { + protected $_attributeTableFields; protected $_generalGroupName = 'General'; public $defaultGroupIdAssociations = array('General'=>1); + /** + * Clean cache + * + * @return Mage_Eav_Model_Entity_Setup + */ public function cleanCache() { Mage::app()->cleanCache(array('eav')); return $this; } + /** + * Install Default Group Ids + * + * @return Mage_Eav_Model_Entity_Setup + */ public function installDefaultGroupIds() { $setIds = $this->getAllAttributeSetIds(); @@ -56,6 +74,7 @@ public function installDefaultGroupIds() ); } } + return $this; } @@ -96,10 +115,10 @@ public function addEntityType($code, array $params) /** * Update entity row * - * @param unknown_type $code - * @param unknown_type $field - * @param unknown_type $value - * @return unknown + * @param string $code + * @param string $field + * @param string $value + * @return Mage_Eav_Model_Entity_Setup */ public function updateEntityType($code, $field, $value=null) { @@ -110,6 +129,13 @@ public function updateEntityType($code, $field, $value=null) return $this; } + /** + * Retrieve Entity Type Data + * + * @param int|string $id + * @param string $field + * @return mixed + */ public function getEntityType($id, $field=null) { return $this->getTableRow('eav/entity_type', @@ -118,6 +144,12 @@ public function getEntityType($id, $field=null) ); } + /** + * Retrieve Entity Type Id By Id or Code + * + * @param mixed $entityTypeId + * @return int + */ public function getEntityTypeId($entityTypeId) { if (!is_numeric($entityTypeId)) { @@ -129,6 +161,12 @@ public function getEntityTypeId($entityTypeId) return $entityTypeId; } + /** + * Remove entity type by Id or Code + * + * @param mixed $id + * @return Mage_Eav_Model_Entity_Setup + */ public function removeEntityType($id) { if (is_numeric($id)) { @@ -146,6 +184,13 @@ public function removeEntityType($id) /******************* ATTRIBUTE SETS *****************/ + /** + * Retrieve Attribute Set Sort order + * + * @param mixed $entityTypeId + * @param int $sortOrder + * @return int + */ public function getAttributeSetSortOrder($entityTypeId, $sortOrder=null) { if (!is_numeric($sortOrder)) { @@ -158,6 +203,14 @@ public function getAttributeSetSortOrder($entityTypeId, $sortOrder=null) return $sortOrder; } + /** + * Add Attribute Set + * + * @param mixed $entityTypeId + * @param string $name + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ public function addAttributeSet($entityTypeId, $name, $sortOrder=null) { $data = array( @@ -177,6 +230,15 @@ public function addAttributeSet($entityTypeId, $name, $sortOrder=null) return $this; } + /** + * Update attribute set data + * + * @param mixed $entityTypeId + * @param int $id + * @param string $field + * @param mixed $value + * @return Mage_Eav_Model_Entity_Setup + */ public function updateAttributeSet($entityTypeId, $id, $field, $value=null) { $this->updateTableRow('eav/attribute_set', @@ -187,6 +249,14 @@ public function updateAttributeSet($entityTypeId, $id, $field, $value=null) return $this; } + /** + * Retrieve Attribute set data by id or name + * + * @param mixed $entityTypeId + * @param mixed $id + * @param string $field + * @return mixed + */ public function getAttributeSet($entityTypeId, $id, $field=null) { return $this->getTableRow('eav/attribute_set', @@ -196,6 +266,14 @@ public function getAttributeSet($entityTypeId, $id, $field=null) ); } + /** + * Retrieve Attribute Set Id By Id or Name + * + * @throws Mage_Eav_Exception + * @param mixed $entityTypeId + * @param mixed $setId + * @return int + */ public function getAttributeSetId($entityTypeId, $setId) { if (!is_numeric($setId)) { @@ -207,6 +285,13 @@ public function getAttributeSetId($entityTypeId, $setId) return $setId; } + /** + * Remove Attribute Set + * + * @param mixed $entityTypeId + * @param mixed $id + * @return Mage_Eav_Model_Entity_Setup + */ public function removeAttributeSet($entityTypeId, $id) { $this->_conn->delete($this->getTable('eav/attribute_set'), @@ -215,16 +300,59 @@ public function removeAttributeSet($entityTypeId, $id) return $this; } - public function setDefaultSetToEntityType($entityType) + /** + * Set Default Attribute Set to Entity Type + * + * @param mixed $entityType + * @return Mage_Eav_Model_Entity_Setup + */ + public function setDefaultSetToEntityType($entityType, $attributeSet = 'Default') { $entityTypeId = $this->getEntityTypeId($entityType); - $setId = $this->getAttributeSetId($entityTypeId, 'Default'); + $setId = $this->getAttributeSetId($entityTypeId, $attributeSet); $this->updateEntityType($entityTypeId, 'default_attribute_set_id', $setId); return $this; } + /** + * Get identifiers of all attribute sets + * + * @return array + */ + public function getAllAttributeSetIds($entityTypeId=null) + { + $where = ''; + if (!is_null($entityTypeId)) { + $where = " WHERE `entity_type_id` = '" . $this->getEntityTypeId($entityTypeId) . "'"; + } + $sql = "SELECT `attribute_set_id` FROM `{$this->getTable('eav/attribute_set')}`" . $where; + return $this->_conn->fetchCol($sql); + } + + /** + * Retrieve Default Attribute Set for Entity Type + * + * @param string|int $entityType + * @return int + */ + public function getDefaultAttributeSetId($entityType) + { + $select = $this->getConnection()->select() + ->from($this->getTable('eav/entity_type'), 'default_attribute_set_id') + ->where(is_numeric($entityType) ? 'entity_type_id=?' : 'entity_type_code=?', $entityType); + return $this->getConnection()->fetchOne($select); + } + /******************* ATTRIBUTE GROUPS *****************/ + /** + * Retrieve Attribute Group Sort order + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param int $sortOrder + * @return int + */ public function getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder=null) { if (!is_numeric($sortOrder)) { @@ -237,6 +365,15 @@ public function getAttributeGroupSortOrder($entityTypeId, $setId, $sortOrder=nul return $sortOrder; } + /** + * Add Attribute Group + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param string $name + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ public function addAttributeGroup($entityTypeId, $setId, $name, $sortOrder=null) { $setId = $this->getAttributeSetId($entityTypeId, $setId); @@ -263,6 +400,16 @@ public function addAttributeGroup($entityTypeId, $setId, $name, $sortOrder=null) return $this; } + /** + * Update Attribute Group Data + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $id + * @param string $field + * @param mixed $value + * @return Mage_Eav_Model_Entity_Setup + */ public function updateAttributeGroup($entityTypeId, $setId, $id, $field, $value=null) { $this->updateTableRow('eav/attribute_group', @@ -273,6 +420,15 @@ public function updateAttributeGroup($entityTypeId, $setId, $id, $field, $value= return $this; } + /** + * Retrieve Attribute Group Data + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $id + * @param string $field + * @return mixed + */ public function getAttributeGroup($entityTypeId, $setId, $id, $field=null) { $searchId = $id; @@ -293,6 +449,14 @@ public function getAttributeGroup($entityTypeId, $setId, $id, $field=null) ); } + /** + * Retrieve Attribute Group Id by Id or Name + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $groupId + * @return Mage_Eav_Model_Entity_Setup + */ public function getAttributeGroupId($entityTypeId, $setId, $groupId) { if (!is_numeric($groupId)) { @@ -304,6 +468,14 @@ public function getAttributeGroupId($entityTypeId, $setId, $groupId) return $groupId; } + /** + * Remove Attribute Group By Id or Name + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $id + * @return Mage_Eav_Model_Entity_Setup + */ public function removeAttributeGroup($entityTypeId, $setId, $id) { $this->_conn->delete($this->getTable('eav/attribute_group'), @@ -312,8 +484,43 @@ public function removeAttributeGroup($entityTypeId, $setId, $id) return $this; } + /** + * Retrieve Default Attribute Group Id By Entity Type and Attribute Set + * + * @param string|int $entityType + * @param int $attributeSetId + * @return int + */ + public function getDefaultAttributeGroupId($entityType, $attributeSetId = null) + { + $entityType = $this->getEntityTypeId($entityType); + if (!is_numeric($attributeSetId)) { + $attributeSetId = $this->getDefaultAttributeSetId($entityType); + } + + $select = $this->getConnection()->select() + ->from($this->getTable('eav/attribute_group'), 'attribute_group_id') + ->where('attribute_set_id=?', $attributeSetId) + ->order('default_id DESC, sort_order') + ->limit(1); + return $this->getConnection()->fetchOne($select); + } + /******************* ATTRIBUTES *****************/ + /** + * Retrieve value from array by key or return default value + * + * @param array $array + * @param string $key + * @param string $default + * @return string + */ + protected function _getValue($array, $key, $default = null) + { + return isset($array[$key]) ? $array[$key] : $default; + } + /** * Add attribute to an entity type * @@ -328,32 +535,37 @@ public function addAttribute($entityTypeId, $code, array $attr) { $entityTypeId = $this->getEntityTypeId($entityTypeId); $data = array( - 'entity_type_id' => $entityTypeId, - 'attribute_code' => $code, - 'backend_model' => isset($attr['backend']) ? $attr['backend'] : '', - 'backend_type' => isset($attr['type']) ? $attr['type'] : 'varchar', - 'backend_table' => isset($attr['table']) ? $attr['table'] : '', - 'frontend_model' => isset($attr['frontend']) ? $attr['frontend'] : '', -// 'frontend_block' => isset($attr['frontend_block']) ? $attr['frontend_block'] : '', - 'frontend_input' => isset($attr['input']) ? $attr['input'] : 'text', - 'frontend_label' => isset($attr['label']) ? $attr['label'] : '', - 'source_model' => isset($attr['source']) ? $attr['source'] : '', - 'is_global' => isset($attr['global']) ? $attr['global'] : 1, - 'is_visible' => isset($attr['visible']) ? (int) $attr['visible'] : 1, - 'is_required' => isset($attr['required']) ? $attr['required'] : 1, - 'is_user_defined' => isset($attr['user_defined']) ? $attr['user_defined'] : 0, - 'default_value' => isset($attr['default']) ? $attr['default'] : '', - 'is_searchable' => isset($attr['searchable']) ? $attr['searchable'] : 0, - 'is_filterable' => isset($attr['filterable']) ? $attr['filterable'] : 0, - 'is_comparable' => isset($attr['comparable']) ? $attr['comparable'] : 0, - 'is_visible_on_front' => isset($attr['visible_on_front']) ? $attr['visible_on_front'] : 0, - 'is_html_allowed_on_front' => isset($attr['is_html_allowed_on_front']) ? $attr['is_html_allowed_on_front'] : 0, - 'is_visible_in_advanced_search' => isset($attr['visible_in_advanced_search']) ? $attr['visible_in_advanced_search'] : 0, - 'is_unique' => isset($attr['unique']) ? $attr['unique'] : 0, - 'apply_to' => isset($attr['apply_to']) ? $attr['apply_to'] : '', - 'is_configurable' => isset($attr['is_configurable']) ? $attr['is_configurable'] : 1, - 'note' => isset($attr['note']) ? $attr['note'] : '', - 'position' => isset($attr['position']) ? $attr['position'] : 0, + 'entity_type_id' => $entityTypeId, + 'attribute_code' => $code, + 'backend_model' => $this->_getValue($attr, 'backend', ''), + 'backend_type' => $this->_getValue($attr, 'type', 'varchar'), + 'backend_table' => $this->_getValue($attr, 'table', ''), + 'frontend_model' => $this->_getValue($attr, 'frontend', ''), + 'frontend_input' => $this->_getValue($attr, 'input', 'text'), + 'frontend_input_renderer' => $this->_getValue($attr, 'input_renderer', ''), + 'frontend_label' => $this->_getValue($attr, 'label', ''), + 'source_model' => $this->_getValue($attr, 'source', ''), + 'is_global' => $this->_getValue($attr, 'global', 1), + 'is_visible' => $this->_getValue($attr, 'visible', 1), + 'is_required' => $this->_getValue($attr, 'required', 1), + 'is_user_defined' => $this->_getValue($attr, 'user_defined', 0), + 'default_value' => $this->_getValue($attr, 'default', ''), + 'is_searchable' => $this->_getValue($attr, 'searchable', 0), + 'is_filterable' => $this->_getValue($attr, 'filterable', 0), + 'is_comparable' => $this->_getValue($attr, 'comparable', 0), + 'is_visible_on_front' => $this->_getValue($attr, 'visible_on_front', 0), + 'is_html_allowed_on_front' => $this->_getValue($attr, 'is_html_allowed_on_front', 0), + 'is_visible_in_advanced_search' + => $this->_getValue($attr, 'visible_in_advanced_search', 0), + 'is_used_for_price_rules' => $this->_getValue($attr, 'used_for_price_rules', 1), + 'is_filterable_in_search' => $this->_getValue($attr, 'filterable_in_search', 0), + 'used_in_product_listing' => $this->_getValue($attr, 'used_in_product_listing', 0), + 'used_for_sort_by' => $this->_getValue($attr, 'used_for_sort_by', 0), + 'is_unique' => $this->_getValue($attr, 'unique', 0), + 'apply_to' => $this->_getValue($attr, 'apply_to', ''), + 'is_configurable' => $this->_getValue($attr, 'is_configurable', 1), + 'note' => $this->_getValue($attr, 'note', ''), + 'position' => $this->_getValue($attr, 'position', 0), ); $sortOrder = isset($attr['sort_order']) ? $attr['sort_order'] : null; @@ -361,7 +573,7 @@ public function addAttribute($entityTypeId, $code, array $attr) if ($id = $this->getAttribute($entityTypeId, $code, 'attribute_id')) { $this->updateAttribute($entityTypeId, $id, $data, null, $sortOrder); } else { - $this->_conn->insert($this->getTable('eav/attribute'), $data); + $this->_insertAttribute($data); } if (!empty($attr['group'])) { @@ -387,6 +599,11 @@ public function addAttribute($entityTypeId, $code, array $attr) return $this; } + /** + * Add Attribure Option + * + * @param array $option + */ public function addAttributeOption($option) { if (isset($option['value'])) { @@ -435,6 +652,16 @@ public function addAttributeOption($option) } } + /** + * Update Attribute data + * + * @param mixed $entityTypeId + * @param mixed $id + * @param string $field + * @param mixed $value + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ public function updateAttribute($entityTypeId, $id, $field, $value=null, $sortOrder=null) { if (!is_null($sortOrder)) { @@ -443,6 +670,26 @@ public function updateAttribute($entityTypeId, $id, $field, $value=null, $sortOr 'sort_order', $sortOrder ); } + + $attributeFields = $this->_getAttributeTableFields(); + if (is_array($field)) { + $bind = array(); + foreach ($field as $k => $v) { + if (isset($attributeFields[$k])) { + $bind[$k] = $v; + } + } + if (!$bind) { + return $this; + } + $field = $bind; + } + else { + if (!isset($attributeFields[$field])) { + return $this; + } + } + $this->updateTableRow('eav/attribute', 'attribute_id', $this->getAttributeId($entityTypeId, $id), $field, $value, @@ -451,6 +698,14 @@ public function updateAttribute($entityTypeId, $id, $field, $value=null, $sortOr return $this; } + /** + * Retrieve Attribute Data By Id or Code + * + * @param mixed $entityTypeId + * @param mixed $id + * @param string $field + * @return mixed + */ public function getAttribute($entityTypeId, $id, $field=null) { return $this->getTableRow('eav/attribute', @@ -460,6 +715,13 @@ public function getAttribute($entityTypeId, $id, $field=null) ); } + /** + * Retrieve Attribute Id Data By Id or Code + * + * @param mixed $entityTypeId + * @param mixed $id + * @return int + */ public function getAttributeId($entityTypeId, $id) { if (!is_numeric($id)) { @@ -506,6 +768,13 @@ public function getAttributeTable($entityTypeId, $id) return false; } + /** + * Remove Attribute + * + * @param mixed $entityTypeId + * @param mixed $code + * @return Mage_Eav_Model_Entity_Setup + */ public function removeAttribute($entityTypeId, $code) { if ($attributeId = $this->getAttributeId($entityTypeId, $code)) { @@ -516,6 +785,15 @@ public function removeAttribute($entityTypeId, $code) return $this; } + /** + * Retrieve Attribute Sort Order + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $groupId + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ public function getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder=null) { if (!is_numeric($sortOrder)) { @@ -528,6 +806,16 @@ public function getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrde return $sortOrder; } + /** + * Add Attribute to All Groups on Attribute Set + * + * @param mixed $entityTypeId + * @param mixed $setId + * @param mixed $groupId + * @param mixed $attributeId + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ public function addAttributeToSet($entityTypeId, $setId, $groupId, $attributeId, $sortOrder=null) { $entityTypeId = $this->getEntityTypeId($entityTypeId); @@ -546,18 +834,82 @@ public function addAttributeToSet($entityTypeId, $setId, $groupId, $attributeId, return $this; } $this->_conn->insert($this->getTable('eav/entity_attribute'), array( - 'entity_type_id'=>$entityTypeId, - 'attribute_set_id'=>$setId, + 'entity_type_id' =>$entityTypeId, + 'attribute_set_id' =>$setId, 'attribute_group_id'=>$groupId, - 'attribute_id'=>$attributeId, - 'sort_order'=>$this->getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder), + 'attribute_id' =>$attributeId, + 'sort_order' =>$this->getAttributeSortOrder($entityTypeId, $setId, $groupId, $sortOrder), )); return $this; } + /** + * Add or update attribute to group + * + * @param int|string $entityType + * @param int|string $setId + * @param int|string $groupId + * @param int|string $attributeId + * @param int $sortOrder + * @return Mage_Eav_Model_Entity_Setup + */ + public function addAttributeToGroup($entityType, $setId, $groupId, $attributeId, $sortOrder = null) + { + $entityType = $this->getEntityTypeId($entityType); + $setId = $this->getAttributeSetId($entityType, $setId); + $groupId = $this->getAttributeGroupId($entityType, $setId, $groupId); + $attributeId = $this->getAttributeId($entityType, $attributeId); + + $bind = array( + 'entity_type_id' => $entityType, + 'attribute_set_id' => $setId, + 'attribute_group_id' => $groupId, + 'attribute_id' => $attributeId, + ); + + $select = $this->getConnection()->select() + ->from($this->getTable('eav/entity_attribute')) + ->where('entity_type_id=?', $entityType) + ->where('attribute_set_id=?', $setId) + ->where('attribute_id=?', $attributeId); + $row = $this->getConnection()->fetchRow($select); + if ($row) { + // update + if (!is_null($sortOrder)) { + $bind['sort_order'] = $sortOrder; + } + + $this->getConnection()->update( + $this->getTable('eav/entity_attribute'), + $bind, + $this->getConnection()->quoteInto('entity_attribute_id=?', $row['entity_attribute_id']) + ); + } + else { + if (is_null($sortOrder)) { + $select = $this->getConnection()->select() + ->from($this->getTable('eav/entity_attribute'), 'MAX(sort_order) + 10') + ->where('entity_type_id=?', $entityType) + ->where('attribute_set_id=?', $setId) + ->where('attribute_group_id=?', $groupId); + $sortOrder = $this->getConnection()->fetchOne($select); + } + $bind['sort_order'] = $sortOrder; + $this->getConnection()->insert($this->getTable('eav/entity_attribute'), $bind); + } + + return $this; + } + /******************* BULK INSTALL *****************/ + /** + * Install entities + * + * @param array $entities + * @return Mage_Eav_Model_Entity_Setup + */ public function installEntities($entities=null) { $this->cleanCache(); @@ -691,17 +1043,34 @@ public function createEntityTables($baseName, array $options=array()) } /** - * Get identifiers of all attribute sets + * Retrieve attribute table fields * * @return array */ - public function getAllAttributeSetIds($entityTypeId=null) - { - $where = ''; - if (!is_null($entityTypeId)) { - $where = " WHERE `entity_type_id` = '" . $this->getEntityTypeId($entityTypeId) . "'"; + protected function _getAttributeTableFields() { + return $this->getConnection()->describeTable($this->getTable('eav/attribute')); + } + + /** + * Insert attribute and filter data + * + * @return Mage_Eav_Model_Entity_Setup + */ + protected function _insertAttribute(array $data) { + $bind = array(); + $fields = $this->_getAttributeTableFields(); + + foreach ($data as $k => $v) { + if (isset($fields[$k])) { + $bind[$k] = $v; + } } - $sql = "SELECT `attribute_set_id` FROM `{$this->getTable('eav/attribute_set')}`" . $where; - return $this->_conn->fetchCol($sql); + if (!$bind) { + return $this; + } + + $this->getConnection()->insert($this->getTable('eav/attribute'), $bind); + + return $this; } } \ No newline at end of file diff --git a/app/code/core/Mage/Eav/Model/Entity/Type.php b/app/code/core/Mage/Eav/Model/Entity/Type.php index 44da9e9304..57894492df 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Type.php +++ b/app/code/core/Mage/Eav/Model/Entity/Type.php @@ -170,7 +170,9 @@ public function fetchNewIncrementId($storeId=null) ->setPrefix($entityStoreConfig->getIncrementPrefix()) ->setPadLength($this->getIncrementPadLength()) ->setPadChar($this->getIncrementPadChar()) - ->setLastId($entityStoreConfig->getIncrementLastId()); + ->setLastId($entityStoreConfig->getIncrementLastId()) + ->setEntityTypeId($entityStoreConfig->getEntityTypeId()) + ->setStoreId($entityStoreConfig->getStoreId()); /** * do read lock on eav/entity_store to solve potential timing issues diff --git a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute.php b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute.php index 55d5277b5e..f30f45953b 100644 --- a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute.php +++ b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute.php @@ -385,4 +385,41 @@ public function getAttributeCodesByFrontendType($type) } } + /** + * Retrieve Select For Flat Attribute update + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param int $store + * @return Varien_Db_Select + */ + public function getFlatUpdateSelect(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $store) { + return $this->_getReadAdapter()->select() + ->joinLeft( + array('t1' => $attribute->getBackend()->getTable()), + "`e`.`entity_id`=`t1`.`entity_id` AND `e`.`child_id`=`t1`.`entity_id`", + array() + ) + ->joinLeft( + array('t2' => $attribute->getBackend()->getTable()), + "t2.entity_id = t1.entity_id" + . " AND t1.entity_type_id = t2.entity_type_id" + . " AND t1.attribute_id = t2.attribute_id" + . " AND t2.store_id = {$store}", + array($attribute->getAttributeCode() => "IFNULL(t2.value, t1.value)")) + ->where("t1.entity_type_id=?", $attribute->getEntityTypeId()) + ->where("t1.attribute_id=?", $attribute->getId()) + ->where("t1.store_id=?", 0) + ->where("e.is_child=?", 0); + } + + /** + * Describe table + * + * @param string $table + * @return array + */ + public function describeTable($table) { + return $this->_getReadAdapter()->describeTable($table); + } + } diff --git a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Collection.php b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Collection.php index e57b8cd475..c03889ef18 100644 --- a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Collection.php +++ b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Collection.php @@ -41,8 +41,7 @@ class Mage_Eav_Model_Mysql4_Entity_Attribute_Collection extends Mage_Core_Model_ protected $_addSetInfoFlag = false; /** - * Enter description here... - * + * Resource model initialization */ public function _construct() { @@ -50,11 +49,32 @@ public function _construct() } /** - * Enter description here... + * Specify select columns which are used for load arrtibute values * - * @param int $typeId * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ + public function useLoadDataFields() + { + $this->getSelect()->reset(Zend_Db_Select::COLUMNS); + $this->getSelect()->columns(array( + 'attribute_id', + 'entity_type_id', + 'attribute_code', + 'attribute_model', + 'backend_model', + 'backend_type', + 'backend_table', + 'is_global' + )); + return $this; + } + + /** + * Specify attribute entity type filter + * + * @param int $typeId + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + */ public function setEntityTypeFilter($typeId) { $this->getSelect()->where('main_table.entity_type_id=?', $typeId); @@ -62,10 +82,10 @@ public function setEntityTypeFilter($typeId) } /** - * Enter description here... + * Specify attribute set filter * - * @param int $setId - * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + * @param int $setId + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ public function setAttributeSetFilter($setId) { @@ -84,10 +104,11 @@ public function setAttributeSetFilter($setId) } /** - * Enter description here... + * Specify multiple attribute sets filter + * Result will be ordered by sort_order * - * @param array $setIds - * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + * @param array $setIds + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ public function setAttributeSetsFilter(array $setIds) { @@ -120,10 +141,10 @@ public function setInAllAttributeSetsFilter(array $setIds) } /** - * Enter description here... + * Add filter which exclude attributes assigned to attribute set * - * @param int $setId - * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + * @param int $setId + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ public function setAttributeSetExcludeFilter($setId) { @@ -134,23 +155,22 @@ public function setAttributeSetExcludeFilter($setId) } /** - * Enter description here... + * Exclude attributes filter * - * @param int $attributes - * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + * @param array $attributes + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ public function setAttributesExcludeFilter($attributes) { - #$this->join('entity_attribute', 'entity_attribute.attribute_id=main_table.attribute_id', 'sort_order'); $this->getSelect()->where('main_table.attribute_id NOT IN(?)', $attributes); return $this; } /** - * Enter description here... + * Filter by attribute group id * - * @param int $groupId - * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + * @param int $groupId + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ public function setAttributeGroupFilter($groupId) { @@ -161,7 +181,7 @@ public function setAttributeGroupFilter($groupId) } /** - * Enter description here... + * Declare group by attribute id condition for collection select * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -172,7 +192,7 @@ public function addAttributeGrouping() } /** - * Enter description here... + * Specify filter by "is_visible" field * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -183,7 +203,7 @@ public function addVisibleFilter() } /** - * Enter description here... + * Specify "is_filterable" filter * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -205,7 +225,7 @@ public function addIsFilterableInSearchFilter() } /** - * Enter description here... + * Specify "is_unique" filter as true * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -216,7 +236,7 @@ public function addIsUniqueFilter() } /** - * Enter description here... + * Specify "is_unique" filter as false * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -227,7 +247,7 @@ public function addIsNotUniqueFilter() } /** - * Enter description here... + * Specify "is_searchable" filter * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -238,7 +258,7 @@ public function addIsSearchableFilter() } /** - * Enter description here... + * Specify filter to select just attributes with options * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -255,7 +275,7 @@ public function addHasOptionsFilter() } /** - * Enter description here... + * Specify "is_visible_in_advanced_search" filter * * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection */ @@ -279,12 +299,23 @@ public function setFrontendInputTypeFilter($frontendInputType) return $this; } + /** + * Flag for adding information about attributes sets to result + * + * @param bool $flag + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + */ public function addSetInfo($flag=true) { $this->_addSetInfoFlag = $flag; return $this; } + /** + * Ad information about attribute sets to collection result data + * + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection + */ protected function _addSetInfo() { if ($this->_addSetInfoFlag) { @@ -331,6 +362,7 @@ protected function _addSetInfo() unset($attributeToSetInfo); unset($attributeIds); } + return $this; } protected function _afterLoadData() diff --git a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Group/Collection.php b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Group/Collection.php index 5edcd1e9bb..44371972b8 100644 --- a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Group/Collection.php +++ b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Group/Collection.php @@ -27,11 +27,21 @@ class Mage_Eav_Model_Mysql4_Entity_Attribute_Group_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract { + /** + * Init resource model for collection + * + */ public function _construct() { $this->_init('eav/entity_attribute_group'); } + /** + * Set Attribute Set Filter + * + * @param int $setId + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Group_Collection + */ public function setAttributeSetFilter($setId) { $this->getSelect()->where('main_table.attribute_set_id=?', $setId); diff --git a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Option.php b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Option.php index efaded96d6..6823144f0b 100644 --- a/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Option.php +++ b/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Option.php @@ -33,8 +33,86 @@ */ class Mage_Eav_Model_Mysql4_Entity_Attribute_Option extends Mage_Core_Model_Mysql4_Abstract { - public function _construct() + public function _construct() { $this->_init('eav/attribute_option', 'option_id'); } + + /** + * Add Join with option value for collection select + * + * @param Mage_Eav_Model_Entity_Collection_Abstract $collection + * @param Mage_Eav_Model_Entity_Attribute $attribute + * @param Zend_Db_Expr $valueExpr + * + * @return Mage_Eav_Model_Mysql4_Entity_Attribute_Option + */ + public function addOptionValueToCollection($collection, $attribute, $valueExpr) { + $attributeCode = $attribute->getAttributeCode(); + $optionTable1 = $attributeCode . '_option_value_t1'; + $optionTable2 = $attributeCode . '_option_value_t2'; + + $collection->getSelect() + ->joinLeft( + array($optionTable1 => $this->getTable('eav/attribute_option_value')), + "`{$optionTable1}`.`option_id`={$valueExpr}" + . " AND `{$optionTable1}`.`store_id`='0'", + array()) + ->joinLeft( + array($optionTable2 => $this->getTable('eav/attribute_option_value')), + "`{$optionTable2}`.`option_id`={$valueExpr}" + . " AND `{$optionTable1}`.`store_id`='{$collection->getStoreId()}'", + array($attributeCode => "IFNULL(`{$optionTable2}`.`value`, `{$optionTable1}`.`value`)") + ); + + return $this; + } + + /** + * Retrieve Select for update Flat data + * + * @param Mage_Eav_Model_Entity_Attribute_Abstract $attribute + * @param int $store + * @param bool $hasValueField flag which require option value + * @return Varien_Db_Select + */ + public function getFlatUpdateSelect(Mage_Eav_Model_Entity_Attribute_Abstract $attribute, $store, $hasValueField=true) + { + $attributeTable = $attribute->getBackend()->getTable(); + $attributeCode = $attribute->getAttributeCode(); + + $valueExpr = new Zend_Db_Expr("IFNULL(t2.value, t1.value)"); + $select = $this->_getReadAdapter()->select() + ->joinLeft( + array('t1' => $attributeTable), + "`e`.`entity_id`=`t1`.`entity_id` AND `e`.`child_id`=`t1`.`entity_id`", + array() + ) + ->joinLeft( + array('t2' => $attributeTable), + "`t2`.`entity_id`=`t1`.`entity_id`" + . " AND `t1`.`entity_type_id`=`t2`.`entity_type_id`" + . " AND `t1`.`attribute_id`=`t2`.`attribute_id`" + . " AND `t2`.`store_id`={$store}", + array($attributeCode => $valueExpr)); + if (($attribute->getFrontend()->getInputType() != 'multiselect') && $hasValueField) { + $select->joinLeft( + array('to1' => $this->getTable('eav/attribute_option_value')), + "`to1`.`option_id`={$valueExpr}" + . " AND `to1`.`store_id`='0'", + array()) + ->joinLeft( + array('to2' => $this->getTable('eav/attribute_option_value')), + "`to2`.`option_id`={$valueExpr}" + . " AND `to2`.`store_id`='{$store}'", + array($attributeCode . '_value' => "IFNULL(`to2`.`value`, `to1`.`value`)") + ); + } + $select + ->where('t1.entity_type_id=?', $attribute->getEntityTypeId()) + ->where('t1.attribute_id=?', $attribute->getId()) + ->where('t1.store_id=?', 0); + + return $select; + } } diff --git a/app/code/core/Mage/Eav/sql/eav_setup/mysql4-install-0.7.0.php b/app/code/core/Mage/Eav/sql/eav_setup/mysql4-install-0.7.0.php index 61876ab64c..5f8c615669 100644 --- a/app/code/core/Mage/Eav/sql/eav_setup/mysql4-install-0.7.0.php +++ b/app/code/core/Mage/Eav/sql/eav_setup/mysql4-install-0.7.0.php @@ -42,6 +42,7 @@ `backend_table` varchar(255) default NULL, `frontend_model` varchar(255) default NULL, `frontend_input` varchar(50) default NULL, + `frontend_input_renderer` varchar(255) default NULL, `frontend_label` varchar(255) default NULL, `frontend_class` varchar(255) default NULL, `source_model` varchar(255) default NULL, @@ -56,9 +57,15 @@ `is_visible_on_front` tinyint(1) unsigned NOT NULL default '0', `is_unique` tinyint(1) unsigned NOT NULL default '0', `apply_to` tinyint(3) unsigned NOT NULL default '0', + `is_used_for_price_rules` tinyint(1) unsigned NOT NULL default '0', + `is_filterable_in_search` tinyint(1) unsigned NOT NULL default '0', `use_in_super_product` tinyint(1) unsigned NOT NULL default '1', + `used_in_product_listing` tinyint(1) unsigned NOT NULL default '0', + `used_for_sort_by` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`attribute_id`), UNIQUE KEY `entity_type_id` (`entity_type_id`,`attribute_code`), + KEY `IDX_USED_FOR_SORT_BY` (`entity_type_id`,`used_for_sort_by`), + KEY `IDX_USED_IN_PRODUCT_LISTING` (`entity_type_id`,`used_in_product_listing`), CONSTRAINT `FK_eav_attribute` FOREIGN KEY (`entity_type_id`) REFERENCES `{$this->getTable('eav_entity_type')}` (`entity_type_id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/app/code/core/Mage/GiftMessage/Model/Entity/Attribute/Source/Boolean/Config.php b/app/code/core/Mage/GiftMessage/Model/Entity/Attribute/Source/Boolean/Config.php index f131f3f361..cfaef7b3cc 100644 --- a/app/code/core/Mage/GiftMessage/Model/Entity/Attribute/Source/Boolean/Config.php +++ b/app/code/core/Mage/GiftMessage/Model/Entity/Attribute/Source/Boolean/Config.php @@ -18,17 +18,25 @@ * 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_Giftmessage - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GiftMessage + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +/** + * Gift Message attribute source model + * + * @category Mage + * @package Mage_GiftMessage + * @author Magento Core Team + */ class Mage_GiftMessage_Model_Entity_Attribute_Source_Boolean_Config extends Mage_Eav_Model_Entity_Attribute_Source_Boolean { + /** - * Retrive all attribute options + * Retrieve all attribute options * * @return array */ @@ -52,4 +60,5 @@ public function getAllOptions() } return $this->_options; } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/GiftRegistry/Model/Gift.php b/app/code/core/Mage/GiftRegistry/Model/Gift.php index f90fa6ff89..ae46016bc0 100644 --- a/app/code/core/Mage/GiftRegistry/Model/Gift.php +++ b/app/code/core/Mage/GiftRegistry/Model/Gift.php @@ -18,17 +18,18 @@ * 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_GiftRegstry - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GiftRegistry + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Giftregistry gift model * - * @category Mage - * @package Mage_GiftRegstry + * @category Mage + * @package Mage_GiftRegistry * @author Magento Core Team */ class Mage_GiftRegistry_Model_Gift extends Mage_Core_Model_Abstract diff --git a/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift.php b/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift.php index 87b116f106..4e0f5993e6 100644 --- a/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift.php +++ b/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift.php @@ -18,17 +18,18 @@ * 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_GiftRegstry - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GiftRegistry + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Giftregistry gift resource model * - * @category Mage - * @package Mage_GiftRegstry + * @category Mage + * @package Mage_GiftRegistry * @author Magento Core Team */ class Mage_GiftRegistry_Model_Mysql4_Gift extends Mage_Core_Model_Mysql4_Abstract diff --git a/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift/Collection.php b/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift/Collection.php index 19d8645882..21031e988a 100644 --- a/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift/Collection.php +++ b/app/code/core/Mage/GiftRegistry/Model/Mysql4/Gift/Collection.php @@ -18,17 +18,18 @@ * 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_GiftRegstry - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GiftRegistry + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Giftregistry gift collection resource model * - * @category Mage - * @package Mage_GiftRegstry + * @category Mage + * @package Mage_GiftRegistry * @author Magento Core Team */ class Mage_GiftRegistry_Model_Mysql4_Gift_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract diff --git a/app/code/core/Mage/GoogleBase/Model/Observer.php b/app/code/core/Mage/GoogleBase/Model/Observer.php index f69866b416..056c6a5a5c 100644 --- a/app/code/core/Mage/GoogleBase/Model/Observer.php +++ b/app/code/core/Mage/GoogleBase/Model/Observer.php @@ -41,16 +41,26 @@ class Mage_GoogleBase_Model_Observer */ public function saveProductItem($observer) { - $product = $observer->getEvent()->getProduct(); - if (Mage::getStoreConfigFlag('google/googlebase/observed', $product->getStoreId())) { - $collection = Mage::getResourceModel('googlebase/item_collection') - ->addProductFilterId($product->getId()) - ->load(); - foreach ($collection as $item) { - $product = Mage::getSingleton('catalog/product') - ->setStoreId($item->getStoreId()) - ->load($item->getProductId()); - Mage::getModel('googlebase/item')->setProduct($product)->updateItem(); + try { + $product = $observer->getEvent()->getProduct(); + if (Mage::getStoreConfigFlag('google/googlebase/observed', $product->getStoreId())) { + $collection = Mage::getResourceModel('googlebase/item_collection') + ->addProductFilterId($product->getId()) + ->load(); + foreach ($collection as $item) { + $product = Mage::getSingleton('catalog/product') + ->setStoreId($item->getStoreId()) + ->load($item->getProductId()); + Mage::getModel('googlebase/item')->setProduct($product)->updateItem(); + } + } + } catch (Exception $e) { + if (Mage::app()->getStore()->isAdmin()) { + Mage::getSingleton('adminhtml/session')->addNotice( + Mage::helper('googlebase')->__("Cannot update Google Base Item for Store '%s'", Mage::app()->getStore($item->getStoreId())->getName()) + ); + } else { + throw $e; } } return $this; @@ -64,13 +74,23 @@ public function saveProductItem($observer) */ public function deleteProductItem($observer) { - $product = $observer->getEvent()->getProduct(); - if (Mage::getStoreConfigFlag('google/googlebase/observed', $product->getStoreId())) { - $collection = Mage::getResourceModel('googlebase/item_collection') - ->addProductFilterId($product->getId()) - ->load(); - foreach ($collection as $item) { - $item->deleteItem()->delete(); + try { + $product = $observer->getEvent()->getProduct(); + if (Mage::getStoreConfigFlag('google/googlebase/observed', $product->getStoreId())) { + $collection = Mage::getResourceModel('googlebase/item_collection') + ->addProductFilterId($product->getId()) + ->load(); + foreach ($collection as $item) { + $item->deleteItem()->delete(); + } + } + } catch (Exception $e) { + if (Mage::app()->getStore()->isAdmin()) { + Mage::getSingleton('adminhtml/session')->addNotice( + Mage::helper('googlebase')->__("Cannot update Google Base Item for Store '%s'", Mage::app()->getStore($item->getStoreId())->getName()) + ); + } else { + throw $e; } } return $this; diff --git a/app/code/core/Mage/GoogleBase/Model/Service/Item.php b/app/code/core/Mage/GoogleBase/Model/Service/Item.php index ea4decefa6..10a4ba6263 100644 --- a/app/code/core/Mage/GoogleBase/Model/Service/Item.php +++ b/app/code/core/Mage/GoogleBase/Model/Service/Item.php @@ -245,6 +245,8 @@ protected function _setUniversalData() $object = $this->getObject(); $entry = $this->getEntry(); + $this->_setAttribute('id', $object->getId() . '_' . $this->getStoreId(), 'text'); + if ($object->getName()) { $title = $service->newTitle()->setText( $object->getName() ); $entry->setTitle($title); diff --git a/app/code/core/Mage/GoogleBase/controllers/ItemsController.php b/app/code/core/Mage/GoogleBase/controllers/ItemsController.php index 00f46cb46b..7b72f3bb73 100644 --- a/app/code/core/Mage/GoogleBase/controllers/ItemsController.php +++ b/app/code/core/Mage/GoogleBase/controllers/ItemsController.php @@ -117,6 +117,8 @@ public function massAddAction() $this->_getSession()->addError($e->getMessage()); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } @@ -151,6 +153,8 @@ public function massDeleteAction() $this->_getSession()->addError($e->getMessage()); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } @@ -184,6 +188,8 @@ public function massPublishAction() $this->_getSession()->addError($e->getMessage()); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } @@ -217,6 +223,8 @@ public function massHideAction() $this->_getSession()->addError($e->getMessage()); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } @@ -276,6 +284,8 @@ public function refreshAction() $this->_getSession()->addError($e->getMessage()); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } @@ -298,6 +308,8 @@ public function confirmCaptchaAction() $this->_getSession()->addError($this->__('Captcha confirmation error: %s', $e->getMessage())); $this->_redirectToCaptcha($e); return; + } catch (Zend_Gdata_App_Exception $e) { + $this->_getSession()->addError( $this->_parseGdataExceptionMessage($e->getMessage()) ); } catch (Exception $e) { $this->_getSession()->addError($this->__('Captcha confirmation error: %s', $e->getMessage())); } @@ -338,4 +350,29 @@ protected function _isAllowed() { return Mage::getSingleton('admin/session')->isAllowed('catalog/googlebase/items'); } + + /** + * Parse Exception Response Body + * + * @param string $message Exception message to parse + * @return string + */ + protected function _parseGdataExceptionMessage($message) + { + $result = array(); + foreach (explode("\n", $message) as $row) { + if (strip_tags($row) == $row) { + $result[] = $row; + continue; + } + try { + $xml = new Varien_Simplexml_Element($row); + $error = $xml->getAttribute('reason'); + $result[] = $error; + } catch (Exception $e) { + continue; + } + } + return implode(" ", $result); + } } diff --git a/app/code/core/Mage/GoogleCheckout/Block/Redirect.php b/app/code/core/Mage/GoogleCheckout/Block/Redirect.php index 62ae0fe931..fa1ab30aa5 100644 --- a/app/code/core/Mage/GoogleCheckout/Block/Redirect.php +++ b/app/code/core/Mage/GoogleCheckout/Block/Redirect.php @@ -29,7 +29,6 @@ * * @category Mage * @package Mage_GoogleCheckout - * @name Mage_GoogleCheckout_Block_Redirect * @author Magento Core Team */ class Mage_GoogleCheckout_Block_Redirect extends Mage_Page_Block_Redirect @@ -37,8 +36,7 @@ class Mage_GoogleCheckout_Block_Redirect extends Mage_Page_Block_Redirect /** * Description goes here... * - * @param none - * @return void + * @return string */ public function getTargetURL () { diff --git a/app/code/core/Mage/GoogleCheckout/Model/Observer.php b/app/code/core/Mage/GoogleCheckout/Model/Observer.php index a62e96e77d..a63b3506e8 100644 --- a/app/code/core/Mage/GoogleCheckout/Model/Observer.php +++ b/app/code/core/Mage/GoogleCheckout/Model/Observer.php @@ -62,6 +62,9 @@ public function salesOrderShipmentSaveAfter(Varien_Event_Observer $observer) $items = array(); foreach ($shipment->getAllItems() as $item) { + if ($item->getOrderItem()->getParentItemId()) { + continue; + } $items[] = $item->getSku(); } diff --git a/app/code/core/Mage/GoogleCheckout/controllers/RedirectController.php b/app/code/core/Mage/GoogleCheckout/controllers/RedirectController.php index ac84d62da1..2bef1fdc70 100644 --- a/app/code/core/Mage/GoogleCheckout/controllers/RedirectController.php +++ b/app/code/core/Mage/GoogleCheckout/controllers/RedirectController.php @@ -18,18 +18,23 @@ * 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_GoogleCheckout - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GoogleCheckout + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +/** + * @category Mage + * @package Mage_GoogleCheckout + * @author Magento Core Team + */ class Mage_GoogleCheckout_RedirectController extends Mage_Core_Controller_Front_Action { + /** * Send request to Google Checkout and return Responce Api * - * @param none * @return object Mage_GoogleCheckout_Model_Api_Xml_Checkout */ protected function _getApi () @@ -145,4 +150,5 @@ public function continueAction() $this->_redirect($url); } } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/GoogleCheckout/etc/system.xml b/app/code/core/Mage/GoogleCheckout/etc/system.xml index 65d8d3bc82..aafeb0a8cd 100644 --- a/app/code/core/Mage/GoogleCheckout/etc/system.xml +++ b/app/code/core/Mage/GoogleCheckout/etc/system.xml @@ -84,7 +84,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 20 1 @@ -93,7 +93,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 30 1 diff --git a/app/code/core/Mage/GoogleCheckout/etc/wsdl.xml b/app/code/core/Mage/GoogleCheckout/etc/wsdl.xml new file mode 100644 index 0000000000..9c0c0dcbc9 --- /dev/null +++ b/app/code/core/Mage/GoogleCheckout/etc/wsdl.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.0-0.7.1.php b/app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.0-0.7.1.php index 427254a71f..bd535c13ff 100644 --- a/app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.0-0.7.1.php +++ b/app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.0-0.7.1.php @@ -54,7 +54,11 @@ $attributeId = $installer->getAttributeId('catalog_product', 'disable_googlecheckout'); foreach ($installer->getAllAttributeSetIds('catalog_product') as $attributeSetId) { - $attributeGroupId = $installer->getAttributeGroupId('catalog_product', $attributeSetId, 'Prices'); + try { + $attributeGroupId = $installer->getAttributeGroupId('catalog_product', $attributeSetId, 'Prices'); + } catch (Exception $e) { + $attributeGroupId = $installer->getDefaultAttributeGroupId('catalog_product', $attributeSetId); + } $installer->addAttributeToSet('catalog_product', $attributeSetId, $attributeGroupId, $attributeId); } $installer->endSetup(); \ No newline at end of file diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Adminhtml/System/Config/Source/Googleoptimizer/Conversionpages.php b/app/code/core/Mage/GoogleOptimizer/Model/Adminhtml/System/Config/Source/Googleoptimizer/Conversionpages.php index 579309e9b3..39189087bf 100644 --- a/app/code/core/Mage/GoogleOptimizer/Model/Adminhtml/System/Config/Source/Googleoptimizer/Conversionpages.php +++ b/app/code/core/Mage/GoogleOptimizer/Model/Adminhtml/System/Config/Source/Googleoptimizer/Conversionpages.php @@ -18,33 +18,35 @@ * 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_GoogleOptimizer - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GoogleOptimizer + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ /** * Google Optimizer Source Model * - * @category Mage - * @package Mage_GoogleOptmizer - * @author Magento Core Team + * @category Mage + * @package Mage_GoogleOptimizer + * @author Magento Core Team */ class Mage_GoogleOptimizer_Model_Adminhtml_System_Config_Source_Googleoptimizer_Conversionpages { + public function toOptionArray() { return array( - array('value'=>'', 'label'=>Mage::helper('googleoptimizer')->__('-- Please Select --')), - array('value'=>'other', 'label'=>Mage::helper('googleoptimizer')->__('Other')), - array('value'=>'checkout_cart', 'label'=>Mage::helper('googleoptimizer')->__('Shopping Cart')), - array('value'=>'checkout_onepage', 'label'=>Mage::helper('googleoptimizer')->__('One Page Checkout')), - array('value'=>'checkout_multishipping', 'label'=>Mage::helper('googleoptimizer')->__('Multi Address Checkout')), - array('value'=>'checkout_onepage_success', 'label'=>Mage::helper('googleoptimizer')->__('Order Success (One Page Checkout)')), - array('value'=>'checkout_multishipping_success', 'label'=>Mage::helper('googleoptimizer')->__('Order Success (Multi Address Checkout)')), - array('value'=>'customer_account_create', 'label'=>Mage::helper('googleoptimizer')->__('Account Registration')), + array('value' => '', 'label' => Mage::helper('googleoptimizer')->__('-- Please Select --')), + array('value' => 'other', 'label' => Mage::helper('googleoptimizer')->__('Other')), + array('value' => 'checkout_cart', 'label' => Mage::helper('googleoptimizer')->__('Shopping Cart')), + array('value' => 'checkout_onepage', 'label' => Mage::helper('googleoptimizer')->__('One Page Checkout')), + array('value' => 'checkout_multishipping', 'label' => Mage::helper('googleoptimizer')->__('Multi Address Checkout')), + array('value' => 'checkout_onepage_success', 'label' => Mage::helper('googleoptimizer')->__('Order Success (One Page Checkout)')), + array('value' => 'checkout_multishipping_success', 'label' => Mage::helper('googleoptimizer')->__('Order Success (Multi Address Checkout)')), + array('value' => 'customer_account_create', 'label' => Mage::helper('googleoptimizer')->__('Account Registration')), ); } + } \ No newline at end of file diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Code.php b/app/code/core/Mage/GoogleOptimizer/Model/Code.php index 32ef2d151c..3cf1320389 100644 --- a/app/code/core/Mage/GoogleOptimizer/Model/Code.php +++ b/app/code/core/Mage/GoogleOptimizer/Model/Code.php @@ -169,7 +169,7 @@ public function saveScripts($storeId) /** * Removing scripts assigned to entity * - * @param Varien_Object $entity + * @param integer $storeId * @return Mage_Googleoptimizer_Model_Code */ public function deleteScripts($storeId) diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Code/Category.php b/app/code/core/Mage/GoogleOptimizer/Model/Code/Category.php index 899e5d3942..1347269bee 100644 --- a/app/code/core/Mage/GoogleOptimizer/Model/Code/Category.php +++ b/app/code/core/Mage/GoogleOptimizer/Model/Code/Category.php @@ -18,27 +18,29 @@ * 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_GoogleOptimizer - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_GoogleOptimizer + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Google Optimizer Category model * - * @category Mage - * @package Mage_Googleoptimizer_Model_Code_Category - * @author Magento Core Team + * @category Mage + * @package Mage_Googleoptimizer + * @author Magento Core Team */ class Mage_GoogleOptimizer_Model_Code_Category extends Mage_GoogleOptimizer_Model_Code { + protected $_entityType = 'category'; /** * Removing scripts assigned to entity * - * @param Varien_Object $entity + * @param integer $storeId * @return Mage_Googleoptimizer_Model_Code */ public function deleteScripts($storeId) @@ -58,4 +60,5 @@ public function deleteScripts($storeId) } return parent::deleteScripts($storeId); } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Observer.php b/app/code/core/Mage/GoogleOptimizer/Model/Observer.php index 926e29b68e..52a260a7e2 100644 --- a/app/code/core/Mage/GoogleOptimizer/Model/Observer.php +++ b/app/code/core/Mage/GoogleOptimizer/Model/Observer.php @@ -125,6 +125,13 @@ public function deleteProductGoogleOptimizerScripts($observer) */ public function appendToPageGoogleOptimizerScripts($observer) { + /** + * Check activity for frontend + */ + if (Mage::app()->getStore()->getId() && !Mage::helper('googleoptimizer')->isOptimizerActive()) { + return $this; + } + $cmsPage = $observer->getEvent()->getObject(); $googleOptimizerModel = Mage::getModel('googleoptimizer/code_page') ->setEntity($cmsPage) diff --git a/app/code/core/Mage/Install/controllers/WizardController.php b/app/code/core/Mage/Install/controllers/WizardController.php index 1d82ff61d2..1472dbc661 100644 --- a/app/code/core/Mage/Install/controllers/WizardController.php +++ b/app/code/core/Mage/Install/controllers/WizardController.php @@ -23,7 +23,7 @@ * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -@set_time_limit(120); + /** * Installation wizard controller */ diff --git a/app/code/core/Mage/Log/Model/Customer.php b/app/code/core/Mage/Log/Model/Customer.php index 27abcf1ad6..3a2a103bee 100644 --- a/app/code/core/Mage/Log/Model/Customer.php +++ b/app/code/core/Mage/Log/Model/Customer.php @@ -38,10 +38,18 @@ public function __construct() parent::__construct(); $this->_setResourceModel('log/customer'); } - + public function load($customerId, $field=null) { $this->_getResource()->load($this, $customerId); return $this; } + + public function getLoginAtTimestamp() + { + if ($date = $this->getLoginAt()) { + return strtotime($date); + } + return null; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Log/Model/Mysql4/Visitor.php b/app/code/core/Mage/Log/Model/Mysql4/Visitor.php index 1883664f66..e0a7185ffa 100644 --- a/app/code/core/Mage/Log/Model/Mysql4/Visitor.php +++ b/app/code/core/Mage/Log/Model/Mysql4/Visitor.php @@ -186,10 +186,17 @@ protected function _saveQuoteInfo($visitor) } if ($visitor->getDoQuoteDestroy()) { - $write->update($this->getTable('log/quote_table'), - array('deleted_at'=> now()), + /** + * We have delete quote from log because if original quote was + * deleted and Mysql restarted we will get key duplication error + */ + $write->delete($this->getTable('log/quote_table'), $write->quoteInto('quote_id=?', $visitor->getQuoteId()) ); +// $write->update($this->getTable('log/quote_table'), +// array('deleted_at'=> now()), +// $write->quoteInto('quote_id=?', $visitor->getQuoteId()) +// ); $visitor->setDoQuoteDestroy(false); $visitor->setQuoteId(null); } diff --git a/app/code/core/Mage/Page/Block/Html.php b/app/code/core/Mage/Page/Block/Html.php index 7bcb1e05aa..8ab4824431 100644 --- a/app/code/core/Mage/Page/Block/Html.php +++ b/app/code/core/Mage/Page/Block/Html.php @@ -71,8 +71,7 @@ public function getCurrentUrl() /** * Print Logo URL (Conf -> Sales -> Invoice and Packing Slip Design) * - * @param none - * @return void + * @return string */ public function getPrintLogoUrl () { diff --git a/app/code/core/Mage/Page/Block/Html/Pager.php b/app/code/core/Mage/Page/Block/Html/Pager.php index 197c13b403..4025fa0a75 100644 --- a/app/code/core/Mage/Page/Block/Html/Pager.php +++ b/app/code/core/Mage/Page/Block/Html/Pager.php @@ -82,7 +82,7 @@ public function setCollection($collection) } /** - * @return + * @return Mage_Core_Model_Mysql4_Collection_Abstract */ public function getCollection() { diff --git a/app/code/core/Mage/Page/Block/Redirect.php b/app/code/core/Mage/Page/Block/Redirect.php index daec4e41e2..a6cd026f0d 100644 --- a/app/code/core/Mage/Page/Block/Redirect.php +++ b/app/code/core/Mage/Page/Block/Redirect.php @@ -18,21 +18,23 @@ * 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_PackageName - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Page + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Customer Redirect Page * - * @name Mage_Page_Block_Redirect - * @author Magento Core Team + * @category Mage + * @package Mage_Page + * @author Magento Core Team */ - class Mage_Page_Block_Redirect extends Mage_Core_Block_Template { + /** * HTML form hidden fields */ @@ -41,7 +43,6 @@ class Mage_Page_Block_Redirect extends Mage_Core_Block_Template /** * URL for redirect location * - * @param none * @return string URL */ public function getTargetURL () @@ -52,7 +53,6 @@ public function getTargetURL () /** * Additional custom message * - * @param none * @return string Output message */ public function getMessage () @@ -63,7 +63,6 @@ public function getMessage () /** * Client-side redirect engine output * - * @param none * @return string */ public function getRedirectOutput () @@ -78,7 +77,6 @@ public function getRedirectOutput () /** * Redirect via JS location * - * @param none * @return string */ public function getJsRedirect () @@ -92,7 +90,6 @@ public function getJsRedirect () /** * Redirect via HTML form submission * - * @param none * @return string */ public function getHtmlFormRedirect () @@ -114,7 +111,6 @@ public function getHtmlFormRedirect () /** * HTML form or JS redirect * - * @param none * @return boolean */ public function isHtmlFormRedirect () @@ -125,7 +121,6 @@ public function isHtmlFormRedirect () /** * HTML form id/name attributes * - * @param none * @return string Id/name */ public function getFormId() @@ -136,7 +131,6 @@ public function getFormId() /** * HTML form method attribute * - * @param none * @return string Method */ public function getFormMethod () @@ -147,7 +141,6 @@ public function getFormMethod () /** * Array of hidden form fields (name => value) * - * @param none * @return array */ public function getFormFields() @@ -158,7 +151,6 @@ public function getFormFields() /** * Optimized getFormFields() method * - * @param none * @return array */ protected function _getFormFields() @@ -168,4 +160,5 @@ protected function _getFormFields() } return $this->_formFields; } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/Page/Block/Template/Links.php b/app/code/core/Mage/Page/Block/Template/Links.php index afb98bdc04..f2e55a4e2d 100644 --- a/app/code/core/Mage/Page/Block/Template/Links.php +++ b/app/code/core/Mage/Page/Block/Template/Links.php @@ -109,6 +109,23 @@ public function addLink($label, $url='', $title='', $prepare=false, $urlParams=a return $this; } + /** + * Removes link by url + * + * @param string $url + * @return Mage_Page_Block_Template_Links + */ + public function removeLinkByUrl($url) + { + foreach ($this->_links as $k => $v) { + if ($v->getUrl() == $url) { + unset($this->_links[$k]); + } + } + + return $this; + } + /** * Prepare tag attributes * diff --git a/app/code/core/Mage/Paygate/etc/system.xml b/app/code/core/Mage/Paygate/etc/system.xml index 7271591b55..0831914602 100644 --- a/app/code/core/Mage/Paygate/etc/system.xml +++ b/app/code/core/Mage/Paygate/etc/system.xml @@ -75,7 +75,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 2 1 @@ -135,7 +135,7 @@ - password + obscure adminhtml/system_config_backend_encrypted 3 1 @@ -260,7 +260,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 6 1 @@ -326,7 +326,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 5 1 diff --git a/app/code/core/Mage/Payment/Model/Config.php b/app/code/core/Mage/Payment/Model/Config.php index 731850af2e..d92eaa32a5 100644 --- a/app/code/core/Mage/Payment/Model/Config.php +++ b/app/code/core/Mage/Payment/Model/Config.php @@ -126,7 +126,7 @@ public function getYears() $years = array(); $first = date("Y"); - for ($index=0; $index<10; $index++) { + for ($index=0; $index <= 10; $index++) { $year = $first + $index; $years[$year] = $year; } diff --git a/app/code/core/Mage/Payment/Model/Method/Cc.php b/app/code/core/Mage/Payment/Model/Method/Cc.php index 129062ae16..a7b6c0f822 100644 --- a/app/code/core/Mage/Payment/Model/Method/Cc.php +++ b/app/code/core/Mage/Payment/Model/Method/Cc.php @@ -137,6 +137,15 @@ public function validate() $errorMsg = $this->_getHelper()->__('Credit card type is not allowed for this payment method'); } + //validate credit card verification number + if ($errorMsg === false && $this->hasVerification()) { + $verifcationRegEx = $this->getVerificationRegEx(); + $regExp = isset($verifcationRegEx[$info->getCcType()]) ? $verifcationRegEx[$info->getCcType()] : ''; + if (!$info->getCcCid() || !$regExp || !preg_match($regExp ,$info->getCcCid())){ + $errorMsg = $this->_getHelper()->__('Please enter a valid credit card verification number.'); + } + } + if($errorMsg){ Mage::throwException($errorMsg); //throw Mage::exception('Mage_Payment', $errorMsg, $errorCode); @@ -145,6 +154,28 @@ public function validate() return $this; } + public function hasVerification() + { + $configData = $this->getConfigData('useccv'); + if(is_null($configData)){ + return true; + } + return (bool) $configData; + } + + public function getVerificationRegEx() + { + $verificationExpList = array( + 'VI' => '/^[0-9]{3}$/', // Visa + 'MC' => '/^[0-9]{3}$/', // Master Card + 'AE' => '/^[0-9]{4}$/', // American Express + 'DI' => '/^[0-9]{3}$/', // Discovery + 'SS' => '/^[0-9]{4}$/', + 'OT' => '/^[0-9]{3,4}$/' + ); + return $verificationExpList; + } + protected function _validateExpDate($expYear, $expMonth) { $date = Mage::app()->getLocale()->date(); diff --git a/app/code/core/Mage/Payment/Model/Method/Free.php b/app/code/core/Mage/Payment/Model/Method/Free.php index d7add27d66..b521802584 100644 --- a/app/code/core/Mage/Payment/Model/Method/Free.php +++ b/app/code/core/Mage/Payment/Model/Method/Free.php @@ -42,18 +42,9 @@ public function isAvailable($quote=null) return false; } - /* @var $quote Mage_Sales_Model_Quote */ - $totals = $quote->getTotals(); - - if (!isset($totals['grand_total'])) { - return false; - } - $grandTotal = $totals['grand_total']; - - if (Mage::app()->getStore()->roundPrice($grandTotal->getValue()) == 0) { + if (Mage::app()->getStore()->roundPrice($quote->getGrandTotal()) == 0) { return true; } - return false; } } \ No newline at end of file diff --git a/app/code/core/Mage/Paypal/controllers/StandardController.php b/app/code/core/Mage/Paypal/controllers/StandardController.php index 53dbd323fd..c155e18b63 100644 --- a/app/code/core/Mage/Paypal/controllers/StandardController.php +++ b/app/code/core/Mage/Paypal/controllers/StandardController.php @@ -24,13 +24,17 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Paypal Standard Checkout Controller * + * @category Mage + * @package Mage_Paypal * @author Magento Core Team */ class Mage_Paypal_StandardController extends Mage_Core_Controller_Front_Action { + /** * Order instance */ @@ -39,7 +43,6 @@ class Mage_Paypal_StandardController extends Mage_Core_Controller_Front_Action /** * Get order * - * @param none * @return Mage_Sales_Model_Order */ public function getOrder() @@ -148,4 +151,5 @@ public function ipnAction() $this->getStandard()->setIpnFormData($this->getRequest()->getPost()); $this->getStandard()->ipnPostSubmit(); } + } diff --git a/app/code/core/Mage/Paypal/etc/system.xml b/app/code/core/Mage/Paypal/etc/system.xml index 66a6f1dac6..cecd8e5790 100644 --- a/app/code/core/Mage/Paypal/etc/system.xml +++ b/app/code/core/Mage/Paypal/etc/system.xml @@ -290,7 +290,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 2 1 @@ -300,7 +300,7 @@ adminhtml/system_config_backend_encrypted - text + obscure 3 1 1 @@ -308,7 +308,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 1 1 @@ -389,7 +389,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 2 1 diff --git a/app/code/core/Mage/PaypalUk/Model/Api/Result.php b/app/code/core/Mage/PaypalUk/Model/Api/Result.php index 1ea0fa7d2f..ba4dea9d05 100644 --- a/app/code/core/Mage/PaypalUk/Model/Api/Result.php +++ b/app/code/core/Mage/PaypalUk/Model/Api/Result.php @@ -18,20 +18,21 @@ * 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_Paypaluk - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_PaypalUk + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * PayflowUk Pro Result Model * - * @category Mage - * @package Mage_Paypaluk + * @category Mage + * @package Mage_PaypalUk + * @author Magento Core Team */ - class Mage_PaypalUk_Model_Api_Result extends Varien_Object { -} \ No newline at end of file +} diff --git a/app/code/core/Mage/PaypalUk/etc/system.xml b/app/code/core/Mage/PaypalUk/etc/system.xml index 568df94f51..839ee7bda4 100644 --- a/app/code/core/Mage/PaypalUk/etc/system.xml +++ b/app/code/core/Mage/PaypalUk/etc/system.xml @@ -202,7 +202,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 2 1 @@ -219,7 +219,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 4 1 diff --git a/app/code/core/Mage/Poll/Model/Mysql4/Poll/Collection.php b/app/code/core/Mage/Poll/Model/Mysql4/Poll/Collection.php index f62f46e640..514cf08c87 100644 --- a/app/code/core/Mage/Poll/Model/Mysql4/Poll/Collection.php +++ b/app/code/core/Mage/Poll/Model/Mysql4/Poll/Collection.php @@ -61,13 +61,17 @@ public function addFieldToFilter($field, $condition=null) * @param int $storeId * @return Mage_Poll_Model_Mysql4_Poll_Collection */ - public function addStoresFilter($storeId) + public function addStoresFilter($store) { - $this->_select->join( - array('store' => $this->getTable('poll/poll_store')), - 'main_table.poll_id=store.poll_id AND store.store_id=' . (int)$storeId, + + $this->getSelect()->join( + array('store_table' => $this->getTable('poll/poll_store')), + 'main_table.poll_id = store_table.poll_id', array() - ); + ) + ->where('store_table.store_id in (?)', array(0, $store)) + ->group('main_table.poll_id'); + return $this; } diff --git a/app/code/core/Mage/ProductAlert/Model/Observer.php b/app/code/core/Mage/ProductAlert/Model/Observer.php index a9cfd08a26..65bfbc5ad5 100644 --- a/app/code/core/Mage/ProductAlert/Model/Observer.php +++ b/app/code/core/Mage/ProductAlert/Model/Observer.php @@ -30,9 +30,9 @@ * * @category Mage * @package Mage_ProductAlert - * @author Magento Core Team + * @author Magento Core Team */ -class Mage_productAlert_Model_Observer +class Mage_ProductAlert_Model_Observer { /** * Error email template configuration @@ -103,6 +103,8 @@ protected function _processPrice(Mage_ProductAlert_Model_Email $email) { $email->setType('price'); foreach ($this->_getWebsites() as $website) { + /* @var $website Mage_Core_Model_Website */ + if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) { continue; } @@ -140,7 +142,9 @@ protected function _processPrice(Mage_ProductAlert_Model_Email $email) $customer = $previousCustomer; } - $product = Mage::getModel('catalog/product')->load($alert->getProductId()); + $product = Mage::getModel('catalog/product') + ->setStoreId($website->getDefaultStore()->getId()) + ->load($alert->getProductId()); if (!$product) { continue; } @@ -151,6 +155,7 @@ protected function _processPrice(Mage_ProductAlert_Model_Email $email) $alert->setPrice($product->getFinalPrice()); $alert->setLastSendDate(Mage::getModel('core/date')->gmtDate()); $alert->setSendCount($alert->getSendCount() + 1); + $alert->setStatus(1); $alert->save(); } } @@ -181,6 +186,8 @@ protected function _processStock(Mage_ProductAlert_Model_Email $email) $email->setType('stock'); foreach ($this->_getWebsites() as $website) { + /* @var $website Mage_Core_Model_Website */ + if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) { continue; } @@ -191,6 +198,7 @@ protected function _processStock(Mage_ProductAlert_Model_Email $email) $collection = Mage::getModel('productalert/stock') ->getCollection() ->addWebsiteFilter($website->getId()) + ->addStatusFilter(0) ->setCustomerOrder(); } catch (Exception $e) { @@ -218,12 +226,17 @@ protected function _processStock(Mage_ProductAlert_Model_Email $email) $customer = $previousCustomer; } - $product = Mage::getModel('catalog/product')->load($alert->getProductId()); + $product = Mage::getModel('catalog/product') + ->setStoreId($website->getDefaultStore()->getId()) + ->load($alert->getProductId()); + /* @var $product Mage_catalog_Model_Product */ if (!$product) { continue; } + $product->setCustomerGroupId($customer->getGroupId()); - if ($product->isSaleable()) { + + if ($product->isSalable()) { $email->addStockProduct($product); $alert->setSendDate(Mage::getModel('core/date')->gmtDate()); @@ -283,12 +296,19 @@ protected function _sendErrorEmail() return $this; } - public function process($observer) + /** + * Run process send product alerts + * + * @return Mage_productAlert_Model_Observer + */ + public function process() { $email = Mage::getModel('productalert/email'); /* @var $email Mage_ProductAlert_Model_Email */ $this->_processPrice($email); $this->_processStock($email); $this->_sendErrorEmail(); + + return $this; } } \ No newline at end of file diff --git a/app/code/core/Mage/Reports/Block/Product/Compared.php b/app/code/core/Mage/Reports/Block/Product/Compared.php index cc75476b6c..0f9f0458c2 100644 --- a/app/code/core/Mage/Reports/Block/Product/Compared.php +++ b/app/code/core/Mage/Reports/Block/Product/Compared.php @@ -51,26 +51,44 @@ protected function getPageSize() return Mage::getStoreConfig(self::XML_PATH_RECENTLY_COMPARED_COUNT); } + /** + * Retrieve Product Ids to skip + * + * @return array + */ protected function _getProductsToSkip() { $ids = array(); - foreach (Mage::helper('catalog/product_compare')->getItemCollection() as $_item) { - $ids[] = $_item->getId(); - } - if (($product = Mage::registry('product')) && $product->getId()) { - $ids[] = $product->getId(); + if (Mage::helper('catalog/product_compare')->getItemCount()) { + foreach (Mage::helper('catalog/product_compare')->getItemCollection() as $_item) { + $ids[] = $_item->getId(); + } + if (($product = Mage::registry('product')) && $product->getId()) { + $ids[] = $product->getId(); + } } return $ids; } + /** + * Check session has compared products + * + * @return bool + */ protected function _hasComparedProductsBefore() { return Mage::getSingleton('reports/session')->getData('compared_products'); } + /** + * Prepare to html + * check has compared products + * + * @return string + */ protected function _toHtml() { - if ($this->_hasComparedProductsBefore() === false) { + if (!$this->_hasComparedProductsBefore()) { return ''; } diff --git a/app/code/core/Mage/Reports/Block/Product/Viewed.php b/app/code/core/Mage/Reports/Block/Product/Viewed.php index 7ec81fb8c1..e66a09a748 100644 --- a/app/code/core/Mage/Reports/Block/Product/Viewed.php +++ b/app/code/core/Mage/Reports/Block/Product/Viewed.php @@ -51,6 +51,11 @@ protected function getPageSize() return Mage::getStoreConfig(self::XML_PATH_RECENTLY_VIEWED_COUNT); } + /** + * Retrieve Product Ids to skip + * + * @return array + */ protected function _getProductsToSkip() { $ids = array(); @@ -60,14 +65,25 @@ protected function _getProductsToSkip() return $ids; } + /** + * Check session has viewed products + * + * @return bool + */ protected function _hasViewedProductsBefore() { return Mage::getSingleton('reports/session')->getData('viewed_products'); } + /** + * Prepare to html + * check has viewed products + * + * @return string + */ protected function _toHtml() { - if ($this->_hasViewedProductsBefore() === false) { + if (!$this->_hasViewedProductsBefore()) { return ''; } diff --git a/app/code/core/Mage/Reports/Model/Event.php b/app/code/core/Mage/Reports/Model/Event.php index 83a1e21e07..0208fcafce 100644 --- a/app/code/core/Mage/Reports/Model/Event.php +++ b/app/code/core/Mage/Reports/Model/Event.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Reports - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,9 +29,8 @@ * * @category Mage * @package Mage_Reports - * @author Magento Core Team + * @author Magento Core Team */ - class Mage_Reports_Model_Event extends Mage_Core_Model_Abstract { const EVENT_PRODUCT_VIEW = 1; @@ -41,17 +40,34 @@ class Mage_Reports_Model_Event extends Mage_Core_Model_Abstract const EVENT_PRODUCT_TO_WISHLIST = 5; const EVENT_WISHLIST_SHARE = 6; + /** + * Initialize resource + * + */ protected function _construct() { $this->_init('reports/event'); } + /** + * Before Event save process + * + * @return Mage_Reports_Model_Event + */ protected function _beforeSave() { $this->setLoggedAt(Mage::getModel('core/date')->gmtDate()); return parent::_beforeSave(); } + /** + * Update customer type after customer login + * + * @param int $visitorId + * @param int $customerId + * @param array $types + * @return Mage_Reports_Model_Event + */ public function updateCustomerType($visitorId, $customerId, $types = null) { if (is_null($types)) { @@ -76,4 +92,4 @@ public function clean() $this->getResource()->clean($this); return $this; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Collection.php index 4fee8791cd..4b53d79d19 100644 --- a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Collection.php +++ b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Collection.php @@ -96,8 +96,19 @@ public function joinOrders($from = '', $to = '') public function addOrdersCount() { + $order = Mage::getResourceSingleton('sales/order'); + /* @var $order Mage_Sales_Model_Entity_Order */ + $stateAttr = $order->getAttribute('state'); + $_joinCondition = "{$this->_customerIdTableName}.entity_id=order_state.entity_id"; + $_joinCondition .= $this->getConnection()->quoteInto(' AND order_state.attribute_id=? ', $stateAttr->getId()); + $_joinCondition .= $this->getConnection()->quoteInto(' AND order_state.value<>? ', Mage_Sales_Model_Order::STATE_CANCELED); + $this->getSelect() - ->from('', array("orders_count" => "COUNT({$this->_customerIdTableName}.entity_id)")) + ->from('', array("orders_count" => "COUNT(order_state.entity_id)")) + ->joinLeft( + array('order_state' => $stateAttr->getBackend()->getTable()), + $_joinCondition, + array()) ->group("e.entity_id"); return $this; diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Event.php b/app/code/core/Mage/Reports/Model/Mysql4/Event.php index 03135b71f3..59fc0590d3 100644 --- a/app/code/core/Mage/Reports/Model/Mysql4/Event.php +++ b/app/code/core/Mage/Reports/Model/Mysql4/Event.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Reports - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -29,21 +29,33 @@ * * @category Mage * @package Mage_Reports - * @author Magento Core Team + * @author Magento Core Team */ - class Mage_Reports_Model_Mysql4_Event extends Mage_Core_Model_Mysql4_Abstract { + /** + * Initialize connection + * + */ protected function _construct() { $this->_init('reports/event', 'event_id'); } + /** + * Update customer type after customer login + * + * @param Mage_Reports_Model_Event $model + * @param int $visitorId + * @param int $customerId + * @param array $types + * @return Mage_Reports_Model_Mysql4_Event + */ public function updateCustomerType(Mage_Reports_Model_Event $model, $visitorId, $customerId, $types = array()) { if ($types) { $this->_getWriteAdapter()->update($this->getMainTable(), - array('subject_id'=>$customerId, 'subtype'=>0), + array('subject_id' => $customerId, 'subtype' => 0), array( $this->_getWriteAdapter()->quoteInto('subject_id=?', $visitorId), $this->_getWriteAdapter()->quoteInto('subtype=?', 1), @@ -135,6 +147,9 @@ public function getCurrentStoreIds(array $predefinedStoreIds = null) /** * Clean report event table + * + * @param Mage_Reports_Model_Event $object + * @return Mage_Reports_Model_Mysql4_Event */ public function clean(Mage_Reports_Model_Event $object) { diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php index 7ad9905b1a..b5e1918789 100644 --- a/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php +++ b/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php @@ -46,6 +46,7 @@ public function setDateRange($from, $to) ->addExpressionAttributeToSelect('orders_invoiced', 'SUM(IF({{base_total_invoiced}} > 0, 1, 0))', array('base_total_invoiced')) + ->addAttributeToFilter('state', array('neq' => Mage_Sales_Model_Order::STATE_CANCELED)) ->getSelect()->group('("*")')->having('orders > 0'); return $this; diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php index 43b07564c3..2114fa4824 100644 --- a/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php +++ b/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php @@ -221,6 +221,7 @@ public function setDateRange($from, $to) ->addAttributeToSelect('*') ->addAttributeToFilter('created_at', array('from' => $from, 'to' => $to)) ->addExpressionAttributeToSelect('orders', 'COUNT(DISTINCT({{entity_id}}))', array('entity_id')) + ->addAttributeToFilter('state', array('neq' => Mage_Sales_Model_Order::STATE_CANCELED)) ->getSelect()->group('("*")'); /** @@ -363,6 +364,7 @@ public function joinCustomerName() */ public function addOrdersCount() { + $this->addAttributeToFilter('state', array('neq' => Mage_Sales_Model_Order::STATE_CANCELED)); $this->getSelect() ->from('', array("orders_count" => "COUNT(e.entity_id)")); @@ -398,7 +400,7 @@ public function addSumAvgTotals($storeId = 0) /** * calculate average and total amount */ - $expr = "(e.base_subtotal-IFNULL(e.base_subtotal_refunded,0)-IFNULL(e.base_subtotal_canceled,0))/_b2gr_{$baseToGlobalRateTableName}.{$baseToGlobalRateTableName}"; + $expr = "(e.base_subtotal-IFNULL(e.base_subtotal_refunded,0)-IFNULL(e.base_subtotal_canceled,0))*_b2gr_{$baseToGlobalRateTableName}.{$baseToGlobalRateTableName}"; } else { diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Product/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Product/Collection.php index bc79a41c6d..f1dee9fa69 100644 --- a/app/code/core/Mage/Reports/Model/Mysql4/Product/Collection.php +++ b/app/code/core/Mage/Reports/Model/Mysql4/Product/Collection.php @@ -196,14 +196,44 @@ public function addOrderedQty($from = '', $to = '') $dateFilter = ""; } - $this->getSelect()->reset() - ->from( - array('order_items' => $qtyOrderedTableName), - array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")) - ->joinInner( + $this->getSelect()->reset()->from( + array('order_items' => $qtyOrderedTableName), + array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})") + ); + + $order = Mage::getResourceSingleton('sales/order'); + /* @var $order Mage_Sales_Model_Entity_Order */ + $stateAttr = $order->getAttribute('state'); + if ($stateAttr->getBackend()->isStatic()) { + + $_joinCondition = $this->getConnection()->quoteInto( + 'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED + ); + $_joinCondition .= $dateFilter; + + $this->getSelect()->joinInner( array('order' => $this->getTable('sales/order')), - 'order.entity_id = order_items.order_id'.$dateFilter, - array()) + $_joinCondition, + array() + ); + } else { + + $_joinCondition = 'order.entity_id = order_state.entity_id'; + $_joinCondition .= $this->getConnection()->quoteInto(' AND order_state.attribute_id=? ', $stateAttr->getId()); + $_joinCondition .= $this->getConnection()->quoteInto(' AND order_state.value<>? ', Mage_Sales_Model_Order::STATE_CANCELED); + + $this->getSelect() + ->joinInner( + array('order' => $this->getTable('sales/order')), + 'order.entity_id = order_items.order_id' . $dateFilter, + array()) + ->joinInner( + array('order_state' => $stateAttr->getBackend()->getTable()), + $_joinCondition, + array()); + } + + $this->getSelect() ->joinInner(array('e' => $this->getProductEntityTableName()), "e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}") ->group('e.entity_id') diff --git a/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php b/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php index c0ee0d26c2..f4a8ed6126 100644 --- a/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php +++ b/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php @@ -58,15 +58,27 @@ public function addStoreFilter($storeId=null) $this->getSelect() ->join(array('store'=>$this->_reviewStoreTable), 'rt.review_id=store.review_id AND store.store_id=' . (int)$storeId, array()); - return $this; } public function setStoreFilter($storeId) { - $this->getSelect() - ->join(array('store'=>$this->_reviewStoreTable), - 'rt.review_id=store.review_id AND store.store_id=' . (int)$storeId, array()); + if( is_array($storeId) && isset($storeId['eq']) ) { + $storeId = array_shift($storeId); + } + + if( is_array($storeId) ) { + $this->getSelect() + ->join(array('store'=>$this->_reviewStoreTable), + $this->getConnection()->quoteInto('rt.review_id=store.review_id AND store.store_id IN(?)', $storeId), array()) + ->distinct(true) + ; + } else { + $this->getSelect() + ->join(array('store'=>$this->_reviewStoreTable), + 'rt.review_id=store.review_id AND store.store_id=' . (int)$storeId, array()); + } + return $this; } diff --git a/app/code/core/Mage/Review/controllers/ProductController.php b/app/code/core/Mage/Review/controllers/ProductController.php index e227e3e689..21db420aad 100644 --- a/app/code/core/Mage/Review/controllers/ProductController.php +++ b/app/code/core/Mage/Review/controllers/ProductController.php @@ -63,6 +63,7 @@ public function preDispatch() */ protected function _initProduct() { + Mage::dispatchEvent('review_controller_product_init_before', array('controller_action'=>$this)); $categoryId = (int) $this->getRequest()->getParam('category', false); $productId = (int) $this->getRequest()->getParam('id'); @@ -83,6 +84,15 @@ protected function _initProduct() } Mage::register('current_product', $product); Mage::register('product', $product); + + try { + Mage::dispatchEvent('review_controller_product_init', array('product'=>$product)); + Mage::dispatchEvent('review_controller_product_init_after', array('product'=>$product, 'controller_action' => $this)); + } catch (Mage_Core_Exception $e) { + Mage::logException($e); + return false; + } + return $product; } @@ -169,7 +179,7 @@ public function listAction() } $this->renderLayout(); - } else { + } elseif ($this->getRequest()->isDispatched()) { $this->_forward('noRoute'); } } diff --git a/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php b/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php index 290fcffff4..04f77bbeb3 100644 --- a/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php +++ b/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php @@ -83,7 +83,7 @@ public function addNotifyItemXmlCallback($args) { $product = $args['product']; $product->setData($args['row']); - $url = Mage::helper('adminhtml')->getUrl('adminhtml/catalog_product/edit/', array('id'=>$product->getId(),'_secure' => true)); + $url = Mage::helper('adminhtml')->getUrl('adminhtml/catalog_product/edit/', array('id'=>$product->getId(),'_secure' => true,'_nosecret' => true)); $description = Mage::helper('rss')->__('%s has reached a quantity of %s.', $product->getName(),(1*$product->getQty())); $rssObj = $args['rssObj']; $data = array( diff --git a/app/code/core/Mage/Rss/Block/Catalog/Review.php b/app/code/core/Mage/Rss/Block/Catalog/Review.php index e9e2df9cf9..bae3cba6f5 100644 --- a/app/code/core/Mage/Rss/Block/Catalog/Review.php +++ b/app/code/core/Mage/Rss/Block/Catalog/Review.php @@ -74,7 +74,7 @@ public function addReviewItemXmlCallback($args) $row = $args['row']; $productUrl = Mage::getUrl('catalog/product/view',array('id'=>$row['entity_id'])); - $reviewUrl = Mage::helper('adminhtml')->getUrl('adminhtml/catalog_product_review/edit/', array('id'=>$row['review_id'],'_secure' => true)); + $reviewUrl = Mage::helper('adminhtml')->getUrl('adminhtml/catalog_product_review/edit/', array('id'=>$row['review_id'],'_secure' => true,'_nosecret' => true)); $storeName = Mage::app()->getStore($row['store_id'])->getName(); $description = '

'. diff --git a/app/code/core/Mage/Rss/Block/Order/New.php b/app/code/core/Mage/Rss/Block/Order/New.php index ac23ceca0c..310ed82b71 100644 --- a/app/code/core/Mage/Rss/Block/Order/New.php +++ b/app/code/core/Mage/Rss/Block/Order/New.php @@ -47,7 +47,7 @@ protected function _toHtml() $order = Mage::getModel('sales/order'); $passDate = $order->getResource()->formatDate(mktime(0,0,0,date('m'),date('d')-7)); - $newurl = Mage::helper('adminhtml')->getUrl('adminhtml/sales_order', array('_secure' => true)); + $newurl = Mage::helper('adminhtml')->getUrl('adminhtml/sales_order', array('_secure' => true, '_nosecret' => true)); $title = Mage::helper('rss')->__('New Orders'); $rssObj = Mage::getModel('rss/rss'); @@ -78,7 +78,7 @@ public function addNewOrderXmlCallback($args) $order->unsetData()->load($args['row']['entity_id']); if ($order && $order->getId()) { $title = Mage::helper('rss')->__('Order #%s created at %s', $order->getIncrementId(), $this->formatDate($order->getCreatedAt())); - $url = Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('_secure' => true, 'order_id' => $order->getId())); + $url = Mage::helper('adminhtml')->getUrl('adminhtml/sales_order/view', array('_secure' => true, 'order_id' => $order->getId(), '_nosecret' => true)); $detailBlock->setOrder($order); $data = array( 'title' => $title, diff --git a/app/code/core/Mage/Rule/Model/Rule.php b/app/code/core/Mage/Rule/Model/Rule.php index c2eeed8447..7a5129d5b3 100644 --- a/app/code/core/Mage/Rule/Model/Rule.php +++ b/app/code/core/Mage/Rule/Model/Rule.php @@ -163,6 +163,17 @@ protected function _convertFlatToRecursive(array $rule) } } } else { + /** + * convert dates into Zend_Date + */ + if (in_array($key, array('from_date', 'to_date')) && $value) { + $value = Mage::app()->getLocale()->date( + $value, + Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT), + null, + false + ); + } $this->setData($key, $value); } } @@ -232,13 +243,6 @@ protected function _beforeSave() Mage::throwException(Mage::helper('rule')->__('Invalid discount amount.')); } - // convert dates into Zend_Date and hope it will validate 'em - foreach (array('from_date', 'to_date') as $dateType) { - if ($date = $this->getData($dateType)) { - $format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT); - $this->setData($dateType, Mage::app()->getLocale()->date($date, $format, null, false)); - } - } if ($this->getConditions()) { $this->setConditionsSerialized(serialize($this->getConditions()->asArray())); diff --git a/app/code/core/Mage/Sales/Block/Order/Info.php b/app/code/core/Mage/Sales/Block/Order/Info.php index d2dc16399f..5db61b6489 100644 --- a/app/code/core/Mage/Sales/Block/Order/Info.php +++ b/app/code/core/Mage/Sales/Block/Order/Info.php @@ -18,17 +18,18 @@ * 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_Adminhtml - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @category Mage + * @package Mage_Sales + * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + /** * Invoice view comments form * - * @category Mage - * @package Mage_Sale + * @category Mage + * @package Mage_Sales * @author Magento Core Team */ class Mage_Sales_Block_Order_Info extends Mage_Core_Block_Template @@ -106,4 +107,5 @@ public function getPrintUrl($order) { return $this->getUrl('sales/order/print', array('order_id' => $order->getId())); } -} \ No newline at end of file + +} diff --git a/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php b/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php index e0f88e3a8c..e3b978282a 100644 --- a/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php +++ b/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php @@ -1,124 +1,138 @@ - - */ -class Mage_Sales_Block_Order_Item_Renderer_Default extends Mage_Core_Block_Template -{ - public function setItem(Varien_Object $item) - { - $this->setData('item', $item); - return $this; - } - - public function getItem() - { - return $this->_getData('item'); - } - - /** - * Retrieve current order model instance - * - * @return Mage_Sales_Model_Order - */ - public function getOrder() - { - return $this->getOrderItem()->getOrder(); - } - - - public function getOrderItem() - { - if ($this->getItem() instanceof Mage_Sales_Model_Order_Item) { - return $this->getItem(); - } else { - return $this->getItem()->getOrderItem(); - } - } - - public function getItemOptions() - { - $result = array(); - - if ($options = $this->getOrderItem()->getProductOptions()) { - if (isset($options['options'])) { - $result = array_merge($result, $options['options']); - } - if (isset($options['additional_options'])) { - $result = array_merge($result, $options['additional_options']); - } - if (isset($options['attributes_info'])) { - $result = array_merge($result, $options['attributes_info']); - } - } - - return $result; - } - - public function getFormatedOptionValue($optionValue) - { - $formateOptionValue = array(); - if (is_array($optionValue)) { - $_truncatedValue = implode("\n", $optionValue); - $_truncatedValue = nl2br($_truncatedValue); - return array('value' => $_truncatedValue); - } else { - $_truncatedValue = Mage::helper('core/string')->truncate($optionValue, 55, ''); - $_truncatedValue = nl2br($_truncatedValue); - } - - $formateOptionValue = array( - 'value' => $_truncatedValue - ); - - if (Mage::helper('core/string')->strlen($optionValue) > 55) { - $formateOptionValue['value'] = $formateOptionValue['value'] . ' ...'; - $optionValue = nl2br($optionValue); - $formateOptionValue = array_merge($formateOptionValue, array('full_view' => $optionValue)); - - } - - return $formateOptionValue; - } - - /** - * Return sku of order item. - * - * @return string - */ - public function getSku() - { - if ($this->getOrderItem()->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) { - return $this->getOrderItem()->getProductOptionByCode('simple_sku'); - } - return $this->getItem()->getSku(); - } + + */ +class Mage_Sales_Block_Order_Item_Renderer_Default extends Mage_Core_Block_Template +{ + public function setItem(Varien_Object $item) + { + $this->setData('item', $item); + return $this; + } + + public function getItem() + { + return $this->_getData('item'); + } + + /** + * Retrieve current order model instance + * + * @return Mage_Sales_Model_Order + */ + public function getOrder() + { + return $this->getOrderItem()->getOrder(); + } + + + public function getOrderItem() + { + if ($this->getItem() instanceof Mage_Sales_Model_Order_Item) { + return $this->getItem(); + } else { + return $this->getItem()->getOrderItem(); + } + } + + public function getItemOptions() + { + $result = array(); + + if ($options = $this->getOrderItem()->getProductOptions()) { + if (isset($options['options'])) { + /** + * Remove html tags from option + */ + $productOptions = $options['options']; + if ($this->getPrintStatus()) { + foreach ($productOptions as &$option) { + if (isset($option['value'])) { + $option['value'] = strip_tags($option['value']); + } + } + } + $result = array_merge($result, $productOptions); + } + if (isset($options['additional_options'])) { + $result = array_merge($result, $options['additional_options']); + } + if (isset($options['attributes_info'])) { + $result = array_merge($result, $options['attributes_info']); + } + } + + return $result; + } + + public function getFormatedOptionValue($optionValue) + { + if (Mage::helper('catalog/product_options')->isHtmlFormattedOptionValue($optionValue)) { + return array('value' => $optionValue); + } + + $formateOptionValue = array(); + if (is_array($optionValue)) { + $_truncatedValue = implode("\n", $optionValue); + $_truncatedValue = nl2br($_truncatedValue); + return array('value' => $_truncatedValue); + } else { + $_truncatedValue = Mage::helper('core/string')->truncate($optionValue, 55, ''); + $_truncatedValue = nl2br($_truncatedValue); + } + + $formateOptionValue = array( + 'value' => $_truncatedValue + ); + + if (Mage::helper('core/string')->strlen($optionValue) > 55) { + $formateOptionValue['value'] = $formateOptionValue['value'] . ' ...'; + $optionValue = nl2br($optionValue); + $formateOptionValue = array_merge($formateOptionValue, array('full_view' => $optionValue)); + } + + return $formateOptionValue; + } + + /** + * Return sku of order item. + * + * @return string + */ + public function getSku() + { + if ($this->getOrderItem()->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) { + return $this->getOrderItem()->getProductOptionByCode('simple_sku'); + } + return $this->getItem()->getSku(); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Sales/Model/Convert/Quote.php b/app/code/core/Mage/Sales/Model/Convert/Quote.php index c9dcc57d1e..49a7c905b0 100644 --- a/app/code/core/Mage/Sales/Model/Convert/Quote.php +++ b/app/code/core/Mage/Sales/Model/Convert/Quote.php @@ -1,275 +1,275 @@ - - */ -class Mage_Sales_Model_Convert_Quote extends Varien_Object -{ - - /** - * Convert quote model to order model - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Sales_Model_Order - */ - public function toOrder(Mage_Sales_Model_Quote $quote, $order=null) - { - if (!($order instanceof Mage_Sales_Model_Order)) { - $order = Mage::getModel('sales/order'); - } - /* @var $order Mage_Sales_Model_Order */ - - $order - /** - * Base Data - */ - ->setIncrementId($quote->getReservedOrderId()) - ->setStoreId($quote->getStoreId()) - ->setQuoteId($quote->getId()); - - Mage::helper('core')->copyFieldset('sales_convert_quote', 'to_order', $quote, $order); -// -// ->setRemoteIp($quote->getRemoteIp()) -// -// /** -// * Customer data -// */ -// ->setCustomerId($quote->getCustomerId()) -// ->setCustomerEmail($quote->getCustomerEmail()) -// ->setCustomerPrefix($quote->getCustomerPrefix()) -// ->setCustomerFirstname($quote->getCustomerFirstname()) -// ->setCustomerMiddlename($quote->getCustomerMiddlename()) -// ->setCustomerLastname($quote->getCustomerLastname()) -// ->setCustomerSuffix($quote->getCustomerSuffix()) -// ->setCustomerGroupId($quote->getCustomerGroupId()) -// ->setCustomerTaxClassId($quote->getCustomerTaxClassId()) -// ->setCustomerNote($quote->getCustomerNote()) -// ->setCustomerNoteNotify($quote->getCustomerNoteNotify()) -// ->setCustomerIsGuest($quote->getCustomerIsGuest()) -// ->setCustomerDob($quote->getCustomerDob()) -// -// /** -// * Currency data -// */ -// ->setBaseCurrencyCode($quote->getBaseCurrencyCode()) -// ->setStoreCurrencyCode($quote->getStoreCurrencyCode()) -// ->setOrderCurrencyCode($quote->getQuoteCurrencyCode()) -// ->setStoreToBaseRate($quote->getStoreToBaseRate()) -// ->setStoreToOrderRate($quote->getStoreToQuoteRate()) -// -// /** -// * Another data -// */ -// ->setCouponCode($quote->getCouponCode()) -// ->setGiftcertCode($quote->getGiftcertCode()) -// ->setIsVirtual($quote->getIsVirtual()) -// ->setIsMultiPayment($quote->getIsMultiPayment()) -// ->setAppliedRuleIds($quote->getAppliedRuleIds()); - - - Mage::dispatchEvent('sales_convert_quote_to_order', array('order'=>$order, 'quote'=>$quote)); - return $order; - } - - /** - * Convert quote address model to order - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Sales_Model_Order - */ - public function addressToOrder(Mage_Sales_Model_Quote_Address $address, $order=null) - { - if (!($order instanceof Mage_Sales_Model_Order)) { - $order = $this->toOrder($address->getQuote()); - } - - Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_order', $address, $order); - -// $order -// ->setWeight($address->getWeight()) -// ->setShippingMethod($address->getShippingMethod()) -// ->setShippingDescription($address->getShippingDescription()) -// ->setShippingRate($address->getShippingRate()) -// -// ->setSubtotal($address->getSubtotal()) -// ->setTaxAmount($address->getTaxAmount()) -// ->setDiscountAmount($address->getDiscountAmount()) -// ->setShippingAmount($address->getShippingAmount()) -// ->setShippingTaxAmount($address->getShippingTaxAmount()) -// ->setGiftcertAmount($address->getGiftcertAmount()) -// ->setCustbalanceAmount($address->getCustbalanceAmount()) -// ->setGrandTotal($address->getGrandTotal()) -// -// ->setBaseSubtotal($address->getBaseSubtotal()) -// ->setBaseTaxAmount($address->getBaseTaxAmount()) -// ->setBaseDiscountAmount($address->getBaseDiscountAmount()) -// ->setBaseShippingAmount($address->getBaseShippingAmount()) -// ->setBaseShippingTaxAmount($address->getBaseShippingTaxAmount()) -// ->setBaseGiftcertAmount($address->getBaseGiftcertAmount()) -// ->setBaseCustbalanceAmount($address->getBaseCustbalanceAmount()) -// ->setBaseGrandTotal($address->getBaseGrandTotal()); - - Mage::dispatchEvent('sales_convert_quote_address_to_order', array('address'=>$address, 'order'=>$order)); - return $order; - } - - /** - * Convert quote address to order address - * - * @param Mage_Sales_Model_Quote_Address $address - * @return Mage_Sales_Model_Order_Address - */ - public function addressToOrderAddress(Mage_Sales_Model_Quote_Address $address) - { - $orderAddress = Mage::getModel('sales/order_address') - ->setStoreId($address->getStoreId()) - ->setAddressType($address->getAddressType()) - ->setCustomerId($address->getCustomerId()) - ->setCustomerAddressId($address->getCustomerAddressId()); - - Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_order_address', $address, $orderAddress); -// ->setPrefix($address->getPrefix()) -// ->setFirstname($address->getFirstname()) -// ->setMiddlename($address->getMiddlename()) -// ->setLastname($address->getLastname()) -// ->setSuffix($address->getSuffix()) -// ->setCompany($address->getCompany()) -// ->setStreet($address->getStreet(-1)) -// ->setCity($address->getCity()) -// ->setRegion($address->getRegion()) -// ->setRegionId($address->getRegionId()) -// ->setPostcode($address->getPostcode()) -// ->setCountryId($address->getCountryId()) -// ->setTelephone($address->getTelephone()) -// ->setFax($address->getFax()); - - Mage::dispatchEvent('sales_convert_quote_address_to_order_address', - array('address' => $address, 'order_address' => $orderAddress)); - - return $orderAddress; - } - - /** - * Convert quote payment to order payment - * - * @param Mage_Sales_Model_Quote_Payment $payment - * @return Mage_Sales_Model_Quote_Payment - */ - public function paymentToOrderPayment(Mage_Sales_Model_Quote_Payment $payment) - { - $orderPayment = Mage::getModel('sales/order_payment') - ->setStoreId($payment->getStoreId()) - ->setCustomerPaymentId($payment->getCustomerPaymentId()); - Mage::helper('core')->copyFieldset('sales_convert_quote_payment', 'to_order_payment', $payment, $orderPayment); -// ->setMethod($payment->getMethod()) -// ->setAdditionalData($payment->getAdditionalData()) -// ->setPoNumber($payment->getPoNumber()) -// ->setCcType($payment->getCcType()) -// ->setCcNumberEnc($payment->getCcNumberEnc()) -// ->setCcLast4($payment->getCcLast4()) -// ->setCcOwner($payment->getCcOwner()) -// ->setCcExpMonth($payment->getCcExpMonth()) -// ->setCcExpYear($payment->getCcExpYear()) -// -// ->setCcNumber($payment->getCcNumber()) // only for doing first transaction, not for save -// ->setCcCid($payment->getCcCid()) // only for doing first transaction, not for save -// -// ->setCcSsIssue($payment->getCcSsIssue()) //for direct payment -// ->setCcSsStartMonth($payment->getCcSsStartMonth()) //for direct payment -// ->setCcSsStartYear($payment->getCcSsStartYear()) //for direct payment -// ; - - Mage::dispatchEvent('sales_convert_quote_payment_to_order_payment', - array('order_payment' => $orderPayment, 'quote_payment' => $payment)); - - return $orderPayment; - } - - /** - * Convert quote item to order item - * - * @param Mage_Sales_Model_Quote_Item_Abstract $item - * @return Mage_Sales_Model_Order_Item - */ - public function itemToOrderItem(Mage_Sales_Model_Quote_Item_Abstract $item) - { - $orderItem = Mage::getModel('sales/order_item') - ->setStoreId($item->getStoreId()) - ->setQuoteItemId($item->getId()) - ->setQuoteParentItemId($item->getParentItemId()) - ->setProductId($item->getProductId()) - ->setProductType($item->getProductType()) - ->setProductOptions($item->getProduct()->getTypeInstance()->getOrderOptions()) - ->setQtyBackordered($item->getBackorders()) - ; - - Mage::helper('core')->copyFieldset('sales_convert_quote_item', 'to_order_item', $item, $orderItem); - - if ($item->getParentItem()) { - $orderItem->setQtyOrdered($orderItem->getQtyOrdered()*$item->getParentItem()->getQty()); - } -// ->setSku($item->getSku()) -// ->setName($item->getName()) -// ->setDescription($item->getDescription()) -// ->setWeight($item->getWeight()) -// ->setIsQtyDecimal($item->getIsQtyDecimal()) -// ->setQtyOrdered($item->getQty()) -// ->setOriginalPrice($item->getOriginalPrice()) -// ->setAppliedRuleIds($item->getAppliedRuleIds()) -// ->setAdditionalData($item->getAdditionalData()) -// -// ->setPrice($item->getCalculationPrice()) -// ->setTaxPercent($item->getTaxPercent()) -// ->setTaxAmount($item->getTaxAmount()) -// ->setRowWeight($item->getRowWeight()) -// ->setRowTotal($item->getRowTotal()) -// -// ->setBasePrice($item->getBaseCalculationPrice()) -// ->setBaseOriginalPrice($item->getPrice()) -// ->setBaseTaxAmount($item->getBaseTaxAmount()) -// ->setBaseRowTotal($item->getBaseRowTotal()); - - if (!$item->getNoDiscount()) { - Mage::helper('core')->copyFieldset('sales_convert_quote_item', 'to_order_item_discount', $item, $orderItem); -// $orderItem->setDiscountPercent($item->getDiscountPercent()) -// ->setDiscountAmount($item->getDiscountAmount()) -// ->setBaseDiscountAmount($item->getBaseDiscountAmount()); - } - - Mage::dispatchEvent('sales_convert_quote_item_to_order_item', - array('order_item'=>$orderItem, 'item'=>$item) - ); - return $orderItem; - } -} + + */ +class Mage_Sales_Model_Convert_Quote extends Varien_Object +{ + + /** + * Convert quote model to order model + * + * @param Mage_Sales_Model_Quote $quote + * @return Mage_Sales_Model_Order + */ + public function toOrder(Mage_Sales_Model_Quote $quote, $order=null) + { + if (!($order instanceof Mage_Sales_Model_Order)) { + $order = Mage::getModel('sales/order'); + } + /* @var $order Mage_Sales_Model_Order */ + + $order + /** + * Base Data + */ + ->setIncrementId($quote->getReservedOrderId()) + ->setStoreId($quote->getStoreId()) + ->setQuoteId($quote->getId()); + + Mage::helper('core')->copyFieldset('sales_convert_quote', 'to_order', $quote, $order); +// +// ->setRemoteIp($quote->getRemoteIp()) +// +// /** +// * Customer data +// */ +// ->setCustomerId($quote->getCustomerId()) +// ->setCustomerEmail($quote->getCustomerEmail()) +// ->setCustomerPrefix($quote->getCustomerPrefix()) +// ->setCustomerFirstname($quote->getCustomerFirstname()) +// ->setCustomerMiddlename($quote->getCustomerMiddlename()) +// ->setCustomerLastname($quote->getCustomerLastname()) +// ->setCustomerSuffix($quote->getCustomerSuffix()) +// ->setCustomerGroupId($quote->getCustomerGroupId()) +// ->setCustomerTaxClassId($quote->getCustomerTaxClassId()) +// ->setCustomerNote($quote->getCustomerNote()) +// ->setCustomerNoteNotify($quote->getCustomerNoteNotify()) +// ->setCustomerIsGuest($quote->getCustomerIsGuest()) +// ->setCustomerDob($quote->getCustomerDob()) +// +// /** +// * Currency data +// */ +// ->setBaseCurrencyCode($quote->getBaseCurrencyCode()) +// ->setStoreCurrencyCode($quote->getStoreCurrencyCode()) +// ->setOrderCurrencyCode($quote->getQuoteCurrencyCode()) +// ->setStoreToBaseRate($quote->getStoreToBaseRate()) +// ->setStoreToOrderRate($quote->getStoreToQuoteRate()) +// +// /** +// * Another data +// */ +// ->setCouponCode($quote->getCouponCode()) +// ->setGiftcertCode($quote->getGiftcertCode()) +// ->setIsVirtual($quote->getIsVirtual()) +// ->setIsMultiPayment($quote->getIsMultiPayment()) +// ->setAppliedRuleIds($quote->getAppliedRuleIds()); + + + Mage::dispatchEvent('sales_convert_quote_to_order', array('order'=>$order, 'quote'=>$quote)); + return $order; + } + + /** + * Convert quote address model to order + * + * @param Mage_Sales_Model_Quote $quote + * @return Mage_Sales_Model_Order + */ + public function addressToOrder(Mage_Sales_Model_Quote_Address $address, $order=null) + { + if (!($order instanceof Mage_Sales_Model_Order)) { + $order = $this->toOrder($address->getQuote()); + } + + Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_order', $address, $order); + +// $order +// ->setWeight($address->getWeight()) +// ->setShippingMethod($address->getShippingMethod()) +// ->setShippingDescription($address->getShippingDescription()) +// ->setShippingRate($address->getShippingRate()) +// +// ->setSubtotal($address->getSubtotal()) +// ->setTaxAmount($address->getTaxAmount()) +// ->setDiscountAmount($address->getDiscountAmount()) +// ->setShippingAmount($address->getShippingAmount()) +// ->setShippingTaxAmount($address->getShippingTaxAmount()) +// ->setGiftcertAmount($address->getGiftcertAmount()) +// ->setCustbalanceAmount($address->getCustbalanceAmount()) +// ->setGrandTotal($address->getGrandTotal()) +// +// ->setBaseSubtotal($address->getBaseSubtotal()) +// ->setBaseTaxAmount($address->getBaseTaxAmount()) +// ->setBaseDiscountAmount($address->getBaseDiscountAmount()) +// ->setBaseShippingAmount($address->getBaseShippingAmount()) +// ->setBaseShippingTaxAmount($address->getBaseShippingTaxAmount()) +// ->setBaseGiftcertAmount($address->getBaseGiftcertAmount()) +// ->setBaseCustbalanceAmount($address->getBaseCustbalanceAmount()) +// ->setBaseGrandTotal($address->getBaseGrandTotal()); + + Mage::dispatchEvent('sales_convert_quote_address_to_order', array('address'=>$address, 'order'=>$order)); + return $order; + } + + /** + * Convert quote address to order address + * + * @param Mage_Sales_Model_Quote_Address $address + * @return Mage_Sales_Model_Order_Address + */ + public function addressToOrderAddress(Mage_Sales_Model_Quote_Address $address) + { + $orderAddress = Mage::getModel('sales/order_address') + ->setStoreId($address->getStoreId()) + ->setAddressType($address->getAddressType()) + ->setCustomerId($address->getCustomerId()) + ->setCustomerAddressId($address->getCustomerAddressId()); + + Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_order_address', $address, $orderAddress); +// ->setPrefix($address->getPrefix()) +// ->setFirstname($address->getFirstname()) +// ->setMiddlename($address->getMiddlename()) +// ->setLastname($address->getLastname()) +// ->setSuffix($address->getSuffix()) +// ->setCompany($address->getCompany()) +// ->setStreet($address->getStreet(-1)) +// ->setCity($address->getCity()) +// ->setRegion($address->getRegion()) +// ->setRegionId($address->getRegionId()) +// ->setPostcode($address->getPostcode()) +// ->setCountryId($address->getCountryId()) +// ->setTelephone($address->getTelephone()) +// ->setFax($address->getFax()); + + Mage::dispatchEvent('sales_convert_quote_address_to_order_address', + array('address' => $address, 'order_address' => $orderAddress)); + + return $orderAddress; + } + + /** + * Convert quote payment to order payment + * + * @param Mage_Sales_Model_Quote_Payment $payment + * @return Mage_Sales_Model_Quote_Payment + */ + public function paymentToOrderPayment(Mage_Sales_Model_Quote_Payment $payment) + { + $orderPayment = Mage::getModel('sales/order_payment') + ->setStoreId($payment->getStoreId()) + ->setCustomerPaymentId($payment->getCustomerPaymentId()); + Mage::helper('core')->copyFieldset('sales_convert_quote_payment', 'to_order_payment', $payment, $orderPayment); +// ->setMethod($payment->getMethod()) +// ->setAdditionalData($payment->getAdditionalData()) +// ->setPoNumber($payment->getPoNumber()) +// ->setCcType($payment->getCcType()) +// ->setCcNumberEnc($payment->getCcNumberEnc()) +// ->setCcLast4($payment->getCcLast4()) +// ->setCcOwner($payment->getCcOwner()) +// ->setCcExpMonth($payment->getCcExpMonth()) +// ->setCcExpYear($payment->getCcExpYear()) +// +// ->setCcNumber($payment->getCcNumber()) // only for doing first transaction, not for save +// ->setCcCid($payment->getCcCid()) // only for doing first transaction, not for save +// +// ->setCcSsIssue($payment->getCcSsIssue()) //for direct payment +// ->setCcSsStartMonth($payment->getCcSsStartMonth()) //for direct payment +// ->setCcSsStartYear($payment->getCcSsStartYear()) //for direct payment +// ; + + Mage::dispatchEvent('sales_convert_quote_payment_to_order_payment', + array('order_payment' => $orderPayment, 'quote_payment' => $payment)); + + return $orderPayment; + } + + /** + * Convert quote item to order item + * + * @param Mage_Sales_Model_Quote_Item_Abstract $item + * @return Mage_Sales_Model_Order_Item + */ + public function itemToOrderItem(Mage_Sales_Model_Quote_Item_Abstract $item) + { + $orderItem = Mage::getModel('sales/order_item') + ->setStoreId($item->getStoreId()) + ->setQuoteItemId($item->getId()) + ->setQuoteParentItemId($item->getParentItemId()) + ->setProductId($item->getProductId()) + ->setProductType($item->getProductType()) + ->setProductOptions($item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct())) + ->setQtyBackordered($item->getBackorders()) + ; + + Mage::helper('core')->copyFieldset('sales_convert_quote_item', 'to_order_item', $item, $orderItem); + + if ($item->getParentItem()) { + $orderItem->setQtyOrdered($orderItem->getQtyOrdered()*$item->getParentItem()->getQty()); + } +// ->setSku($item->getSku()) +// ->setName($item->getName()) +// ->setDescription($item->getDescription()) +// ->setWeight($item->getWeight()) +// ->setIsQtyDecimal($item->getIsQtyDecimal()) +// ->setQtyOrdered($item->getQty()) +// ->setOriginalPrice($item->getOriginalPrice()) +// ->setAppliedRuleIds($item->getAppliedRuleIds()) +// ->setAdditionalData($item->getAdditionalData()) +// +// ->setPrice($item->getCalculationPrice()) +// ->setTaxPercent($item->getTaxPercent()) +// ->setTaxAmount($item->getTaxAmount()) +// ->setRowWeight($item->getRowWeight()) +// ->setRowTotal($item->getRowTotal()) +// +// ->setBasePrice($item->getBaseCalculationPrice()) +// ->setBaseOriginalPrice($item->getPrice()) +// ->setBaseTaxAmount($item->getBaseTaxAmount()) +// ->setBaseRowTotal($item->getBaseRowTotal()); + + if (!$item->getNoDiscount()) { + Mage::helper('core')->copyFieldset('sales_convert_quote_item', 'to_order_item_discount', $item, $orderItem); +// $orderItem->setDiscountPercent($item->getDiscountPercent()) +// ->setDiscountAmount($item->getDiscountAmount()) +// ->setBaseDiscountAmount($item->getBaseDiscountAmount()); + } + + Mage::dispatchEvent('sales_convert_quote_item_to_order_item', + array('order_item'=>$orderItem, 'item'=>$item) + ); + return $orderItem; + } +} diff --git a/app/code/core/Mage/Sales/Model/Entity/Order/Attribute/Backend/Billing.php b/app/code/core/Mage/Sales/Model/Entity/Order/Attribute/Backend/Billing.php index de4a52c4a3..bdd28f56c6 100644 --- a/app/code/core/Mage/Sales/Model/Entity/Order/Attribute/Backend/Billing.php +++ b/app/code/core/Mage/Sales/Model/Entity/Order/Attribute/Backend/Billing.php @@ -34,27 +34,43 @@ class Mage_Sales_Model_Entity_Order_Attribute_Backend_Billing extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract { - + /** + * Before save order billing address process + * + * @param Mage_Sales_Model_Order $object + * @return Mage_Sales_Model_Entity_Order_Attribute_Backend_Billing + */ public function beforeSave($object) { $billingAddressId = $object->getBillingAddressId(); if (is_null($billingAddressId)) { $object->unsetBillingAddressId(); } + return $this; } + /** + * After save order billing address process + * + * @param Mage_Sales_Model_Order $object + * @return Mage_Sales_Model_Entity_Order_Attribute_Backend_Billing + */ public function afterSave($object) { $billingAddressId = false; foreach ($object->getAddressesCollection() as $address) { - if ('billing' == $address->getAddressType()) { - $billingAddressId = $address->getId(); - } + /* @var $address Mage_Sales_Model_Order_Address */ + if ('billing' == $address->getAddressType()) { + $billingAddressId = $address->getId(); + } } + if ($billingAddressId) { $object->setBillingAddressId($billingAddressId); $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getAttributeCode()); } + + return $this; } } diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Quote/Item/Collection.php b/app/code/core/Mage/Sales/Model/Mysql4/Quote/Item/Collection.php index 382891a9b0..c34a21e55c 100644 --- a/app/code/core/Mage/Sales/Model/Mysql4/Quote/Item/Collection.php +++ b/app/code/core/Mage/Sales/Model/Mysql4/Quote/Item/Collection.php @@ -1,178 +1,181 @@ - - */ - -class Mage_Sales_Model_Mysql4_Quote_Item_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract -{ - /** - * Collection quote instance - * - * @var Mage_Sales_Model_Quote - */ - protected $_quote; - protected $_productIds = array(); - - protected function _construct() - { - $this->_init('sales/quote_item'); - } - - public function getStoreId() - { - return $this->_quote->getStoreId(); - } - - public function setQuote($quote) - { - $this->_quote = $quote; - $this->addFieldToFilter('quote_id', $quote->getId()); - return $this; - } - - /** - * Reset the collection and inner join it to quotes table - * - * Optionally can select items with specified product id only - * - * @param string $quotesTableName - * @param int $productId - * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection - */ - public function resetJoinQuotes($quotesTableName, $productId = null) - { - $this->getSelect() - ->reset() - ->from(array('qi' => $this->getResource()->getMainTable()), array('item_id', 'qty', 'quote_id')); - $this->getSelect() - ->joinInner(array('q' => $quotesTableName), 'qi.quote_id=q.entity_id', array('store_id', 'items_qty', 'items_count')); - if ($productId) { - $this->getSelect()->where('qi.product_id=?', $productId); - } - return $this; - } - - protected function _afterLoad() - { - parent::_afterLoad(); - /** - * Assign parent items - */ - foreach ($this as $item) { - if ($item->getParentItemId()) { - $item->setParentItem($this->getItemById($item->getParentItemId())); - } - } - - /** - * Assign options and products - */ - $this->_assignOptions() - ->_assignProducts(); - return $this; - } - - /** - * Add options to items - * - * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection - */ - protected function _assignOptions() - { - $itemIds = array_keys($this->_items); - $optionCollection = Mage::getModel('sales/quote_item_option')->getCollection() - ->addItemFilter($itemIds); - foreach ($this as $item) { - $item->setOptions($optionCollection->getOptionsByItem($item)); - } - $productIds = $optionCollection->getProductIds(); - $this->_productIds = array_merge($this->_productIds, $productIds); - return $this; - } - - /** - * Add products to items and item options - * - * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection - */ - protected function _assignProducts() - { - Varien_Profiler::start('QUOTE:'.__METHOD__); - $productIds = array(); - foreach ($this as $item) { - $productIds[] = $item->getProductId(); - } - $this->_productIds = array_merge($this->_productIds, $productIds); - - $productCollection = Mage::getModel('catalog/product')->getCollection() - ->setStoreId($this->getStoreId()) - ->addIdFilter($this->_productIds) - ->addAttributeToSelect(Mage::getSingleton('sales/quote_config')->getProductAttributes()) - ->addOptionsToResult() - ->addStoreFilter() - ->addUrlRewrite(); - - $recollectQuote = false; - foreach ($this as $item) { - if ($this->_quote) { - $item->setQuote($this->_quote); - } - - if ($product = $productCollection->getItemById($item->getProductId())) { - $product->setCustomOptions(array()); - - foreach ($item->getOptions() as $option) { - /** - * Call type specified logic for product associated with quote item - */ - $product->getTypeInstance()->assignProductToOption( - $productCollection->getItemById($option->getProductId()), - $option - ); - } - $item->setProduct($product); - } - else { - $item->isDeleted(true); - $recollectQuote = true; - } - $item->checkData(); - } - - if ($recollectQuote && $this->_quote) { - $this->_quote->collectTotals(); - } - Varien_Profiler::stop('QUOTE:'.__METHOD__); - return $this; - } -} \ No newline at end of file + + */ + +class Mage_Sales_Model_Mysql4_Quote_Item_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract +{ + /** + * Collection quote instance + * + * @var Mage_Sales_Model_Quote + */ + protected $_quote; + protected $_productIds = array(); + + protected function _construct() + { + $this->_init('sales/quote_item'); + } + + public function getStoreId() + { + return $this->_quote->getStoreId(); + } + + public function setQuote($quote) + { + $this->_quote = $quote; + $this->addFieldToFilter('quote_id', $quote->getId()); + return $this; + } + + /** + * Reset the collection and inner join it to quotes table + * + * Optionally can select items with specified product id only + * + * @param string $quotesTableName + * @param int $productId + * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection + */ + public function resetJoinQuotes($quotesTableName, $productId = null) + { + $this->getSelect() + ->reset() + ->from(array('qi' => $this->getResource()->getMainTable()), array('item_id', 'qty', 'quote_id')); + $this->getSelect() + ->joinInner(array('q' => $quotesTableName), 'qi.quote_id=q.entity_id', array('store_id', 'items_qty', 'items_count')); + if ($productId) { + $this->getSelect()->where('qi.product_id=?', $productId); + } + return $this; + } + + protected function _afterLoad() + { + parent::_afterLoad(); + /** + * Assign parent items + */ + foreach ($this as $item) { + if ($item->getParentItemId()) { + $item->setParentItem($this->getItemById($item->getParentItemId())); + } + } + + /** + * Assign options and products + */ + $this->_assignOptions() + ->_assignProducts(); + return $this; + } + + /** + * Add options to items + * + * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection + */ + protected function _assignOptions() + { + $itemIds = array_keys($this->_items); + $optionCollection = Mage::getModel('sales/quote_item_option')->getCollection() + ->addItemFilter($itemIds); + foreach ($this as $item) { + $item->setOptions($optionCollection->getOptionsByItem($item)); + } + $productIds = $optionCollection->getProductIds(); + $this->_productIds = array_merge($this->_productIds, $productIds); + return $this; + } + + /** + * Add products to items and item options + * + * @return Mage_Sales_Model_Mysql4_Quote_Item_Collection + */ + protected function _assignProducts() + { + Varien_Profiler::start('QUOTE:'.__METHOD__); + $productIds = array(); + foreach ($this as $item) { + $productIds[] = $item->getProductId(); + } + $this->_productIds = array_merge($this->_productIds, $productIds); + + $productCollection = Mage::getModel('catalog/product')->getCollection() + ->setStoreId($this->getStoreId()) + ->addIdFilter($this->_productIds) + ->addAttributeToSelect(Mage::getSingleton('sales/quote_config')->getProductAttributes()) + ->addOptionsToResult() + ->addStoreFilter() + ->addUrlRewrite(); + + Mage::dispatchEvent('sales_quote_item_collection_products_after_load', array('product_collection'=>$productCollection)); + + $recollectQuote = false; + foreach ($this as $item) { + if ($this->_quote) { + $item->setQuote($this->_quote); + } + + if ($product = $productCollection->getItemById($item->getProductId())) { + $product->setCustomOptions(array()); + + foreach ($item->getOptions() as $option) { + /** + * Call type specified logic for product associated with quote item + */ + $product->getTypeInstance(true)->assignProductToOption( + $productCollection->getItemById($option->getProductId()), + $option, + $product + ); + } + $item->setProduct($product); + } + else { + $item->isDeleted(true); + $recollectQuote = true; + } + $item->checkData(); + } + + if ($recollectQuote && $this->_quote) { + $this->_quote->collectTotals(); + } + Varien_Profiler::stop('QUOTE:'.__METHOD__); + return $this; + } +} diff --git a/app/code/core/Mage/Sales/Model/Order/Api.php b/app/code/core/Mage/Sales/Model/Order/Api.php index f2c573fad2..7d6ad36589 100644 --- a/app/code/core/Mage/Sales/Model/Order/Api.php +++ b/app/code/core/Mage/Sales/Model/Order/Api.php @@ -88,8 +88,8 @@ public function items($filters = null) if (is_array($filters)) { try { foreach ($filters as $field => $value) { - if (isset($this->_filtersMap[$field])) { - $field = $this->_filtersMap[$field]; + if (isset($this->_attributesMap['order'][$field])) { + $field = $this->_attributesMap['order'][$field]; } $collection->addFieldToFilter($field, $value); diff --git a/app/code/core/Mage/Sales/Model/Order/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Api/V2.php new file mode 100644 index 0000000000..a733e5a1f0 --- /dev/null +++ b/app/code/core/Mage/Sales/Model/Order/Api/V2.php @@ -0,0 +1,95 @@ + + */ +class Mage_Sales_Model_Order_Api_V2 extends Mage_Sales_Model_Order_Api +{ + /** + * Retrieve list of orders by filters + * + * @param array $filters + * @return array + */ + public function items($filters = null) + { + //TODO: add full name logic + $collection = Mage::getResourceModel('sales/order_collection') + ->addAttributeToSelect('*') + ->joinAttribute('billing_firstname', 'order_address/firstname', 'billing_address_id', null, 'left') + ->joinAttribute('billing_lastname', 'order_address/lastname', 'billing_address_id', null, 'left') + ->joinAttribute('shipping_firstname', 'order_address/firstname', 'shipping_address_id', null, 'left') + ->joinAttribute('shipping_lastname', 'order_address/lastname', 'shipping_address_id', null, 'left') + ->addExpressionAttributeToSelect('billing_name', + 'CONCAT({{billing_firstname}}, " ", {{billing_lastname}})', + array('billing_firstname', 'billing_lastname')) + ->addExpressionAttributeToSelect('shipping_name', + 'CONCAT({{shipping_firstname}}, " ", {{shipping_lastname}})', + array('shipping_firstname', 'shipping_lastname')); + + $preparedFilters = array(); + if (isset($filters->filter)) { + foreach ($filters->filter as $_filter) { + $preparedFilters[$_filter->key] = $_filter->value; + } + } + if (isset($filters->complex_filter)) { + foreach ($filters->complex_filter as $_filter) { + $_value = $_filter->value; + $preparedFilters[$_filter->key] = array( + $_value->key => $_value->value + ); + } + } + + if (!empty($preparedFilters)) { + try { + foreach ($preparedFilters as $field => $value) { + if (isset($this->_attributesMap['order'][$field])) { + $field = $this->_attributesMap['order'][$field]; + } + + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + + foreach ($collection as $order) { + $result[] = $this->_getAttributes($order, 'order'); + } + + return $result; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php b/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php index ecb2ce405d..d4889afab3 100644 --- a/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php +++ b/app/code/core/Mage/Sales/Model/Order/Invoice/Api.php @@ -72,8 +72,8 @@ public function items($filters = null) if (is_array($filters)) { try { foreach ($filters as $field => $value) { - if (isset($this->_filtersMap[$field])) { - $field = $this->_filtersMap[$field]; + if (isset($this->_attributesMap['invoice'][$field])) { + $field = $this->_attributesMap['invoice'][$field]; } $collection->addFieldToFilter($field, $value); diff --git a/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php new file mode 100644 index 0000000000..c7474ddae8 --- /dev/null +++ b/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php @@ -0,0 +1,162 @@ + + */ +class Mage_Sales_Model_Order_Invoice_Api_V2 extends Mage_Sales_Model_Order_Invoice_Api +{ + /** + * Retrive invoices by filters + * + * @param array $filters + * @return array + */ + public function items($filters = null) + { + //TODO: add full name logic + $collection = Mage::getResourceModel('sales/order_invoice_collection') + ->addAttributeToSelect('order_id') + ->addAttributeToSelect('increment_id') + ->addAttributeToSelect('created_at') + ->addAttributeToSelect('state') + ->addAttributeToSelect('grand_total') + ->addAttributeToSelect('order_currency_code') + ->joinAttribute('billing_firstname', 'order_address/firstname', 'billing_address_id', null, 'left') + ->joinAttribute('billing_lastname', 'order_address/lastname', 'billing_address_id', null, 'left') + ->joinAttribute('order_increment_id', 'order/increment_id', 'order_id', null, 'left') + ->joinAttribute('order_created_at', 'order/created_at', 'order_id', null, 'left'); + + $preparedFilters = array(); + if (isset($filters->filter)) { + foreach ($filters->filter as $_filter) { + $preparedFilters[$_filter->key] = $_filter->value; + } + } + if (isset($filters->complex_filter)) { + foreach ($filters->complex_filter as $_filter) { + $_value = $_filter->value; + $preparedFilters[$_filter->key] = array( + $_value->key => $_value->value + ); + } + } + + if (!empty($preparedFilters)) { + try { + foreach ($preparedFilters as $field => $value) { + if (isset($this->_attributesMap['invoice'][$field])) { + $field = $this->_attributesMap['invoice'][$field]; + } + + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + + foreach ($collection as $invoice) { + $result[] = $this->_getAttributes($invoice, 'invoice'); + } + + return $result; + } + + protected function _prepareItemQtyData($data) + { + $_data = array(); + foreach ($data as $item) { + if (isset($item->order_item_id) && isset($item->qty)) { + $_data[$item->order_item_id] = $item->qty; + } + } + return $_data; + } + + /** + * Create new invoice for order + * + * @param string $orderIncrementId + * @param array $itemsQty + * @param string $comment + * @param booleam $email + * @param boolean $includeComment + * @return string + */ + public function create($orderIncrementId, $itemsQty, $comment = null, $email = false, $includeComment = false) + { + $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId); + $itemsQty = $this->_prepareItemQtyData($itemsQty); + /* @var $order Mage_Sales_Model_Order */ + /** + * Check order existing + */ + if (!$order->getId()) { + $this->_fault('order_not_exists'); + } + + /** + * Check invoice create availability + */ + if (!$order->canInvoice()) { + $this->_fault('data_invalid', Mage::helper('sales')->__('Can not do invoice for order.')); + } + + $invoice = $order->prepareInvoice($itemsQty); + + $invoice->register(); + + if ($comment !== null) { + $invoice->addComment($comment, $email); + } + + if ($email) { + $invoice->setEmailSent(true); + } + + $invoice->getOrder()->setIsInProcess(true); + + try { + $transactionSave = Mage::getModel('core/resource_transaction') + ->addObject($invoice) + ->addObject($invoice->getOrder()) + ->save(); + + $invoice->sendEmail($email, ($includeComment ? $comment : '')); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $invoice->getIncrementId(); + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Sales/Model/Order/Pdf/Creditmemo.php b/app/code/core/Mage/Sales/Model/Order/Pdf/Creditmemo.php index 6d3cc736e5..09f4a069c6 100644 --- a/app/code/core/Mage/Sales/Model/Order/Pdf/Creditmemo.php +++ b/app/code/core/Mage/Sales/Model/Order/Pdf/Creditmemo.php @@ -44,6 +44,9 @@ public function getPdf($creditmemos = array()) $this->_setFontBold($style, 10); foreach ($creditmemos as $creditmemo) { + if ($creditmemo->getStoreId()) { + Mage::app()->getLocale()->emulate($creditmemo->getStoreId()); + } $page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); $pdf->pages[] = $page; @@ -109,6 +112,9 @@ public function getPdf($creditmemos = array()) $this->_afterGetPdf(); + if ($creditmemo->getStoreId()) { + Mage::app()->getLocale()->revert(); + } return $pdf; } diff --git a/app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php b/app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php index dc4d993a43..e293c84e5d 100644 --- a/app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php +++ b/app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php @@ -44,6 +44,9 @@ public function getPdf($invoices = array()) $this->_setFontBold($style, 10); foreach ($invoices as $invoice) { + if ($invoice->getStoreId()) { + Mage::app()->getLocale()->emulate($invoice->getStoreId()); + } $page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); $pdf->pages[] = $page; @@ -122,6 +125,10 @@ public function getPdf($invoices = array()) /* Add totals */ $this->insertTotals($page, $invoice); + + if ($invoice->getStoreId()) { + Mage::app()->getLocale()->revert(); + } } $this->_afterGetPdf(); diff --git a/app/code/core/Mage/Sales/Model/Order/Pdf/Shipment.php b/app/code/core/Mage/Sales/Model/Order/Pdf/Shipment.php index 83aefa4696..03b6f14178 100644 --- a/app/code/core/Mage/Sales/Model/Order/Pdf/Shipment.php +++ b/app/code/core/Mage/Sales/Model/Order/Pdf/Shipment.php @@ -43,6 +43,9 @@ public function getPdf($shipments = array()) $style = new Zend_Pdf_Style(); $this->_setFontBold($style, 10); foreach ($shipments as $shipment) { + if ($shipment->getStoreId()) { + Mage::app()->getLocale()->emulate($shipment->getStoreId()); + } $page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); $pdf->pages[] = $page; @@ -116,6 +119,9 @@ public function getPdf($shipments = array()) $this->_afterGetPdf(); + if ($shipment->getStoreId()) { + Mage::app()->getLocale()->revert(); + } return $pdf; } } \ No newline at end of file diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php index 155fb81e66..19c435559e 100644 --- a/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php +++ b/app/code/core/Mage/Sales/Model/Order/Shipment/Api.php @@ -65,8 +65,8 @@ public function items($filters = null) if (is_array($filters)) { try { foreach ($filters as $field => $value) { - if (isset($this->_filtersMap[$field])) { - $field = $this->_filtersMap[$field]; + if (isset($this->_attributesMap['shipment'][$field])) { + $field = $this->_attributesMap['shipment'][$field]; } $collection->addFieldToFilter($field, $value); diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php new file mode 100644 index 0000000000..f935338d5f --- /dev/null +++ b/app/code/core/Mage/Sales/Model/Order/Shipment/Api/V2.php @@ -0,0 +1,198 @@ + + */ +class Mage_Sales_Model_Order_Shipment_Api_V2 extends Mage_Sales_Model_Order_Shipment_Api +{ + /** + * Retrive shipments by filters + * + * @param array $filters + * @return array + */ + public function items($filters = null) + { + //TODO: add full name logic + $collection = Mage::getResourceModel('sales/order_shipment_collection') + ->addAttributeToSelect('increment_id') + ->addAttributeToSelect('created_at') + ->addAttributeToSelect('total_qty') + ->joinAttribute('shipping_firstname', 'order_address/firstname', 'shipping_address_id', null, 'left') + ->joinAttribute('shipping_lastname', 'order_address/lastname', 'shipping_address_id', null, 'left') + ->joinAttribute('order_increment_id', 'order/increment_id', 'order_id', null, 'left') + ->joinAttribute('order_created_at', 'order/created_at', 'order_id', null, 'left'); + + $preparedFilters = array(); + if (isset($filters->filter)) { + foreach ($filters->filter as $_filter) { + $preparedFilters[$_filter->key] = $_filter->value; + } + } + if (isset($filters->complex_filter)) { + foreach ($filters->complex_filter as $_filter) { + $_value = $_filter->value; + $preparedFilters[$_filter->key] = array( + $_value->key => $_value->value + ); + } + } + + if (!empty($preparedFilters)) { + try { + foreach ($preparedFilters as $field => $value) { + if (isset($this->_attributesMap['shipment'][$field])) { + $field = $this->_attributesMap['shipment'][$field]; + } + + $collection->addFieldToFilter($field, $value); + } + } catch (Mage_Core_Exception $e) { + $this->_fault('filters_invalid', $e->getMessage()); + } + } + + $result = array(); + + foreach ($collection as $shipment) { + $result[] = $this->_getAttributes($shipment, 'shipment'); + } + + return $result; + } + + protected function _prepareItemQtyData($data) + { + $_data = array(); + foreach ($data as $item) { + if (isset($item->order_item_id) && isset($item->qty)) { + $_data[$item->order_item_id] = $item->qty; + } + } + return $_data; + } + + /** + * Create new shipment for order + * + * @param string $orderIncrementId + * @param array $itemsQty + * @param string $comment + * @param booleam $email + * @param boolean $includeComment + * @return string + */ + public function create($orderIncrementId, $itemsQty = array(), $comment = null, $email = false, $includeComment = false) + { + $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId); + $itemsQty = $this->_prepareItemQtyData($itemsQty); + /** + * Check order existing + */ + if (!$order->getId()) { + $this->_fault('order_not_exists'); + } + + /** + * Check shipment create availability + */ + if (!$order->canShip()) { + $this->_fault('data_invalid', Mage::helper('sales')->__('Can not do shipment for order.')); + } + + $convertor = Mage::getModel('sales/convert_order'); + $shipment = $convertor->toShipment($order); + /* @var $shipment Mage_Sales_Model_Order_Shipment */ + + foreach ($order->getAllItems() as $orderItem) { + if (!$orderItem->getQtyToShip()) { + continue; + } + if ($orderItem->getIsVirtual()) { + continue; + } + $item = $convertor->itemToShipmentItem($orderItem); + if (isset($itemsQty[$orderItem->getId()])) { + $qty = $itemsQty[$orderItem->getId()]; + } + else { + $qty = $orderItem->getQtyToShip(); + } + $item->setQty($qty); + $shipment->addItem($item); + } + $shipment->register(); + $shipment->addComment($comment, $email && $includeComment); + + if ($email) { + $shipment->setEmailSent(true); + } + + $shipment->getOrder()->setIsInProcess(true); + + try { + $transactionSave = Mage::getModel('core/resource_transaction') + ->addObject($shipment) + ->addObject($shipment->getOrder()) + ->save(); + + $shipment->sendEmail($email, ($includeComment ? $comment : '')); + } catch (Mage_Core_Exception $e) { + $this->_fault('data_invalid', $e->getMessage()); + } + + return $shipment->getIncrementId(); + } + + /** + * Retrieve allowed shipping carriers for specified order + * + * @param string $orderIncrementId + * @return array + */ + public function getCarriers($orderIncrementId) + { + $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId); + + /** + * Check order existing + */ + if (!$order->getId()) { + $this->_fault('order_not_exists'); + } + $carriers = array(); + foreach ($this->_getCarriers($order) as $key => $value) { + $carriers[] = array('key' => $key, 'value' => $value); + } + + return $carriers; + } +} diff --git a/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php b/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php index d8a772f925..a040f8eb08 100644 --- a/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php +++ b/app/code/core/Mage/Sales/Model/Order/Shipment/Track.php @@ -59,6 +59,10 @@ public function setShipment(Mage_Sales_Model_Order_Shipment $shipment) */ public function getShipment() { + if (!($this->_shipment instanceof Mage_Sales_Model_Order_Shipment)) { + $this->_shipment = Mage::getModel('sales/order_shipment')->load($this->getParentId()); + } + return $this->_shipment; } @@ -79,6 +83,8 @@ public function getNumberDetail() $custom['title'] = $this->getTitle(); $custom['number'] = $this->getNumber(); return $custom; + } else { + $carrierInstance->setStore($this->getStore()); } if (!$trackingInfo = $carrierInstance->getTrackingInfo($this->getNumber())) { diff --git a/app/code/core/Mage/Sales/Model/Quote.php b/app/code/core/Mage/Sales/Model/Quote.php index 1439422c51..14ec2010a8 100644 --- a/app/code/core/Mage/Sales/Model/Quote.php +++ b/app/code/core/Mage/Sales/Model/Quote.php @@ -605,6 +605,7 @@ public function removeItem($itemId) $child->isDeleted(true); } } + Mage::dispatchEvent('sales_quote_remove_item', array('quote_item' => $item)); } return $this; } @@ -620,6 +621,7 @@ public function addItem(Mage_Sales_Model_Quote_Item $item) $item->setQuote($this); if (!$item->getId()) { $this->getItemsCollection()->addItem($item); + Mage::dispatchEvent('sales_quote_add_item', array('quote_item' => $item)); } return $this; } @@ -645,7 +647,8 @@ public function addProduct(Mage_Catalog_Model_Product $product, $request=null) Mage::throwException(Mage::helper('sales')->__('Invalid request for adding product to quote')); } - $cartCandidates = $product->getTypeInstance()->prepareForCart($request); + $cartCandidates = $product->getTypeInstance(true) + ->prepareForCart($request, $product); /** * Error message @@ -1067,7 +1070,7 @@ public function hasVirtualItems() if ($_item->getParentItemId()) { continue; } - if ($_item->getProduct()->getTypeInstance()->isVirtual()) { + if ($_item->getProduct()->isVirtual()) { $hasVirtual = true; } } @@ -1126,13 +1129,16 @@ protected function _validateCouponCode() $code = $this->_getData('coupon_code'); if ($code) { $addressHasCoupon = false; - foreach ($this->getAllAddresses() as $address) { - if ($address->hasCouponCode()) { - $addressHasCoupon = true; - } - } - if (!$addressHasCoupon) { - $this->setCouponCode(''); + $addresses = $this->getAllAddresses(); + if (count($addresses)>0) { + foreach ($addresses as $address) { + if ($address->hasCouponCode()) { + $addressHasCoupon = true; + } + } + if (!$addressHasCoupon) { + $this->setCouponCode(''); + } } } return $this; diff --git a/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php b/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php index 49ac257182..17eba71195 100644 --- a/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php +++ b/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php @@ -1,178 +1,178 @@ -getWeight(); - $address->setWeight(0); - $address->setShippingAmount(0); - $address->setBaseShippingAmount(0); - $address->setFreeMethodWeight(0); - - $items = $address->getAllItems(); - if (!count($items)) { - return $this; - } - - $method = $address->getShippingMethod(); - $freeAddress = $address->getFreeShipping(); - - $addressWeight = $address->getWeight(); - $freeMethodWeight = $address->getFreeMethodWeight(); - - $addressQty = 0; - - foreach ($items as $item) { - /** - * Skip if this item is virtual - */ - - if ($item->getProduct()->getTypeInstance()->isVirtual()) { - continue; - } - /** - * Children weight we calculate for parent - */ - if ($item->getParentItem()) { - continue; - } - - if ($item->getHasChildren() && $item->isShipSeparately()) { - foreach ($item->getChildren() as $child) { - if ($child->getProduct()->getTypeInstance()->isVirtual()) { - continue; - } - $addressQty += $item->getQty()*$child->getQty(); - - if (!$item->getProduct()->getWeightType()) { - $itemWeight = $child->getWeight(); - $itemQty = $item->getQty()*$child->getQty(); - $rowWeight = $itemWeight*$itemQty; - $addressWeight += $rowWeight; - if ($freeAddress || $child->getFreeShipping()===true) { - $rowWeight = 0; - } elseif (is_numeric($child->getFreeShipping())) { - $freeQty = $child->getFreeShipping(); - if ($itemQty>$freeQty) { - $rowWeight = $itemWeight*($itemQty-$freeQty); - } - else { - $rowWeight = 0; - } - } - $freeMethodWeight += $rowWeight; - } - $item->setRowWeight($rowWeight); - } - if ($item->getProduct()->getWeightType()) { - $itemWeight = $item->getWeight(); - $rowWeight = $itemWeight*$item->getQty(); - $addressWeight+= $rowWeight; - if ($freeAddress || $item->getFreeShipping()===true) { - $rowWeight = 0; - } elseif (is_numeric($item->getFreeShipping())) { - $freeQty = $item->getFreeShipping(); - if ($item->getQty()>$freeQty) { - $rowWeight = $itemWeight*($item->getQty()-$freeQty); - } - else { - $rowWeight = 0; - } - } - $freeMethodWeight+= $rowWeight; - $item->setRowWeight($rowWeight); - } - } - else { - if (!$item->getProduct()->getTypeInstance()->isVirtual()) { - $addressQty += $item->getQty(); - } - $itemWeight = $item->getWeight(); - $rowWeight = $itemWeight*$item->getQty(); - $addressWeight+= $rowWeight; - if ($freeAddress || $item->getFreeShipping()===true) { - $rowWeight = 0; - } elseif (is_numeric($item->getFreeShipping())) { - $freeQty = $item->getFreeShipping(); - if ($item->getQty()>$freeQty) { - $rowWeight = $itemWeight*($item->getQty()-$freeQty); - } - else { - $rowWeight = 0; - } - } - $freeMethodWeight+= $rowWeight; - $item->setRowWeight($rowWeight); - } - } - - if (isset($addressQty)) { - $address->setItemQty($addressQty); - } - - $address->setWeight($addressWeight); - $address->setFreeMethodWeight($freeMethodWeight); - - $address->collectShippingRates(); - - $address->setShippingAmount(0); - $address->setBaseShippingAmount(0); - - $method = $address->getShippingMethod(); - - if ($method) { - foreach ($address->getAllShippingRates() as $rate) { - if ($rate->getCode()==$method) { - $amountPrice = $address->getQuote()->getStore()->convertPrice($rate->getPrice(), false); - $address->setShippingAmount($amountPrice); - $address->setBaseShippingAmount($rate->getPrice()); - $address->setShippingDescription($rate->getCarrierTitle().' - '.$rate->getMethodTitle()); - break; - } - } - } - - $address->setGrandTotal($address->getGrandTotal() + $address->getShippingAmount()); - $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getBaseShippingAmount()); - return $this; - } - - public function fetch(Mage_Sales_Model_Quote_Address $address) - { - $amount = $address->getShippingAmount(); - if ($amount!=0 || $address->getShippingDescription()) { - $address->addTotal(array( - 'code'=>$this->getCode(), - 'title'=>Mage::helper('sales')->__('Shipping & Handling').' ('.$address->getShippingDescription().')', - 'value'=>$address->getShippingAmount() - )); - } - return $this; - } -} +getWeight(); + $address->setWeight(0); + $address->setShippingAmount(0); + $address->setBaseShippingAmount(0); + $address->setFreeMethodWeight(0); + + $items = $address->getAllItems(); + if (!count($items)) { + return $this; + } + + $method = $address->getShippingMethod(); + $freeAddress = $address->getFreeShipping(); + + $addressWeight = $address->getWeight(); + $freeMethodWeight = $address->getFreeMethodWeight(); + + $addressQty = 0; + + foreach ($items as $item) { + /** + * Skip if this item is virtual + */ + + if ($item->getProduct()->isVirtual()) { + continue; + } + /** + * Children weight we calculate for parent + */ + if ($item->getParentItem()) { + continue; + } + + if ($item->getHasChildren() && $item->isShipSeparately()) { + foreach ($item->getChildren() as $child) { + if ($child->getProduct()->isVirtual()) { + continue; + } + $addressQty += $item->getQty()*$child->getQty(); + + if (!$item->getProduct()->getWeightType()) { + $itemWeight = $child->getWeight(); + $itemQty = $item->getQty()*$child->getQty(); + $rowWeight = $itemWeight*$itemQty; + $addressWeight += $rowWeight; + if ($freeAddress || $child->getFreeShipping()===true) { + $rowWeight = 0; + } elseif (is_numeric($child->getFreeShipping())) { + $freeQty = $child->getFreeShipping(); + if ($itemQty>$freeQty) { + $rowWeight = $itemWeight*($itemQty-$freeQty); + } + else { + $rowWeight = 0; + } + } + $freeMethodWeight += $rowWeight; + $item->setRowWeight($rowWeight); + } + } + if ($item->getProduct()->getWeightType()) { + $itemWeight = $item->getWeight(); + $rowWeight = $itemWeight*$item->getQty(); + $addressWeight+= $rowWeight; + if ($freeAddress || $item->getFreeShipping()===true) { + $rowWeight = 0; + } elseif (is_numeric($item->getFreeShipping())) { + $freeQty = $item->getFreeShipping(); + if ($item->getQty()>$freeQty) { + $rowWeight = $itemWeight*($item->getQty()-$freeQty); + } + else { + $rowWeight = 0; + } + } + $freeMethodWeight+= $rowWeight; + $item->setRowWeight($rowWeight); + } + } + else { + if (!$item->getProduct()->isVirtual()) { + $addressQty += $item->getQty(); + } + $itemWeight = $item->getWeight(); + $rowWeight = $itemWeight*$item->getQty(); + $addressWeight+= $rowWeight; + if ($freeAddress || $item->getFreeShipping()===true) { + $rowWeight = 0; + } elseif (is_numeric($item->getFreeShipping())) { + $freeQty = $item->getFreeShipping(); + if ($item->getQty()>$freeQty) { + $rowWeight = $itemWeight*($item->getQty()-$freeQty); + } + else { + $rowWeight = 0; + } + } + $freeMethodWeight+= $rowWeight; + $item->setRowWeight($rowWeight); + } + } + + if (isset($addressQty)) { + $address->setItemQty($addressQty); + } + + $address->setWeight($addressWeight); + $address->setFreeMethodWeight($freeMethodWeight); + + $address->collectShippingRates(); + + $address->setShippingAmount(0); + $address->setBaseShippingAmount(0); + + $method = $address->getShippingMethod(); + + if ($method) { + foreach ($address->getAllShippingRates() as $rate) { + if ($rate->getCode()==$method) { + $amountPrice = $address->getQuote()->getStore()->convertPrice($rate->getPrice(), false); + $address->setShippingAmount($amountPrice); + $address->setBaseShippingAmount($rate->getPrice()); + $address->setShippingDescription($rate->getCarrierTitle().' - '.$rate->getMethodTitle()); + break; + } + } + } + + $address->setGrandTotal($address->getGrandTotal() + $address->getShippingAmount()); + $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getBaseShippingAmount()); + return $this; + } + + public function fetch(Mage_Sales_Model_Quote_Address $address) + { + $amount = $address->getShippingAmount(); + if ($amount!=0 || $address->getShippingDescription()) { + $address->addTotal(array( + 'code'=>$this->getCode(), + 'title'=>Mage::helper('sales')->__('Shipping & Handling').' ('.$address->getShippingDescription().')', + 'value'=>$address->getShippingAmount() + )); + } + return $this; + } +} diff --git a/app/code/core/Mage/Sales/Model/Quote/Item.php b/app/code/core/Mage/Sales/Model/Quote/Item.php index 79ed2afa22..401070a926 100644 --- a/app/code/core/Mage/Sales/Model/Quote/Item.php +++ b/app/code/core/Mage/Sales/Model/Quote/Item.php @@ -1,491 +1,501 @@ -_init('sales/quote_item'); - } - - protected function _beforeSave() - { - parent::_beforeSave(); - $this->setIsVirtual($this->getProduct()->getIsVirtual()); - if ($this->getQuote()) { - $this->setQuoteId($this->getQuote()->getId()); - } - return $this; - } - - /** - * Declare quote model object - * - * @param Mage_Sales_Model_Quote $quote - * @return Mage_Sales_Model_Quote_Item - */ - public function setQuote(Mage_Sales_Model_Quote $quote) - { - $this->_quote = $quote; - $this->setQuoteId($quote->getId()); - return $this; - } - - /** - * Retrieve quote model object - * - * @return Mage_Sales_Model_Quote - */ - public function getQuote() - { - return $this->_quote; - } - - protected function _prepareQty($qty) - { - $qty = Mage::app()->getLocale()->getNumber($qty); - $qty = ($qty > 0) ? $qty : 1; - return $qty; - } - - /** - * Adding quantity to quote item - * - * @param float $qty - * @return Mage_Sales_Model_Quote_Item - */ - public function addQty($qty) - { - $oldQty = $this->getQty(); - $qty = $this->_prepareQty($qty); - - /** - * We can't modify quontity of existing items which have parent - * This qty declared just once duering add process and is not editable - */ - if (!$this->getParentItem() || !$this->getId()) { - $this->setQtyToAdd($qty); - $this->setQty($oldQty+$qty); - } - return $this; - } - - /** - * Declare quote item quantity - * - * @param float $qty - * @return Mage_Sales_Model_Quote_Item - */ - public function setQty($qty) - { - $qty = $this->_prepareQty($qty); - - - $oldQty = $this->_getData('qty'); - $this->setData('qty', $qty); - - Mage::dispatchEvent('sales_quote_item_qty_set_after', array('item'=>$this)); - - if ($this->getQuote() && $this->getQuote()->getIgnoreOldQty()) { - return $this; - } - if ($this->getUseOldQty()) { - $this->setData('qty', $oldQty); - } - return $this; - } - - /** - * Retrieve option product with Qty - * - * Return array - * 'qty' => the qty - * 'product' => the product model - * - * @return array - */ - public function getQtyOptions() - { - $productIds = array(); - $return = array(); - foreach ($this->getOptions() as $option) { - /* @var $option Mage_Sales_Model_Quote_Item_Option */ - if (is_object($option->getProduct()) && $option->getProduct()->getId() != $this->getProduct()->getId() - && !isset($productIds[$option->getProduct()->getId()])) { - $productIds[$option->getProduct()->getId()] = $option->getProduct()->getId(); - } - } - - foreach ($productIds as $productId) { - if ($option = $this->getOptionByCode('product_qty_' . $productId)) { - $return[$productId] = $option; - } - } - - return $return; - } - - /** - * Setup product for quote item - * - * @param Mage_Catalog_Model_Product $product - * @return Mage_Sales_Model_Quote_Item - */ - public function setProduct($product) - { - if ($this->getQuote()) { - $product->setStoreId($this->getQuote()->getStoreId()); - } - $this->setData('product', $product) - ->setProductId($product->getId()) - ->setProductType($product->getTypeId()) - ->setSku($this->getProduct()->getSku()) - ->setName($product->getName()) - ->setWeight($this->getProduct()->getWeight()) - ->setTaxClassId($product->getTaxClassId()) - ->setCost($product->getCost()) +_init('sales/quote_item'); + } + + protected function _beforeSave() + { + parent::_beforeSave(); + $this->setIsVirtual($this->getProduct()->getIsVirtual()); + if ($this->getQuote()) { + $this->setQuoteId($this->getQuote()->getId()); + } + return $this; + } + + /** + * Declare quote model object + * + * @param Mage_Sales_Model_Quote $quote + * @return Mage_Sales_Model_Quote_Item + */ + public function setQuote(Mage_Sales_Model_Quote $quote) + { + $this->_quote = $quote; + $this->setQuoteId($quote->getId()); + return $this; + } + + /** + * Retrieve quote model object + * + * @return Mage_Sales_Model_Quote + */ + public function getQuote() + { + return $this->_quote; + } + + protected function _prepareQty($qty) + { + $qty = Mage::app()->getLocale()->getNumber($qty); + $qty = ($qty > 0) ? $qty : 1; + return $qty; + } + + /** + * Adding quantity to quote item + * + * @param float $qty + * @return Mage_Sales_Model_Quote_Item + */ + public function addQty($qty) + { + $oldQty = $this->getQty(); + $qty = $this->_prepareQty($qty); + + /** + * We can't modify quontity of existing items which have parent + * This qty declared just once duering add process and is not editable + */ + if (!$this->getParentItem() || !$this->getId()) { + $this->setQtyToAdd($qty); + $this->setQty($oldQty+$qty); + } + return $this; + } + + /** + * Declare quote item quantity + * + * @param float $qty + * @return Mage_Sales_Model_Quote_Item + */ + public function setQty($qty) + { + $qty = $this->_prepareQty($qty); + + + $oldQty = $this->_getData('qty'); + $this->setData('qty', $qty); + + Mage::dispatchEvent('sales_quote_item_qty_set_after', array('item'=>$this)); + + if ($this->getQuote() && $this->getQuote()->getIgnoreOldQty()) { + return $this; + } + if ($this->getUseOldQty()) { + $this->setData('qty', $oldQty); + } + return $this; + } + + /** + * Retrieve option product with Qty + * + * Return array + * 'qty' => the qty + * 'product' => the product model + * + * @return array + */ + public function getQtyOptions() + { + $productIds = array(); + $return = array(); + foreach ($this->getOptions() as $option) { + /* @var $option Mage_Sales_Model_Quote_Item_Option */ + if (is_object($option->getProduct()) && $option->getProduct()->getId() != $this->getProduct()->getId() + && !isset($productIds[$option->getProduct()->getId()])) { + $productIds[$option->getProduct()->getId()] = $option->getProduct()->getId(); + } + } + + foreach ($productIds as $productId) { + if ($option = $this->getOptionByCode('product_qty_' . $productId)) { + $return[$productId] = $option; + } + } + + return $return; + } + + /** + * Setup product for quote item + * + * @param Mage_Catalog_Model_Product $product + * @return Mage_Sales_Model_Quote_Item + */ + public function setProduct($product) + { + if ($this->getQuote()) { + $product->setStoreId($this->getQuote()->getStoreId()); + } + $this->setData('product', $product) + ->setProductId($product->getId()) + ->setProductType($product->getTypeId()) + ->setSku($this->getProduct()->getSku()) + ->setName($product->getName()) + ->setWeight($this->getProduct()->getWeight()) + ->setTaxClassId($product->getTaxClassId()) + ->setCost($product->getCost()) ->setIsQtyDecimal($product->getIsQtyDecimal()); -// if ($options = $product->getCustomOptions()) { -// foreach ($options as $option) { -// $this->addOption($option); -// } -// } - return $this; - } - - /** - * Retrieve product model object associated with item - * - * @return Mage_Catalog_Model_Product - */ - public function getProduct() - { - $product = $this->_getData('product'); - if (($product === null) && $this->getProductId()) { - $product = Mage::getModel('catalog/product') - ->setStoreId($this->getQuote()->getStoreId()) - ->load($this->getProductId()); - $this->setProduct($product); - } - $product->setCustomOptions($this->_optionsByCode); - return $product; - } - - /** - * Check product representation in item - * - * @param Mage_Catalog_Model_Product $product - * @return bool - */ - public function representProduct($product) - { - $itemProduct = $this->getProduct(); - if ($itemProduct->getId() != $product->getId()) { - return false; - } - - $itemOptions = $this->getOptions(); - $productOptions = $product->getCustomOptions(); - if (count($itemOptions) != count($productOptions)) { - return false; - } - - foreach ($itemOptions as $option) { - $code = $option->getCode(); - if (in_array($code, $this->_norRepresentOptions )) { - continue; - } - if ( !isset($productOptions[$code]) - || ($productOptions[$code]->getValue() === null) - || $productOptions[$code]->getValue() != $option->getValue()) { - return false; - } - } - return true; - } - - /** - * Compare item - * - * @param Mage_Sales_Model_Quote_Item $item - * @return bool - */ - public function compare($item) - { - if ($this->getProductId() != $item->getProductId()) { - return false; - } - foreach ($this->getOptions() as $option) { - if ($itemOption = $item->getOptionByCode($option->getCode())) { - $itemOptionValue = $itemOption->getValue(); - $optionValue = $option->getValue(); - - // dispose of some options params, that can cramp comparing of arrays - if (is_string($itemOptionValue) && is_string($optionValue)) { - $_itemOptionValue = @unserialize($itemOptionValue); - $_optionValue = @unserialize($optionValue); - if (is_array($_itemOptionValue) && is_array($_optionValue)) { - $itemOptionValue = $_itemOptionValue; - $optionValue = $_optionValue; - // looks like it does not break bundle selection qty - unset($itemOptionValue['qty'], $itemOptionValue['uenc'], $optionValue['qty'], $optionValue['uenc']); - } - } - - if ($itemOptionValue != $optionValue) { - return false; - } - } - else { - return false; - } - } - return true; - } - - /** - * Get item product type - * - * @return string - */ - public function getProductType() - { - if ($option = $this->getOptionByCode('product_type')) { - return $option->getValue(); - } - if ($product = $this->getProduct()) { - return $product->getTypeId(); - } - return $this->_getData('product_type'); - } - - /** - * Return real product type of item - * - * @return unknown - */ - public function getRealProductType() - { - return $this->_getData('product_type'); - } - - public function toArray(array $arrAttributes=array()) - { - $data = parent::toArray($arrAttributes); - - if ($product = $this->getProduct()) { - $data['product'] = $product->toArray(); - } - return $data; - } - - /** - * Initialize quote item options - * - * @param array $options - * @return Mage_Sales_Model_Quote_Item - */ - public function setOptions($options) - { - foreach ($options as $option) { - $this->addOption($option); - } - return $this; - } - - /** - * Get all item options - * - * @return array - */ - public function getOptions() - { - return $this->_options; - } - - /** - * Add option to item - * - * @param Mage_Sales_Model_Quote_Item_Option $option - * @return Mage_Sales_Model_Quote_Item - */ - public function addOption($option) - { - if (is_array($option)) { - $option = Mage::getModel('sales/quote_item_option')->setData($option) - ->setItem($this); - } - elseif (($option instanceof Varien_Object) && !($option instanceof Mage_Sales_Model_Quote_Item_Option)) { - $option = Mage::getModel('sales/quote_item_option')->setData($option->getData()) - ->setProduct($option->getProduct()) - ->setItem($this); - } - elseif($option instanceof Mage_Sales_Model_Quote_Item_Option) { - $option->setItem($this); - } - else { - Mage::throwException(Mage::helper('sales')->__('Invalid item option format')); - } - - if ($exOption = $this->getOptionByCode($option->getCode())) { - $exOption->addData($option->getData()); - } - else { - $this->_addOptionCode($option); - $this->_options[] = $option; - } - return $this; - } - - /** - * Can specify specific actions for ability to change given quote options values - * Exemple: cataloginventory decimal qty validation may change qty to int, - * so need to change quote item qty option value. - * - * @param array $options - * @param Varien_Object $option - * @param mixed $value - * - * @return object Mage_Catalog_Model_Product_Type_Abstract - */ - public function updateQtyOption(Varien_Object $option, $value) - { - $optionProduct = $option->getProduct(); - - $options = $this->getQtyOptions(); - if (isset($options[$optionProduct->getId()])) { - $options[$optionProduct->getId()]->setValue($value); - } - - $this->getProduct()->getTypeInstance() - ->updateQtyOption($this->getOptions(), $option, $value); - - return $this; - } - - /** - *Remove option from item options - * - * @param string $code - * @return Mage_Sales_Model_Quote_Item - */ - public function removeOption($code) - { - if ($option = $this->getOptionByCode($code)) { - $option->isDeleted(true); - } - return $this; - } - - /** - * Register option code - * - * @param Mage_Sales_Model_Quote_Item_Option $option - * @return Mage_Sales_Model_Quote_Item - */ - protected function _addOptionCode($option) - { - if (!isset($this->_optionsByCode[$option->getCode()])) { - $this->_optionsByCode[$option->getCode()] = $option; - } - else { - Mage::throwException(Mage::helper('sales')->__('Item option with code %s already exist', $option->getCode())); - } - return $this; - } - - /** - * Get item option by code - * - * @param string $code - * @return Mage_Sales_Model_Quote_Item_Option || null - */ - public function getOptionByCode($code) - { - if (isset($this->_optionsByCode[$code]) && !$this->_optionsByCode[$code]->isDeleted()) { - return $this->_optionsByCode[$code]; - } - return null; - } - - /** - * Save item options - * - * @return Mage_Sales_Model_Quote_Item - */ - protected function _afterSave() - { - foreach ($this->_options as $index => $option) { - if ($option->isDeleted()) { - $option->delete(); - unset($this->_options[$index]); - unset($this->_optionsByCode[$option->getCode()]); - } - else { - $option->save(); - } - } - return parent::_afterSave(); - } - - /** - * Clone quote item - * - * @return Mage_Sales_Model_Quote_Item - */ - public function __clone() - { - parent::__clone(); - $options = $this->getOptions(); - $this->_quote = null; - $this->_options = array(); - $this->_optionsByCode = array(); - foreach ($options as $option) { - $this->addOption(clone $option); - } - return $this; - } + Mage::dispatchEvent('sales_quote_item_set_product', array( + 'product' => $product, + 'quote_item'=>$this + )); + +// if ($options = $product->getCustomOptions()) { +// foreach ($options as $option) { +// $this->addOption($option); +// } +// } + return $this; + } + + /** + * Retrieve product model object associated with item + * + * @return Mage_Catalog_Model_Product + */ + public function getProduct() + { + $product = $this->_getData('product'); + if (($product === null) && $this->getProductId()) { + $product = Mage::getModel('catalog/product') + ->setStoreId($this->getQuote()->getStoreId()) + ->load($this->getProductId()); + $this->setProduct($product); + } + + /** + * Reset product final price because it related to custom options + */ + $product->setFinalPrice(null); + $product->setCustomOptions($this->_optionsByCode); + return $product; + } + + /** + * Check product representation in item + * + * @param Mage_Catalog_Model_Product $product + * @return bool + */ + public function representProduct($product) + { + $itemProduct = $this->getProduct(); + if ($itemProduct->getId() != $product->getId()) { + return false; + } + + $itemOptions = $this->getOptions(); + $productOptions = $product->getCustomOptions(); + if (count($itemOptions) != count($productOptions)) { + return false; + } + + foreach ($itemOptions as $option) { + $code = $option->getCode(); + if (in_array($code, $this->_norRepresentOptions )) { + continue; + } + if ( !isset($productOptions[$code]) + || ($productOptions[$code]->getValue() === null) + || $productOptions[$code]->getValue() != $option->getValue()) { + return false; + } + } + return true; + } + + /** + * Compare item + * + * @param Mage_Sales_Model_Quote_Item $item + * @return bool + */ + public function compare($item) + { + if ($this->getProductId() != $item->getProductId()) { + return false; + } + foreach ($this->getOptions() as $option) { + if ($itemOption = $item->getOptionByCode($option->getCode())) { + $itemOptionValue = $itemOption->getValue(); + $optionValue = $option->getValue(); + + // dispose of some options params, that can cramp comparing of arrays + if (is_string($itemOptionValue) && is_string($optionValue)) { + $_itemOptionValue = @unserialize($itemOptionValue); + $_optionValue = @unserialize($optionValue); + if (is_array($_itemOptionValue) && is_array($_optionValue)) { + $itemOptionValue = $_itemOptionValue; + $optionValue = $_optionValue; + // looks like it does not break bundle selection qty + unset($itemOptionValue['qty'], $itemOptionValue['uenc'], $optionValue['qty'], $optionValue['uenc']); + } + } + + if ($itemOptionValue != $optionValue) { + return false; + } + } + else { + return false; + } + } + return true; + } + + /** + * Get item product type + * + * @return string + */ + public function getProductType() + { + if ($option = $this->getOptionByCode('product_type')) { + return $option->getValue(); + } + if ($product = $this->getProduct()) { + return $product->getTypeId(); + } + return $this->_getData('product_type'); + } + + /** + * Return real product type of item + * + * @return unknown + */ + public function getRealProductType() + { + return $this->_getData('product_type'); + } + + public function toArray(array $arrAttributes=array()) + { + $data = parent::toArray($arrAttributes); + + if ($product = $this->getProduct()) { + $data['product'] = $product->toArray(); + } + return $data; + } + + /** + * Initialize quote item options + * + * @param array $options + * @return Mage_Sales_Model_Quote_Item + */ + public function setOptions($options) + { + foreach ($options as $option) { + $this->addOption($option); + } + return $this; + } + + /** + * Get all item options + * + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Add option to item + * + * @param Mage_Sales_Model_Quote_Item_Option $option + * @return Mage_Sales_Model_Quote_Item + */ + public function addOption($option) + { + if (is_array($option)) { + $option = Mage::getModel('sales/quote_item_option')->setData($option) + ->setItem($this); + } + elseif (($option instanceof Varien_Object) && !($option instanceof Mage_Sales_Model_Quote_Item_Option)) { + $option = Mage::getModel('sales/quote_item_option')->setData($option->getData()) + ->setProduct($option->getProduct()) + ->setItem($this); + } + elseif($option instanceof Mage_Sales_Model_Quote_Item_Option) { + $option->setItem($this); + } + else { + Mage::throwException(Mage::helper('sales')->__('Invalid item option format')); + } + + if ($exOption = $this->getOptionByCode($option->getCode())) { + $exOption->addData($option->getData()); + } + else { + $this->_addOptionCode($option); + $this->_options[] = $option; + } + return $this; + } + + /** + * Can specify specific actions for ability to change given quote options values + * Exemple: cataloginventory decimal qty validation may change qty to int, + * so need to change quote item qty option value. + * + * @param array $options + * @param Varien_Object $option + * @param mixed $value + * + * @return object Mage_Catalog_Model_Product_Type_Abstract + */ + public function updateQtyOption(Varien_Object $option, $value) + { + $optionProduct = $option->getProduct(); + + $options = $this->getQtyOptions(); + if (isset($options[$optionProduct->getId()])) { + $options[$optionProduct->getId()]->setValue($value); + } + + $this->getProduct()->getTypeInstance(true) + ->updateQtyOption($this->getOptions(), $option, $value, $this->getProduct()); + + return $this; + } + + /** + *Remove option from item options + * + * @param string $code + * @return Mage_Sales_Model_Quote_Item + */ + public function removeOption($code) + { + if ($option = $this->getOptionByCode($code)) { + $option->isDeleted(true); + } + return $this; + } + + /** + * Register option code + * + * @param Mage_Sales_Model_Quote_Item_Option $option + * @return Mage_Sales_Model_Quote_Item + */ + protected function _addOptionCode($option) + { + if (!isset($this->_optionsByCode[$option->getCode()])) { + $this->_optionsByCode[$option->getCode()] = $option; + } + else { + Mage::throwException(Mage::helper('sales')->__('Item option with code %s already exist', $option->getCode())); + } + return $this; + } + + /** + * Get item option by code + * + * @param string $code + * @return Mage_Sales_Model_Quote_Item_Option || null + */ + public function getOptionByCode($code) + { + if (isset($this->_optionsByCode[$code]) && !$this->_optionsByCode[$code]->isDeleted()) { + return $this->_optionsByCode[$code]; + } + return null; + } + + /** + * Save item options + * + * @return Mage_Sales_Model_Quote_Item + */ + protected function _afterSave() + { + foreach ($this->_options as $index => $option) { + if ($option->isDeleted()) { + $option->delete(); + unset($this->_options[$index]); + unset($this->_optionsByCode[$option->getCode()]); + } + else { + $option->save(); + } + } + return parent::_afterSave(); + } + + /** + * Clone quote item + * + * @return Mage_Sales_Model_Quote_Item + */ + public function __clone() + { + parent::__clone(); + $options = $this->getOptions(); + $this->_quote = null; + $this->_options = array(); + $this->_optionsByCode = array(); + foreach ($options as $option) { + $this->addOption(clone $option); + } + return $this; + } } \ No newline at end of file diff --git a/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php b/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php index 4135959e4c..7fd762e1ad 100644 --- a/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php +++ b/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php @@ -177,7 +177,7 @@ public function checkData() } try { - $this->getProduct()->getTypeInstance()->checkProductBuyState(); + $this->getProduct()->getTypeInstance(true)->checkProductBuyState($this->getProduct()); } catch (Mage_Core_Exception $e) { $this->setHasError(true); $this->setMessage($e->getMessage()); @@ -425,8 +425,25 @@ protected function _calculatePrice($value, $saveTaxes = true) $sAddress = $bAddress; } - $priceExcludingTax = Mage::helper('tax')->getPrice($this->getProduct()->setTaxPercent(null), $value, false, $sAddress, $bAddress, $this->getQuote()->getCustomerTaxClassId(), $store); - $priceIncludingTax = Mage::helper('tax')->getPrice($this->getProduct()->setTaxPercent(null), $value, true, $sAddress, $bAddress, $this->getQuote()->getCustomerTaxClassId(), $store); + $priceExcludingTax = Mage::helper('tax')->getPrice( + $this->getProduct()->setTaxPercent(null), + $value, + false, + $sAddress, + $bAddress, + $this->getQuote()->getCustomerTaxClassId(), + $store + ); + + $priceIncludingTax = Mage::helper('tax')->getPrice( + $this->getProduct()->setTaxPercent(null), + $value, + true, + $sAddress, + $bAddress, + $this->getQuote()->getCustomerTaxClassId(), + $store + ); if ($saveTaxes) { $qty = $this->getQty(); @@ -436,8 +453,24 @@ protected function _calculatePrice($value, $saveTaxes = true) if (Mage::helper('tax')->displayCartPriceInclTax($store)) { $rowTotal = $value*$qty; - $rowTotalExcTax = Mage::helper('tax')->getPrice($this->getProduct()->setTaxPercent(null), $rowTotal, false, $sAddress, $bAddress, $this->getQuote()->getCustomerTaxClassId(), $store); - $rowTotalIncTax = Mage::helper('tax')->getPrice($this->getProduct()->setTaxPercent(null), $rowTotal, true, $sAddress, $bAddress, $this->getQuote()->getCustomerTaxClassId(), $store); + $rowTotalExcTax = Mage::helper('tax')->getPrice( + $this->getProduct()->setTaxPercent(null), + $rowTotal, + false, + $sAddress, + $bAddress, + $this->getQuote()->getCustomerTaxClassId(), + $store + ); + $rowTotalIncTax = Mage::helper('tax')->getPrice( + $this->getProduct()->setTaxPercent(null), + $rowTotal, + true, + $sAddress, + $bAddress, + $this->getQuote()->getCustomerTaxClassId(), + $store + ); $totalBaseTax = $rowTotalIncTax-$rowTotalExcTax; $this->setRowTotalExcTax($rowTotalExcTax); } diff --git a/app/code/core/Mage/Sales/controllers/DownloadController.php b/app/code/core/Mage/Sales/controllers/DownloadController.php new file mode 100644 index 0000000000..f63d3930ad --- /dev/null +++ b/app/code/core/Mage/Sales/controllers/DownloadController.php @@ -0,0 +1,88 @@ + + */ + +class Mage_Sales_DownloadController extends Mage_Core_Controller_Front_Action +{ + + /** + * Custom options downloader + */ + public function downloadCustomOptionAction () + { + $quoteItemOptionId = $this->getRequest()->getParam('id'); + $secretKey = $this->getRequest()->getParam('key'); + $option = Mage::getModel('sales/quote_item_option')->load($quoteItemOptionId); + + if ($option->getId()) { + + try { + $info = unserialize($option->getValue()); + + if ($secretKey != $info['secret_key']) { + throw new Exception(); + } + + $filePath = Mage::getBaseDir() . $info['order_path']; + if (!is_file($filePath) || !is_readable($filePath)) { + // try get file from quote + $filePath = Mage::getBaseDir() . $info['quote_path']; + if (!is_file($filePath) || !is_readable($filePath)) { + throw new Exception(); + } + } + + $this->getResponse() + ->setHttpResponseCode(200) + ->setHeader('Pragma', 'public', true) + ->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true) + ->setHeader('Content-type', $info['type'], true) + ->setHeader('Content-Length', $info['size']) + ->setHeader('Content-Disposition', 'inline' . '; filename='.$info['title']); + + $this->getResponse() + ->clearBody(); + $this->getResponse() + ->sendHeaders(); + + readfile($filePath); + + } catch (Exception $e) { + $this->_forward('noRoute'); + } + + } else { + $this->_forward('noRoute'); + } + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Sales/etc/api.xml b/app/code/core/Mage/Sales/etc/api.xml index 66d8f63577..8330605c06 100644 --- a/app/code/core/Mage/Sales/etc/api.xml +++ b/app/code/core/Mage/Sales/etc/api.xml @@ -203,6 +203,13 @@ sales_order_shipment sales_order_invoice + + + salesOrder + salesOrderShipment + salesOrderInvoice + + diff --git a/app/code/core/Mage/Sales/etc/config.xml b/app/code/core/Mage/Sales/etc/config.xml index 663ef4020f..1d8cac80c7 100644 --- a/app/code/core/Mage/Sales/etc/config.xml +++ b/app/code/core/Mage/Sales/etc/config.xml @@ -28,7 +28,7 @@ - 0.9.31 + 0.9.32 @@ -347,9 +347,9 @@ Mage_Sales_Model_Mysql4 sales_flat_quote
+ sales_flat_quote_item
sales_flat_quote_address
sales_flat_quote_address_item
- sales_flat_quote_item
sales_flat_quote_item_option
sales_flat_quote_payment
sales_flat_quote_shipping_rate
@@ -483,6 +483,15 @@ Mage_Sales_Block + + + + + global/sales/quote/item/product_attributes + + + + diff --git a/app/code/core/Mage/Sales/etc/wsdl.xml b/app/code/core/Mage/Sales/etc/wsdl.xml new file mode 100644 index 0000000000..afa09729cb --- /dev/null +++ b/app/code/core/Mage/Sales/etc/wsdl.xml @@ -0,0 +1,879 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Retrieve list of orders by filters + + + + + Retrieve order information + + + + + Add comment to order + + + + + Hold order + + + + + Unhold order + + + + + Cancel order + + + + + Retrieve list of shipments by filters + + + + + Retrieve shipment information + + + + + Create new shipment for order + + + + + Add new comment to shipment + + + + + Add new tracking number + + + + + Remove tracking number + + + + + Retrieve list of allowed carriers for order + + + + + Retrieve list of invoices by filters + + + + + Retrieve invoice information + + + + + Create new invoice for order + + + + + Add new comment to shipment + + + + + Capture invoice + + + + + Void invoice + + + + + Cancel invoice + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.6.2-0.7.0.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.6.2-0.7.0.php index 35a9e1b7a2..cdef4132f7 100644 --- a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.6.2-0.7.0.php +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.6.2-0.7.0.php @@ -31,8 +31,8 @@ $installer->run(" -UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n

\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order. You can check the status of your order by logging into your account. If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (800) DEMO-NUMBER Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.getFormated(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.getFormated(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; -UPDATE {$this->getTable('core_email_template')} set template_text='\r\n
\r\n\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Dear {{var billing.name}},
\r\n Your order # {{var order.increment_id}} has been {{var order.getStatusLabel()}}.

\r\n

{{var comment}}

\r\n

If you have any questions, please feel free to contact us at \r\n dummyemail@magentocommerce.com or by phone at (800) DEMO-STORE.

\r\n

Thank you again,
Magento Demo Store

\r\n
\r\n
\r\n
\r\n' WHERE template_code='Order update (HTML)'; +UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order. You can check the status of your order by logging into your account. If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (555) 555-0123 Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.getFormated(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.getFormated(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; +UPDATE {$this->getTable('core_email_template')} set template_text='\r\n
\r\n\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Dear {{var billing.name}},
\r\n Your order # {{var order.increment_id}} has been {{var order.getStatusLabel()}}.

\r\n

{{var comment}}

\r\n

If you have any questions, please feel free to contact us at \r\n dummyemail@magentocommerce.com or by phone at (555) 555-0123.

\r\n

Thank you again,
Magento Demo Store

\r\n
\r\n
\r\n
\r\n' WHERE template_code='Order update (HTML)'; DROP TABLE IF EXISTS {$this->getTable('sales_order_status')}; diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.7.2-0.7.3.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.7.2-0.7.3.php index 15578e44dd..966ee2356a 100644 --- a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.7.2-0.7.3.php +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.7.2-0.7.3.php @@ -30,8 +30,8 @@ $installer->startSetup(); $installer->run(" -UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order. You can check the status of your order by logging into your account. If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (800) DEMO-NUMBER Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.format(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.format(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; -UPDATE {$this->getTable('core_email_template')} set template_text='\r\n
\r\n\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Dear {{var billing.name}},
\r\n Your order # {{var order.increment_id}} has been {{var order.getStatusLabel()}}.

\r\n

{{var comment}}

\r\n

If you have any questions, please feel free to contact us at \r\n dummyemail@magentocommerce.com or by phone at (800) DEMO-STORE.

\r\n

Thank you again,
Magento Demo Store

\r\n
\r\n
\r\n
\r\n' WHERE template_code='Order update (HTML)'; +UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order. You can check the status of your order by logging into your account. If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (555) 555-0123 Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.format(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.format(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; +UPDATE {$this->getTable('core_email_template')} set template_text='\r\n
\r\n\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Dear {{var billing.name}},
\r\n Your order # {{var order.increment_id}} has been {{var order.getStatusLabel()}}.

\r\n

{{var comment}}

\r\n

If you have any questions, please feel free to contact us at \r\n dummyemail@magentocommerce.com or by phone at (555) 555-0123.

\r\n

Thank you again,
Magento Demo Store

\r\n
\r\n
\r\n
\r\n' WHERE template_code='Order update (HTML)'; "); $installer->endSetup(); diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.8.3-0.8.4.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.8.3-0.8.4.php index ba2687e529..47941e3d3f 100644 --- a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.8.3-0.8.4.php +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.8.3-0.8.4.php @@ -30,7 +30,7 @@ $installer->startSetup(); $installer->run(" -UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order.{{depend order.getCustomerId()}} You can check the status of your order by logging into your account.{{/depend}} If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (800) DEMO-NUMBER Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.format(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.format(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; +UPDATE {$this->getTable('core_email_template')} set template_text='\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \"Magento\"
\r\n\r\n \r\n \r\n \r\n \r\n \r\n
\r\n

Hello {{var billing.name}},
\r\n Thank you for your order from Magento Demo Store. Once your package ships we will send an email with a link to track your order.{{depend order.getCustomerId()}} You can check the status of your order by logging into your account.{{/depend}} If you have any questions about your order please contact us at dummyemail@magentocommerce.com or call us at (555) 555-0123 Monday - Friday, 8am - 5pm PST.

\r\n

Your order confirmation is below. Thank you again for your business.

\r\n \r\n

Your Order #{{var order.increment_id}} (placed on {{var order.getCreatedAtFormated(\'long\')}})

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Billing \r\n Information:Payment \r\n Method:
{{var order.billing_address.format(\'html\')}}  {{var payment_html}}

\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Shipping \r\n Information:Shipping \r\n Method:
{{var order.shipping_address.format(\'html\')}} {{var order.shipping_description}}

\r\n\r\n{{var items_html}}
\r\n {{var order.getEmailCustomerNote()}} \r\n

Thank you again,
Magento Demo Store

\r\n\r\n\r\n
\r\n \r\n
\r\n
\r\n' WHERE template_code='New order (HTML)'; "); $installer->endSetup(); diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.29-0.9.30.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.29-0.9.30.php index 2ad7e089e2..7da3ec4071 100644 --- a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.29-0.9.30.php +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.29-0.9.30.php @@ -30,6 +30,41 @@ $tableOrder = $this->getTable('sales/order'); $tableOrderEntity = $this->getTable('sales/order_entity'); +$cleanTables = array( + $tableOrder . '_datetime', + $tableOrder . '_decimal', + $tableOrder . '_int', + $tableOrder . '_text', + $tableOrder . '_varchar', + $tableOrderEntity . '_decimal', + $tableOrderEntity . '_datetime', + $tableOrderEntity . '_int', + $tableOrderEntity . '_text', + $tableOrderEntity . '_varchar' +); +foreach ($cleanTables as $tableName) { + $select = $installer->getConnection()->select() + ->from($tableName, array( + 'entity_id' => 'entity_id', + 'attribute_id' => 'attribute_id', + 'entity_type_id' => 'entity_type_id', + 'rows_count' => 'COUNT(*)')) + ->group(array('entity_id', 'attribute_id', 'entity_type_id')) + ->having('rows_count > 1'); + $query = $installer->getConnection()->query($select); + + while ($row = $query->fetch()) { + $sql = 'DELETE FROM `' . $tableName . '`' + . ' WHERE entity_id=? AND attribute_id=? AND entity_type_id=?' + . ' LIMIT ' . ($row['rows_count'] - 1); + $installer->getConnection()->query($sql, array( + $row['entity_id'], + $row['attribute_id'], + $row['entity_type_id'] + )); + } +} + $installer->getConnection()->addKey("{$tableOrder}_datetime", 'UNQ_ENTITY_ATTRIBUTE_TYPE', array('entity_id', 'attribute_id', 'entity_type_id'), 'unique'); $installer->getConnection()->addKey("{$tableOrder}_decimal", 'UNQ_ENTITY_ATTRIBUTE_TYPE', array('entity_id', 'attribute_id', 'entity_type_id'), 'unique'); $installer->getConnection()->addKey("{$tableOrder}_int", 'UNQ_ENTITY_ATTRIBUTE_TYPE', array('entity_id', 'attribute_id', 'entity_type_id'), 'unique'); diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.30-0.9.31.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.30-0.9.31.php index 29874e9da1..4d3184be89 100644 --- a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.30-0.9.31.php +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.30-0.9.31.php @@ -37,6 +37,5 @@ $installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'subtotal_with_discount', 'decimal(12,4)'); $installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'base_subtotal_with_discount', 'decimal(12,4)'); $installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'is_changed', 'int(10) unsigned'); -$installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'global_currency_code', 'decimal(12,4)'); $installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'base_to_global_rate', 'decimal(12,4)'); $installer->getConnection()->modifyColumn($installer->getTable('sales/quote'), 'base_to_quote_rate', 'decimal(12,4)'); diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.31-0.9.32.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.31-0.9.32.php new file mode 100644 index 0000000000..3d845b0928 --- /dev/null +++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-0.9.31-0.9.32.php @@ -0,0 +1,30 @@ +getConnection()->modifyColumn($installer->getTable('sales/quote'), 'global_currency_code', 'varchar(255)'); diff --git a/app/code/core/Mage/SalesRule/Model/Mysql4/Rule.php b/app/code/core/Mage/SalesRule/Model/Mysql4/Rule.php index 8342ea1167..fd20e96f2e 100644 --- a/app/code/core/Mage/SalesRule/Model/Mysql4/Rule.php +++ b/app/code/core/Mage/SalesRule/Model/Mysql4/Rule.php @@ -37,13 +37,17 @@ public function _beforeSave(Mage_Core_Model_Abstract $object) if (!$object->getFromDate()) { $object->setFromDate(new Zend_Date(Mage::getModel('core/date')->gmtTimestamp())); } - $object->setFromDate($object->getFromDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + if ($object->getFromDate() instanceof Zend_Date) { + $object->setFromDate($object->getFromDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + } if (!$object->getToDate()) { $object->setToDate(new Zend_Db_Expr('NULL')); } else { - $object->setToDate($object->getToDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + if ($object->getToDate() instanceof Zend_Date) { + $object->setToDate($object->getToDate()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)); + } } if (!$object->getDiscountQty()) { diff --git a/app/code/core/Mage/SalesRule/Model/Validator.php b/app/code/core/Mage/SalesRule/Model/Validator.php index b2cba7d376..b3991609d9 100644 --- a/app/code/core/Mage/SalesRule/Model/Validator.php +++ b/app/code/core/Mage/SalesRule/Model/Validator.php @@ -252,7 +252,7 @@ public function process(Mage_Sales_Model_Quote_Item_Abstract $item) $appliedRuleIds[$rule->getRuleId()] = $rule->getRuleId(); - if ($rule->getCouponCode() && ($rule->getCouponCode() == $this->getCouponCode())) { + if ($rule->getCouponCode() && ( strtolower($rule->getCouponCode()) == strtolower($this->getCouponCode()))) { $address->setCouponCode($this->getCouponCode()); } diff --git a/app/code/core/Mage/SalesRule/etc/config.xml b/app/code/core/Mage/SalesRule/etc/config.xml index 899c69a407..0fca08fa66 100644 --- a/app/code/core/Mage/SalesRule/etc/config.xml +++ b/app/code/core/Mage/SalesRule/etc/config.xml @@ -51,12 +51,6 @@ salesrule_customer
- - salesrule_product
-
- - salesrule_product_price
-
diff --git a/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php b/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php index 8eb73989fc..dc9cfaa7e2 100644 --- a/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php +++ b/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php @@ -131,10 +131,6 @@ protected function _updateFreeMethodQuote($request) return; } $freeRateId = false; -// if (!is_object($this->_result)) { -// mageDebugBacktrace(); -// exit; -// } if (is_object($this->_result)) { foreach ($this->_result->getAllRates() as $i=>$item) { @@ -165,7 +161,14 @@ protected function _updateFreeMethodQuote($request) } } } + } else { + /** + * if we can apply free shipping for all order we should force price + * to $0.00 for shipping with out sending second request to carrier + */ + $price = 0; } + /** * if we did not get our free shipping method in response we must use its old price */ diff --git a/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php b/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php index ad8adb0bbb..607b9bd6fd 100644 --- a/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php +++ b/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php @@ -1,103 +1,103 @@ - - */ -class Mage_Shipping_Model_Carrier_Flatrate - extends Mage_Shipping_Model_Carrier_Abstract - implements Mage_Shipping_Model_Carrier_Interface -{ - - protected $_code = 'flatrate'; - - /** - * Enter description here... - * - * @param Mage_Shipping_Model_Rate_Request $data - * @return Mage_Shipping_Model_Rate_Result - */ - public function collectRates(Mage_Shipping_Model_Rate_Request $request) - { - if (!$this->getConfigFlag('active')) { - return false; - } - - $freeBoxes = 0; - if ($request->getAllItems()) { - foreach ($request->getAllItems() as $item) { - if ($item->getFreeShipping() && !$item->getProduct()->getTypeInstance()->isVirtual()) { - $freeBoxes+=$item->getQty(); - } - } - } - $this->setFreeBoxes($freeBoxes); - - $result = Mage::getModel('shipping/rate_result'); - if ($this->getConfigData('type') == 'O') { // per order - $shippingPrice = $this->getConfigData('price'); - } elseif ($this->getConfigData('type') == 'I') { // per item - $shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price')); - } else { - $shippingPrice = false; - } - - $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice); - - if ($shippingPrice !== false) { - $method = Mage::getModel('shipping/rate_result_method'); - - $method->setCarrier('flatrate'); - $method->setCarrierTitle($this->getConfigData('title')); - - $method->setMethod('flatrate'); - $method->setMethodTitle($this->getConfigData('name')); - - if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) { - $shippingPrice = '0.00'; - } - - - $method->setPrice($shippingPrice); - $method->setCost($shippingPrice); - - $result->append($method); - } - - return $result; - } - - public function getAllowedMethods() - { - return array('flatrate'=>$this->getConfigData('name')); - } - -} + + */ +class Mage_Shipping_Model_Carrier_Flatrate + extends Mage_Shipping_Model_Carrier_Abstract + implements Mage_Shipping_Model_Carrier_Interface +{ + + protected $_code = 'flatrate'; + + /** + * Enter description here... + * + * @param Mage_Shipping_Model_Rate_Request $data + * @return Mage_Shipping_Model_Rate_Result + */ + public function collectRates(Mage_Shipping_Model_Rate_Request $request) + { + if (!$this->getConfigFlag('active')) { + return false; + } + + $freeBoxes = 0; + if ($request->getAllItems()) { + foreach ($request->getAllItems() as $item) { + if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) { + $freeBoxes+=$item->getQty(); + } + } + } + $this->setFreeBoxes($freeBoxes); + + $result = Mage::getModel('shipping/rate_result'); + if ($this->getConfigData('type') == 'O') { // per order + $shippingPrice = $this->getConfigData('price'); + } elseif ($this->getConfigData('type') == 'I') { // per item + $shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price')); + } else { + $shippingPrice = false; + } + + $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice); + + if ($shippingPrice !== false) { + $method = Mage::getModel('shipping/rate_result_method'); + + $method->setCarrier('flatrate'); + $method->setCarrierTitle($this->getConfigData('title')); + + $method->setMethod('flatrate'); + $method->setMethodTitle($this->getConfigData('name')); + + if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) { + $shippingPrice = '0.00'; + } + + + $method->setPrice($shippingPrice); + $method->setCost($shippingPrice); + + $result->append($method); + } + + return $result; + } + + public function getAllowedMethods() + { + return array('flatrate'=>$this->getConfigData('name')); + } + +} diff --git a/app/code/core/Mage/Shipping/Model/Rate/Result.php b/app/code/core/Mage/Shipping/Model/Rate/Result.php index 47889fb921..34f88b0568 100644 --- a/app/code/core/Mage/Shipping/Model/Rate/Result.php +++ b/app/code/core/Mage/Shipping/Model/Rate/Result.php @@ -132,7 +132,6 @@ public function getCheapestRate() /** * Sort rates by price from min to max * - * @param none * @return Mage_Shipping_Model_Rate_Result */ public function sortRatesByPrice () diff --git a/app/code/core/Mage/Sitemap/Model/Mysql4/Catalog/Product.php b/app/code/core/Mage/Sitemap/Model/Mysql4/Catalog/Product.php index 26d6a0fd0d..a8f2754690 100644 --- a/app/code/core/Mage/Sitemap/Model/Mysql4/Catalog/Product.php +++ b/app/code/core/Mage/Sitemap/Model/Mysql4/Catalog/Product.php @@ -36,18 +36,18 @@ class Mage_Sitemap_Model_Mysql4_Catalog_Product extends Mage_Core_Model_Mysql4_A { /** * Collection Zend Db select - * + * * @var Zend_Db_Select */ protected $_select; - + /** * Attribute cache - * + * * @var array */ protected $_attributesCache = array(); - + /** * Init resource model (catalog/category) */ @@ -55,37 +55,37 @@ protected function _construct() { $this->_init('catalog/product', 'entity_id'); } - + /** * Add attribute to filter - * + * * @param int $storeId * @param string $attributeCode * @param mixed $value * @param string $type - * + * * @return Zend_Db_Select */ protected function _addFilter($storeId, $attributeCode, $value, $type = '=') { if (!isset($this->_attributesCache[$attributeCode])) { $attribute = Mage::getSingleton('catalog/product')->getResource()->getAttribute($attributeCode); - + $this->_attributesCache[$attributeCode] = array( 'entity_type_id' => $attribute->getEntityTypeId(), 'attribute_id' => $attribute->getId(), 'table' => $attribute->getBackend()->getTable(), - 'is_global' => $attribute->getIsGlobal(), + 'is_global' => $attribute->getIsGlobal() == Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL, 'backend_type' => $attribute->getBackendType() ); } - + $attribute = $this->_attributesCache[$attributeCode]; if (!$this->_select instanceof Zend_Db_Select) { - return false; + return false; } - + switch ($type) { case '=': $conditionRule = '=?'; @@ -97,13 +97,13 @@ protected function _addFilter($storeId, $attributeCode, $value, $type = '=') return false; break; } - + if ($attribute['backend_type'] == 'static') { $this->_select->where('e.' . $attributeCode . $conditionRule, $value); } else { if ($attribute['is_global']) { - + } else { $this->_select->join( @@ -120,27 +120,27 @@ protected function _addFilter($storeId, $attributeCode, $value, $type = '=') ->where('IFNULL(t2_'.$attributeCode.'.value, t1_'.$attributeCode.'.value)'.$conditionRule, $value); } } - + return $this->_select; } - - + + /** * Get category collection array - * + * * @return array */ public function getCollection($storeId) { $products = array(); - + $store = Mage::app()->getStore($storeId); /* @var $store Mage_Core_Model_Store */ - + if (!$store) { return false; } - + $urCondions = array( 'e.entity_id=ur.product_id', 'ur.category_id IS NULL', @@ -161,22 +161,22 @@ public function getCollection($storeId) array('url' => 'request_path') ) ; - - $this->_addFilter($storeId, 'visibility', array(2,4), 'in'); - $this->_addFilter($storeId, 'status', 1); - + + $this->_addFilter($storeId, 'visibility', Mage::getSingleton('catalog/product_visibility')->getVisibleInSearchIds(), 'in'); + $this->_addFilter($storeId, 'status', Mage::getSingleton('catalog/product_status')->getVisibleStatusIds(), 'in'); + $query = $this->_getWriteAdapter()->query($this->_select); while ($row = $query->fetch()) { $product = $this->_prepareProduct($row); $products[$product->getId()] = $product; } - + return $products; } - + /** * Prepare product - * + * * @param array $productRow * @return Varien_Object */ diff --git a/app/code/core/Mage/Tag/Model/Mysql4/Tag/Collection.php b/app/code/core/Mage/Tag/Model/Mysql4/Tag/Collection.php index 304ddf61b8..256ec47edc 100644 --- a/app/code/core/Mage/Tag/Model/Mysql4/Tag/Collection.php +++ b/app/code/core/Mage/Tag/Model/Mysql4/Tag/Collection.php @@ -207,6 +207,8 @@ public function addStoreFilter($storeId, $allFilter = true) AND summary_store.store_id IN (' . implode(',', $storeId) . ')', array()); + $this->getSelect()->group('summary_store.tag_id'); + if($this->getJoinFlag('relation') && $allFilter) { $this->getSelect()->where('relation.store_id IN (' . implode(',', $storeId) . ')'); } diff --git a/app/code/core/Mage/Tax/Helper/Data.php b/app/code/core/Mage/Tax/Helper/Data.php index cd15102e64..a37607d1f0 100644 --- a/app/code/core/Mage/Tax/Helper/Data.php +++ b/app/code/core/Mage/Tax/Helper/Data.php @@ -54,22 +54,38 @@ public function getProductPrice($product, $format=null) return $value; } + /** + * Check if product prices inputed include tax + * + * @param mix $store + * @return bool + */ public function priceIncludesTax($store=null) { $storeId = Mage::app()->getStore($store)->getId(); if (!isset($this->_priceIncludesTax[$storeId])) { - $this->_priceIncludesTax[$storeId] = - (int)Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX, $store); + $this->_priceIncludesTax[$storeId] = (int)Mage::getStoreConfig( + Mage_Tax_Model_Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX, + $store + ); } return $this->_priceIncludesTax[$storeId]; } + /** + * Check what taxes should be applied after discount + * + * @param mixed $store + * @return bool + */ public function applyTaxAfterDiscount($store=null) { $storeId = Mage::app()->getStore($store)->getId(); if (!isset($this->_applyTaxAfterDiscount[$storeId])) { - $this->_applyTaxAfterDiscount[$storeId] = - (int)Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, $store); + $this->_applyTaxAfterDiscount[$storeId] = (int)Mage::getStoreConfig( + Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, + $store + ); } return $this->_applyTaxAfterDiscount[$storeId]; } @@ -89,35 +105,37 @@ public function getIncExcText($flag, $store=null) return $s; } -/* - public function updateProductTax($product) - { - $store = Mage::app()->getStore($product->getStoreId()); - $taxRatio = $this->getCatalogTaxRate($product->getTaxClassId(), null, $store); - if (false===$taxRatio) { - return false; - } - $taxRatio /= 100; - $product->setPriceAfterTax($store->roundPrice($product->getPrice()*(1+$taxRatio))); - $product->setFinalPriceAfterTax($store->roundPrice($product->getFinalPrice()*(1+$taxRatio))); - $product->setShowTaxInCatalog(Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_SHOW_IN_CATALOG, $store)); - - return $taxRatio; - } -*/ + /** + * Get product price display tax + * 1 - Excluding tax + * 2 - Including tax + * 3 - Both + * + * @param mixed $store + * @return int + */ public function getPriceDisplayType($store = null) { - $storeId = Mage::app()->getStore($store)->getId(); if (!isset($this->_priceDisplayType[$storeId])) { - $this->_priceDisplayType[$storeId] = - (int)Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_PRICE_DISPLAY_TYPE, $store); + $this->_priceDisplayType[$storeId] = (int)Mage::getStoreConfig( + Mage_Tax_Model_Config::CONFIG_XML_PATH_PRICE_DISPLAY_TYPE, + $store + ); } return $this->_priceDisplayType[$storeId]; } + /** + * Check if necessary do product price conversion + * If it necessary will be returned conversion type (minus or plus) + * + * @param mixed $store + * @return false | int + */ public function needPriceConversion($store = null) { + $res = false; if ($this->priceIncludesTax($store)) { switch ($this->getPriceDisplayType($store)) { case Mage_Tax_Model_Config::DISPLAY_TYPE_EXCLUDING_TAX: @@ -125,49 +143,86 @@ public function needPriceConversion($store = null) return self::PRICE_CONVERSION_MINUS; case Mage_Tax_Model_Config::DISPLAY_TYPE_INCLUDING_TAX: - return false; + $res = false; } } else { switch ($this->getPriceDisplayType($store)) { case Mage_Tax_Model_Config::DISPLAY_TYPE_INCLUDING_TAX: + case Mage_Tax_Model_Config::DISPLAY_TYPE_BOTH: return self::PRICE_CONVERSION_PLUS; - case Mage_Tax_Model_Config::DISPLAY_TYPE_BOTH: case Mage_Tax_Model_Config::DISPLAY_TYPE_EXCLUDING_TAX: - return false; + $res = false; } } - return false; + + if ($res === false) { + $res = $this->displayTaxColumn($store); + } + return $res; } + /** + * Check if need display full tax summary information in totals block + * + * @param mixed $store + * @return bool + */ public function displayFullSummary($store = null) { return ((int)Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_DISPLAY_FULL_SUMMARY, $store) == 1); } + /** + * Check if need display zero tax in subtotal + * + * @param mixed $store + * @return bool + */ public function displayZeroTax($store = null) { - if (is_null($store)) - $store = Mage::app()->getStore(); - - return $store->getConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_DISPLAY_ZERO_TAX); + return Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_DISPLAY_ZERO_TAX, $store); } + /** + * Check if need display cart prices included tax + * + * @param mixed $store + * @return bool + */ public function displayCartPriceInclTax($store = null) { return $this->displayTaxColumn($store) == Mage_Tax_Model_Config::DISPLAY_TYPE_INCLUDING_TAX; } + /** + * Check if need display cart prices excluding price + * + * @param mixed $store + * @return bool + */ public function displayCartPriceExclTax($store = null) { return $this->displayTaxColumn($store) == Mage_Tax_Model_Config::DISPLAY_TYPE_EXCLUDING_TAX; } + /** + * Check if need display cart prices excluding and including tax + * + * @param mixed $store + * @return bool + */ public function displayCartBothPrices($store = null) { return $this->displayTaxColumn($store) == Mage_Tax_Model_Config::DISPLAY_TYPE_BOTH; } + /** + * Check if need display tax column in for shopping cart/order items + * + * @param mixed $store + * @return bool + */ public function displayTaxColumn($store = null) { if (is_null($this->_displayTaxColumn)) { @@ -176,11 +231,26 @@ public function displayTaxColumn($store = null) return $this->_displayTaxColumn; } + /** + * Get prices javascript format json + * + * @param mixed $store + * @return string + */ public function getPriceFormat($store = null) { return Zend_Json::encode(Mage::app()->getLocale()->getJsPriceFormat()); } + /** + * Get all tax rates for all product tax classes + * + * array( + * value_{$productTaxVlassId} => $rate + * ) + * + * @return array + */ public function getTaxRatesByProductClass() { $result = array(); @@ -194,12 +264,29 @@ public function getTaxRatesByProductClass() return Zend_Json::encode($result); } + /** + * Get product price with all tax settings processing + * + * @param Mage_Catalog_Model_Product $product + * @param float $price inputed product price + * @param bool $includingTax return price include tax flag + * @param null|Mage_Customer_Model_Address $shippingAddress + * @param null|Mage_Customer_Model_Address $billingAddress + * @param null|int $ctc customer tax class + * @param mixed $store + * @param bool $priceIncludesTax flag what price parameter contain tax + * @return float + */ public function getPrice($product, $price, $includingTax = null, $shippingAddress = null, $billingAddress = null, $ctc = null, $store = null, $priceIncludesTax = null) { + $store = Mage::app()->getStore($store); + if (!$this->needPriceConversion($store)) { + return $store->roundPrice($price); + } if (is_null($priceIncludesTax)) { - $priceIncludesTax = $this->priceIncludesTax(); + $priceIncludesTax = $this->priceIncludesTax($store); } - $store = Mage::app()->getStore($store); + $percent = $product->getTaxPercent(); $includingPercent = null; diff --git a/app/code/core/Mage/Tax/Model/Calculation.php b/app/code/core/Mage/Tax/Model/Calculation.php index a7ad1616d5..63c5d7641e 100644 --- a/app/code/core/Mage/Tax/Model/Calculation.php +++ b/app/code/core/Mage/Tax/Model/Calculation.php @@ -163,9 +163,9 @@ public function getRateRequest($shippingAddress = null, $billingAddress = null, break; } - if (is_null($customerTaxClass)) { - $customerTaxClass = Mage::getSingleton('customer/session')->getCustomer()->getTaxClassId(); - } elseif ($customerTaxClass === false) { + if (is_null($customerTaxClass) && $session->isLoggedIn()) { + $customerTaxClass = $session->getCustomer()->getTaxClassId(); + } elseif (($customerTaxClass === false) || !$session->isLoggedIn()) { $defaultCustomerGroup = Mage::getStoreConfig('customer/create_account/default_group', $store); $customerTaxClass = Mage::getModel('customer/group')->getTaxClassId($defaultCustomerGroup); } diff --git a/app/code/core/Mage/Tax/Model/Class/Source/Product.php b/app/code/core/Mage/Tax/Model/Class/Source/Product.php index 4ca2fe3887..d0795e4162 100644 --- a/app/code/core/Mage/Tax/Model/Class/Source/Product.php +++ b/app/code/core/Mage/Tax/Model/Class/Source/Product.php @@ -66,4 +66,34 @@ public function toOptionArray() { return $this->getAllOptions(); } + + /** + * Get Column(s) names for flat data building + * + * @return array + */ + public function getFlatColums() + { + $columns = array(); + $columns[$this->getAttribute()->getAttributeCode()] = array( + 'type' => 'int', + 'unsigned' => false, + 'is_null' => true, + 'default' => null, + 'extra' => null + ); + return $columns; + } + + /** + * Retrieve Select for update Attribute value in flat table + * + * @param int $store + * @return Varien_Db_Select|null + */ + public function getFlatUpdateSelect($store) + { + return Mage::getResourceModel('eav/entity_attribute_option') + ->getFlatUpdateSelect($this->getAttribute(), $store, false); + } } \ No newline at end of file diff --git a/app/code/core/Mage/Tax/Model/Observer.php b/app/code/core/Mage/Tax/Model/Observer.php index c451d2890f..e2ffbd1cc5 100644 --- a/app/code/core/Mage/Tax/Model/Observer.php +++ b/app/code/core/Mage/Tax/Model/Observer.php @@ -120,4 +120,36 @@ public function prepareCatalogIndexPriceSelect(Varien_Event_Observer $observer) return $this; } + + /** + * Add tax percent values to product collection items + * + * @param Varien_Event_Observer $observer + * @return Mage_Tax_Model_Observer + */ + public function addTaxPercentToProductCollection($observer) + { + $helper = Mage::helper('tax'); + $collection = $observer->getEvent()->getCollection(); + $store = $collection->getStoreId(); + if (!$helper->needPriceConversion($store)) { + return $this; + } + + if ($collection->requireTaxPercent()) { + $request = Mage::getSingleton('tax/calculation')->getRateRequest(); + foreach ($collection as $item) { + if (null === $item->getTaxClassId()) { + $item->setTaxClassId($item->getMinimalTaxClassId()); + } + if (!isset($classToRate[$item->getTaxClassId()])) { + $request->setProductClassId($item->getTaxClassId()); + $classToRate[$item->getTaxClassId()] = Mage::getSingleton('tax/calculation')->getRate($request); + } + $item->setTaxPercent($classToRate[$item->getTaxClassId()]); + } + + } + return $this; + } } diff --git a/app/code/core/Mage/Tax/etc/config.xml b/app/code/core/Mage/Tax/etc/config.xml index 399202d291..8e867021e3 100644 --- a/app/code/core/Mage/Tax/etc/config.xml +++ b/app/code/core/Mage/Tax/etc/config.xml @@ -100,7 +100,7 @@ - model + singleton tax/observer salesEventConvertQuoteAddressToOrder @@ -109,7 +109,7 @@ - model + singleton tax/observer salesEventOrderAfterSave @@ -118,12 +118,21 @@ - model + singleton tax/observer prepareCatalogIndexPriceSelect + + + + singleton + tax/observer + addTaxPercentToProductCollection + + + diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php index 3ed50a4fce..d812fb12b4 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php @@ -312,7 +312,7 @@ protected function _getXmlQuotes() { $r = $this->_rawRequest; - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('action', 'Request'); $xml->addAttribute('version', '1.1'); @@ -921,7 +921,7 @@ protected function _getXMLTracking($trackings) { $r = $this->_rawTrackRequest; - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('action', 'Request'); $xml->addAttribute('version', '1.1'); diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php index 9ae5f9665b..9bfd44b18b 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php @@ -151,7 +151,7 @@ protected function _setFreeMethodRequest($freeMethod) protected function _getXmlQuotes() { $r = $this->_rawRequest; - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('xmlns:api', 'http://www.fedex.com/fsmapi'); $xml->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); @@ -544,8 +544,7 @@ public function getCode($type, $code='') /** * Return FeDex currency ISO code by Magento Base Currency Code * - * @param none - * @return string 3-digit currency code + * @return string 3-digit currency code */ public function getCurrencyCode () { @@ -600,7 +599,7 @@ protected function _getXMLTracking($tracking) { $r = $this->_rawTrackingRequest; - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $xml->addAttribute('xsi:noNamespaceSchemaLocation', 'FDXTrack2Request.xsd'); @@ -700,6 +699,8 @@ protected function _parseXmlTrackingResponse($trackingvalue,$response) } else { $errorTitle = 'Response is in the wrong format'; } + } else { + $errorTitle = false; } if(!$this->_result){ @@ -760,4 +761,5 @@ public function getAllowedMethods() } return $arr; } + } diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php index c25ef0cdfb..1acf5b80a8 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php @@ -208,7 +208,7 @@ protected function _getCgiQuotes() '14_origCountry' => $r->getOrigCountry(), '15_origPostal' => $r->getOrigPostal(), 'origCity' => $r->getOrigCity(), - '19_destPostal' => $r->getDestPostal(), + '19_destPostal' => substr($r->getDestPostal(), 0, 5), '22_destCountry' => $r->getDestCountry(), '23_weight' => $r->getWeight(), '47_rate_chart' => $r->getPickup(), @@ -509,7 +509,7 @@ protected function _getXmlQuotes() '15_origPostal' => $r->getOrigPostal(), 'origCity' => $r->getOrigCity(), 'origRegionCode' => $r->getOrigRegionCode(), - '19_destPostal' => $r->getDestPostal(), + '19_destPostal' => substr($r->getDestPostal(), 0, 5), '22_destCountry' => $r->getDestCountry(), 'destRegionCode' => $r->getDestRegionCode(), '23_weight' => $r->getWeight(), diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php index 37bdd82570..3ee8bc0aa1 100644 --- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php +++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php @@ -136,7 +136,7 @@ public function setRequest(Mage_Shipping_Model_Rate_Request $request) $weight = $this->getTotalNumOfBoxes($request->getPackageWeight()); $r->setWeightPounds(floor($weight)); - $r->setWeightOunces(($weight-floor($weight))*16); + $r->setWeightOunces(round(($weight-floor($weight))*16, 1)); if ($request->getFreeMethodWeight()!=$request->getPackageWeight()) { $r->setFreeMethodWeight($request->getFreeMethodWeight()); } @@ -165,7 +165,7 @@ protected function _setFreeMethodRequest($freeMethod) $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight()); $r->setWeightPounds(floor($weight)); - $r->setWeightOunces(floor(($weight-floor($weight))*16)); + $r->setWeightOunces(round(($weight-floor($weight))*16, 1)); $r->setService($freeMethod); } @@ -173,7 +173,7 @@ protected function _getXmlQuotes() { $r = $this->_rawRequest; if ($r->getDestCountryId() == self::USA_COUNTRY_ID || $r->getDestCountryId() == self::PUERTORICO_COUNTRY_ID) { - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('USERID', $r->getUserId()); @@ -200,7 +200,7 @@ protected function _getXmlQuotes() $request = $xml->asXML(); } else { - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('USERID', $r->getUserId()); @@ -467,7 +467,7 @@ protected function _getXmlTracking($trackings) $r = $this->_rawTrackRequest; foreach ($trackings as $tracking){ - $xml = new SimpleXMLElement(''); + $xml = new SimpleXMLElement(''); $xml->addAttribute('USERID', $r->getUserId()); diff --git a/app/code/core/Mage/Usa/etc/system.xml b/app/code/core/Mage/Usa/etc/system.xml index 60a855749b..ec0aa10e17 100644 --- a/app/code/core/Mage/Usa/etc/system.xml +++ b/app/code/core/Mage/Usa/etc/system.xml @@ -164,7 +164,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 5 1 @@ -173,7 +173,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 6 1 @@ -191,7 +191,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 8 1 @@ -200,7 +200,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 8 1 @@ -373,7 +373,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 3 1 @@ -559,7 +559,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 3 1 @@ -690,7 +690,7 @@ - password + obscure adminhtml/system_config_backend_encrypted 3 1 @@ -750,7 +750,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 3 1 @@ -953,7 +953,7 @@ - text + obscure adminhtml/system_config_backend_encrypted 3 1 diff --git a/app/code/core/Mage/Weee/Helper/Data.php b/app/code/core/Mage/Weee/Helper/Data.php index e0af07fad8..74004e6115 100644 --- a/app/code/core/Mage/Weee/Helper/Data.php +++ b/app/code/core/Mage/Weee/Helper/Data.php @@ -114,8 +114,12 @@ public function getEmailPriceDisplayType($store = null) return $this->_storeDisplayConfig[$key]; } - public function getAmount($product, $shipping = null, $billing = null, $website = null, $calculateTaxes = false) { - return Mage::getSingleton('weee/tax')->getWeeeAmount($product, $shipping, $billing, $website, $calculateTaxes); + public function getAmount($product, $shipping = null, $billing = null, $website = null, $calculateTaxes = false) + { + if ($this->isEnabled()) { + return Mage::getSingleton('weee/tax')->getWeeeAmount($product, $shipping, $billing, $website, $calculateTaxes); + } + return 0; } public function typeOfDisplay($product, $compareTo = null, $zone = null, $store = null) @@ -212,7 +216,10 @@ public function includeInSubtotal($store = null) public function getProductWeeeAttributesForDisplay($product) { - return $this->getProductWeeeAttributes($product, null, null, null, $this->typeOfDisplay($product, 1)); + if ($this->isEnabled()) { + return $this->getProductWeeeAttributes($product, null, null, null, $this->typeOfDisplay($product, 1)); + } + return array(); } diff --git a/app/code/core/Mage/Weee/Model/Tax.php b/app/code/core/Mage/Weee/Model/Tax.php index 2b1677ef4d..f8c11f80b9 100644 --- a/app/code/core/Mage/Weee/Model/Tax.php +++ b/app/code/core/Mage/Weee/Model/Tax.php @@ -1,160 +1,160 @@ -_init('weee/tax', 'weee/tax'); - } - - public function getWeeeAmount($product, $shipping = null, $billing = null, $website = null, $calculateTax = false, $ignoreDiscount = false) - { - $amount = 0; - $attributes = $this->getProductWeeeAttributes($product, $shipping, $billing, $website, $calculateTax, $ignoreDiscount); - foreach ($attributes as $attribute) { - $amount += $attribute->getAmount(); - } - return $amount; - } - - public function getWeeeAttributeCodes($forceEnabled = false) - { - return $this->getWeeeTaxAttributeCodes($forceEnabled); - } - - public function getWeeeTaxAttributeCodes($forceEnabled = false) - { - if (!$forceEnabled && !Mage::helper('weee')->isEnabled()) { - return array(); - } - - if (is_null($this->_allAttributes)) { - $this->_allAttributes = Mage::getModel('eav/entity_attribute')->getAttributeCodesByFrontendType('weee'); - } - return $this->_allAttributes; - } - - public function getProductWeeeAttributes($product, $shipping = null, $billing = null, $website = null, $calculateTax = null, $ignoreDiscount = false) - { - $result = array(); - $allWeee = $this->getWeeeTaxAttributeCodes(); - if (!$allWeee) { - return $result; - } - - $websiteId = Mage::app()->getWebsite($website)->getId(); - $store = Mage::app()->getWebsite($website)->getDefaultGroup()->getDefaultStore(); - - if ($shipping) { - $customerTaxClass = $shipping->getQuote()->getCustomerTaxClassId(); - } else { - $customerTaxClass = null; - } - - $rateRequest = Mage::getModel('tax/calculation')->getRateRequest($shipping, $billing, $customerTaxClass, $store); - $defaultRateRequest = Mage::getModel('tax/calculation')->getRateRequest(false, false, false, $store); - - $discountPercent = 0; - if (!$ignoreDiscount && Mage::helper('weee')->isDiscounted($store)) { - $discountPercent = $this->_getDiscountPercentForProduct($product); - } - - $productAttributes = $product->getTypeInstance()->getSetAttributes(); - foreach ($productAttributes as $code=>$attribute) { - if (in_array($code, $allWeee)) { - $attributeId = $attribute->getId(); - - $attributeSelect = $this->getResource()->getReadConnection()->select(); - $attributeSelect->from($this->getResource()->getTable('weee/tax'), 'value'); - - $on = array(); - $on[] = "attribute_id = '{$attributeId}'"; - $on[] = "(website_id in ('{$websiteId}', 0))"; - - $country = $rateRequest->getCountryId(); - $on[] = "(country = '{$country}')"; - - $region = $rateRequest->getRegionId(); - $on[] = "(state in ('{$region}', '*'))"; - - foreach ($on as $one) { - $attributeSelect->where($one); - } - $attributeSelect->where('entity_id = ?', $product->getId()); - $attributeSelect->limit(1); - - $order = array('state DESC', 'website_id DESC'); - - $attributeSelect->order($order); - $value = $this->getResource()->getReadConnection()->fetchOne($attributeSelect); - if ($value) { - if ($discountPercent) { - $value = Mage::app()->getStore()->roundPrice($value-($value*$discountPercent/100)); - } - - $taxAmount = $amount = 0; - $amount = $value; - - if ($calculateTax && Mage::helper('weee')->isTaxable($store)) { - $defaultPercent = Mage::getModel('tax/calculation')->getRate($defaultRateRequest->setProductClassId($product->getTaxClassId())); - $currentPercent = $product->getTaxPercent(); - - $taxAmount = Mage::app()->getStore()->roundPrice($value/(100+$defaultPercent)*$currentPercent); - $amount = $value - $taxAmount; - } - - $one = new Varien_Object(); - $one->setName(Mage::helper('catalog')->__($attribute->getFrontend()->getLabel())) - ->setAmount($amount) - ->setTaxAmount($taxAmount) - ->setCode($attribute->getAttributeCode()); - - $result[] = $one; - } - } - } - return $result; - } - - protected function _getDiscountPercentForProduct($product) - { - $website = Mage::app()->getStore()->getWebsiteId(); - $group = Mage::getSingleton('customer/session')->getCustomerGroupId(); - $key = implode('-', array($website, $group, $product->getId())); - if (!isset($this->_productDiscounts[$key])) { - $this->_productDiscounts[$key] = (int) $this->getResource()->getProductDiscountPercent($product->getId(), $website, $group); - } - if ($value = $this->_productDiscounts[$key]) { - return 100-min(100, max(0, $value)); - } else { - return 0; - } - } - - public function updateDiscountPercents() - { - $this->getResource()->updateDiscountPercents(); - return $this; - } -} +_init('weee/tax', 'weee/tax'); + } + + public function getWeeeAmount($product, $shipping = null, $billing = null, $website = null, $calculateTax = false, $ignoreDiscount = false) + { + $amount = 0; + $attributes = $this->getProductWeeeAttributes($product, $shipping, $billing, $website, $calculateTax, $ignoreDiscount); + foreach ($attributes as $attribute) { + $amount += $attribute->getAmount(); + } + return $amount; + } + + public function getWeeeAttributeCodes($forceEnabled = false) + { + return $this->getWeeeTaxAttributeCodes($forceEnabled); + } + + public function getWeeeTaxAttributeCodes($forceEnabled = false) + { + if (!$forceEnabled && !Mage::helper('weee')->isEnabled()) { + return array(); + } + + if (is_null($this->_allAttributes)) { + $this->_allAttributes = Mage::getModel('eav/entity_attribute')->getAttributeCodesByFrontendType('weee'); + } + return $this->_allAttributes; + } + + public function getProductWeeeAttributes($product, $shipping = null, $billing = null, $website = null, $calculateTax = null, $ignoreDiscount = false) + { + $result = array(); + $allWeee = $this->getWeeeTaxAttributeCodes(); + if (!$allWeee) { + return $result; + } + + $websiteId = Mage::app()->getWebsite($website)->getId(); + $store = Mage::app()->getWebsite($website)->getDefaultGroup()->getDefaultStore(); + + if ($shipping) { + $customerTaxClass = $shipping->getQuote()->getCustomerTaxClassId(); + } else { + $customerTaxClass = null; + } + + $rateRequest = Mage::getModel('tax/calculation')->getRateRequest($shipping, $billing, $customerTaxClass, $store); + $defaultRateRequest = Mage::getModel('tax/calculation')->getRateRequest(false, false, false, $store); + + $discountPercent = 0; + if (!$ignoreDiscount && Mage::helper('weee')->isDiscounted($store)) { + $discountPercent = $this->_getDiscountPercentForProduct($product); + } + + $productAttributes = $product->getTypeInstance(true)->getSetAttributes($product); + foreach ($productAttributes as $code=>$attribute) { + if (in_array($code, $allWeee)) { + $attributeId = $attribute->getId(); + + $attributeSelect = $this->getResource()->getReadConnection()->select(); + $attributeSelect->from($this->getResource()->getTable('weee/tax'), 'value'); + + $on = array(); + $on[] = "attribute_id = '{$attributeId}'"; + $on[] = "(website_id in ('{$websiteId}', 0))"; + + $country = $rateRequest->getCountryId(); + $on[] = "(country = '{$country}')"; + + $region = $rateRequest->getRegionId(); + $on[] = "(state in ('{$region}', '*'))"; + + foreach ($on as $one) { + $attributeSelect->where($one); + } + $attributeSelect->where('entity_id = ?', $product->getId()); + $attributeSelect->limit(1); + + $order = array('state DESC', 'website_id DESC'); + + $attributeSelect->order($order); + $value = $this->getResource()->getReadConnection()->fetchOne($attributeSelect); + if ($value) { + if ($discountPercent) { + $value = Mage::app()->getStore()->roundPrice($value-($value*$discountPercent/100)); + } + + $taxAmount = $amount = 0; + $amount = $value; + + if ($calculateTax && Mage::helper('weee')->isTaxable($store)) { + $defaultPercent = Mage::getModel('tax/calculation')->getRate($defaultRateRequest->setProductClassId($product->getTaxClassId())); + $currentPercent = $product->getTaxPercent(); + + $taxAmount = Mage::app()->getStore()->roundPrice($value/(100+$defaultPercent)*$currentPercent); + $amount = $value - $taxAmount; + } + + $one = new Varien_Object(); + $one->setName(Mage::helper('catalog')->__($attribute->getFrontend()->getLabel())) + ->setAmount($amount) + ->setTaxAmount($taxAmount) + ->setCode($attribute->getAttributeCode()); + + $result[] = $one; + } + } + } + return $result; + } + + protected function _getDiscountPercentForProduct($product) + { + $website = Mage::app()->getStore()->getWebsiteId(); + $group = Mage::getSingleton('customer/session')->getCustomerGroupId(); + $key = implode('-', array($website, $group, $product->getId())); + if (!isset($this->_productDiscounts[$key])) { + $this->_productDiscounts[$key] = (int) $this->getResource()->getProductDiscountPercent($product->getId(), $website, $group); + } + if ($value = $this->_productDiscounts[$key]) { + return 100-min(100, max(0, $value)); + } else { + return 0; + } + } + + public function updateDiscountPercents() + { + $this->getResource()->updateDiscountPercents(); + return $this; + } +} diff --git a/app/code/core/Mage/Wishlist/Model/Wishlist.php b/app/code/core/Mage/Wishlist/Model/Wishlist.php index c53f4d0c96..9c87c929ab 100644 --- a/app/code/core/Mage/Wishlist/Model/Wishlist.php +++ b/app/code/core/Mage/Wishlist/Model/Wishlist.php @@ -20,7 +20,7 @@ * * @category Mage * @package Mage_Wishlist - * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) + * @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) */ @@ -30,37 +30,56 @@ * * @category Mage * @package Mage_Wishlist - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Wishlist_Model_Wishlist extends Mage_Core_Model_Abstract { - + /** + * Wishlist item collection + * + * @var Mage_Wishlist_Model_Mysql4_Item_Collection + */ protected $_itemCollection = null; /** - * Enter description here... + * Store filter for wishlist * * @var Mage_Core_Model_Store */ protected $_store = null; + /** + * Shared store ids (website stores) + * + * @var array + */ protected $_storeIds = null; + /** + * Initialize resource model + * + */ protected function _construct() { $this->_init('wishlist/wishlist'); } - public function loadByCustomer($customer, $create=false) + /** + * Load wishlist by customer + * + * @param mixed $customer + * @param bool $create Create wishlist if don't exists + * @return Mage_Wishlist_Model_Wishlist + */ + public function loadByCustomer($customer, $create = false) { if ($customer instanceof Mage_Customer_Model_Customer) { $customer = $customer->getId(); } - $this->_getResource()->load($this, - $customer, - $this->_getResource()->getCustomerIdFieldName()); - if(!$this->getId() && $create) { + $customerIdFieldName = $this->_getResource()->getCustomerIdFieldName(); + $this->_getResource()->load($this, $customer, $customerIdFieldName); + if (!$this->getId() && $create) { $this->setCustomerId($customer); $this->setSharingCode($this->_getSharingRandomCode()); $this->save(); @@ -69,6 +88,12 @@ public function loadByCustomer($customer, $create=false) return $this; } + /** + * Load by sharing code + * + * @param string $code + * @return Mage_Wishlist_Model_Wishlist + */ public function loadByCode($code) { $this->_getResource()->load($this, $code, 'sharing_code'); @@ -78,11 +103,21 @@ public function loadByCode($code) return $this; } + /** + * Retrieve sharing code (random string) + * + * @return string + */ protected function _getSharingRandomCode() { return md5(microtime() . rand()); } + /** + * Retrieve wishlist item collection + * + * @return Mage_Wishlist_Model_Mysql4_Item_Collection + */ public function getItemCollection() { if(is_null($this->_itemCollection)) { @@ -94,6 +129,11 @@ public function getItemCollection() return $this->_itemCollection; } + /** + * Retrieve Product collection + * + * @return Mage_Wishlist_Model_Mysql4_Product_Collection + */ public function getProductCollection() { $collection = $this->getData('product_collection'); @@ -101,42 +141,60 @@ public function getProductCollection() $collection = Mage::getResourceModel('wishlist/product_collection') ->setStoreId($this->getStore()->getId()) ->addWishlistFilter($this) - ->addWishListSortOrder() - ; + ->addWishListSortOrder(); $this->setData('product_collection', $collection); } return $collection; } + /** + * Add new item to wishlist + * + * @param int $productId + * @return Mage_Wishlist_Model_Item + */ public function addNewItem($productId) { $item = Mage::getModel('wishlist/item'); - $item->loadByProductWishlist($this->getId(), $productId, $this->getSharedStoreIds()); - if($item->getId()) { - return $item; + if (!$item->getId()) { + $item->setProductId($productId) + ->setWishlistId($this->getId()) + ->setAddedAt(now()) + ->setStoreId($this->getStore()->getId()) + ->save(); } - $item->setProductId($productId) - ->setWishlistId($this->getId()) - ->setAddedAt(now()) - ->setStoreId($this->getStore()->getId()) - ->save(); - return $item; } + /** + * Set customer id + * + * @param int $customerId + * @return Mage_Wishlist_Model_Wishlist + */ public function setCustomerId($customerId) { return $this->setData($this->_getResource()->getCustomerIdFieldName(), $customerId); } + /** + * Retrieve customer id + * + * @return Mage_Wishlist_Model_Wishlist + */ public function getCustomerId() { return $this->getData($this->_getResource()->getCustomerIdFieldName()); } + /** + * Retrieve data for save + * + * @return array + */ public function getDataForSave() { $data = array(); @@ -147,7 +205,7 @@ public function getDataForSave() } /** - * Enter description here... + * Retrieve shared store ids * * @return array */ @@ -160,7 +218,7 @@ public function getSharedStoreIds() } /** - * Set store ids + * Set shared store ids * * @param array $storeIds * @return Mage_Wishlist_Model_Wishlist @@ -172,7 +230,7 @@ public function setSharedStoreIds($storeIds) } /** - * Enter description here... + * Retrieve wishlist store object * * @return Mage_Core_Model_Store */ @@ -185,7 +243,7 @@ public function getStore() } /** - * Enter description here... + * Set wishlist store * * @param Mage_Core_Model_Store $store * @return Mage_Wishlist_Model_Wishlist @@ -196,11 +254,21 @@ public function setStore($store) return $this; } + /** + * Retrieve wishlist items count + * + * @return int + */ public function getItemsCount() { return $this->_getResource()->fetchItemsCount($this); } + /** + * Retrieve wishlist has salable item(s) + * + * @return bool + */ public function isSalable() { foreach ($this->getProductCollection() as $product) { diff --git a/app/code/core/Mage/Wishlist/controllers/IndexController.php b/app/code/core/Mage/Wishlist/controllers/IndexController.php index 7b7acb9a7c..09ca89f310 100644 --- a/app/code/core/Mage/Wishlist/controllers/IndexController.php +++ b/app/code/core/Mage/Wishlist/controllers/IndexController.php @@ -30,7 +30,7 @@ * * @category Mage * @package Mage_Wishlist - * @author Magento Core Team + * @author Magento Core Team */ class Mage_Wishlist_IndexController extends Mage_Core_Controller_Front_Action { @@ -50,6 +50,11 @@ public function preDispatch() } } + /** + * Retrieve wishlist object + * + * @return Mage_Wishlist_Model_Wishlist + */ protected function _getWishlist() { try { @@ -238,37 +243,42 @@ public function cartAction() /** * Add all items to shoping cart + * */ public function allcartAction() { - $messages = array(); - $urls = array(); - $wishlistIds = array(); + $messages = array(); + $urls = array(); + $wishlistIds = array(); + $notSalableNames = array(); // Out of stock products message - $wishlist = $this->_getWishlist(); + $wishlist = $this->_getWishlist(); $wishlist->getItemCollection()->load(); - $notSalableNames = array(); // Out of stock products message - foreach ($wishlist->getItemCollection() as $item) { - try { - $product = Mage::getModel('catalog/product')->load($item->getProductId())->setQty(1); - if ($product->isSalable()){ + try { + $product = Mage::getModel('catalog/product') + ->load($item->getProductId()) + ->setQty(1); + if ($product->isSalable()) { Mage::getSingleton('checkout/cart')->addProduct($product); $item->delete(); - } else { + } + else { $notSalableNames[] = $product->getName(); } } catch(Exception $e) { - $url = Mage::getSingleton('checkout/session')->getRedirectUrl(true); - if ($url){ - $url = Mage::getModel('core/url')->getUrl('catalog/product/view', array( - 'id'=>$item->getProductId(), - 'wishlist_next'=>1 - )); - - $urls[] = $url; - $messages[] = $e->getMessage(); - $wishlistIds[] = $item->getId(); + $url = Mage::getSingleton('checkout/session') + ->getRedirectUrl(true); + if ($url) { + $url = Mage::getModel('core/url') + ->getUrl('catalog/product/view', array( + 'id' => $item->getProductId(), + 'wishlist_next' => 1 + )); + + $urls[] = $url; + $messages[] = $e->getMessage(); + $wishlistIds[] = $item->getId(); } else { $item->delete(); } @@ -289,7 +299,8 @@ public function allcartAction() { Mage::getSingleton('checkout/session')->setWishlistPendingUrls($urls); Mage::getSingleton('checkout/session')->setWishlistPendingMessages($messages); Mage::getSingleton('checkout/session')->setWishlistIds($wishlistIds); - } else { + } + else { $this->_redirect('checkout/cart'); } } diff --git a/app/design/adminhtml/default/default/layout/admin.xml b/app/design/adminhtml/default/default/layout/admin.xml new file mode 100644 index 0000000000..bcd17ce35e --- /dev/null +++ b/app/design/adminhtml/default/default/layout/admin.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + diff --git a/app/design/adminhtml/default/default/layout/catalog.xml b/app/design/adminhtml/default/default/layout/catalog.xml index aa9b11822c..f07de83348 100644 --- a/app/design/adminhtml/default/default/layout/catalog.xml +++ b/app/design/adminhtml/default/default/layout/catalog.xml @@ -27,6 +27,16 @@ --> + + + + + 0 + + + + + @@ -102,4 +112,14 @@ Layout handle for configurable products + + + + + + + + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/layout/customer.xml b/app/design/adminhtml/default/default/layout/customer.xml new file mode 100644 index 0000000000..cadfcda0db --- /dev/null +++ b/app/design/adminhtml/default/default/layout/customer.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/layout/sales.xml b/app/design/adminhtml/default/default/layout/sales.xml index 707f92771b..931d5ee46b 100644 --- a/app/design/adminhtml/default/default/layout/sales.xml +++ b/app/design/adminhtml/default/default/layout/sales.xml @@ -46,7 +46,33 @@ - + + + + + + + + + subtotal + Subtotal + + + + + + giftcert_amount + Gift Certificate + + + adjustment_positive + Adjustment Refund + + + adjustment_negative + Adjustment Fee + + order_infoorder_tab_info @@ -75,8 +101,37 @@ nameadminhtml/sales_items_column_name_groupedgrouped - - + + + + + + + + + + + + subtotal + Subtotal + + + + + + giftcert_amount + Gift Certificate + + + adjustment_positive + Adjustment Refund + + + adjustment_negative + Adjustment Fee + + + @@ -91,8 +146,35 @@ nameadminhtml/sales_items_column_name_groupedgrouped - - + + + + + + + + + + subtotal + Subtotal + + + + + + giftcert_amount + Gift Certificate + + + adjustment_positive + Adjustment Refund + + + adjustment_negative + Adjustment Fee + + + @@ -118,8 +200,35 @@ invoice - - + + + + + + + + + + subtotal + Subtotal + + + + + + giftcert_amount + Gift Certificate + + + adjustment_positive + Adjustment Refund + + + adjustment_negative + Adjustment Fee + + + @@ -189,8 +298,29 @@ nameadminhtml/sales_items_column_name nameadminhtml/sales_items_column_name_groupedgrouped - - + + + + + Total Refund + + + + + subtotal + Subtotal + + + tax_amount + Tax + + + discount_amount + Discount + + + + @@ -204,8 +334,29 @@ nameadminhtml/sales_items_column_name nameadminhtml/sales_items_column_name_groupedgrouped - - + + + + + Total Refund + + + + + subtotal + Subtotal + + + tax_amount + Tax + + + discount_amount + Discount + + + + @@ -230,8 +381,36 @@ creditmemo - - + + + + + + + + + + + subtotal + Subtotal + + + + + + giftcert_amount + Gift Certificate + + + adjustment_positive + Adjustment Refund + + + adjustment_negative + Adjustment Fee + + + diff --git a/app/design/adminhtml/default/default/template/catalog/category/edit.phtml b/app/design/adminhtml/default/default/template/catalog/category/edit.phtml index fcf710e071..fdb5458926 100644 --- a/app/design/adminhtml/default/default/template/catalog/category/edit.phtml +++ b/app/design/adminhtml/default/default/template/catalog/category/edit.phtml @@ -73,27 +73,29 @@ currentNode.setText(params.node_name); }*/ var categoryContainer = $('category-edit-container'); - new Ajax.Updater( - categoryContainer, - url + (url.match(new RegExp('\\?')) ? '&isAjax=true' : '?isAjax=true' ), - { - parameters: params, - method: 'post', - loaderArea: categoryContainer, - onSuccess: function(transport) { + new Ajax.Request(url + (url.match(new RegExp('\\?')) ? '&isAjax=true' : '?isAjax=true' ), { + parameters: params, + evalScripts: true, + onComplete: refreshTree ? refreshTreeArea.bind(this) : false, + onSuccess: function(transport) { + try { if (transport.responseText.isJSON()) { - var response = transport.responseText.evalJSON(); - if (response.ajaxExpired && response.ajaxRedirect) { - setLocation(response.ajaxRedirect); - return false; - } + var response = transport.responseText.evalJSON() + if (response.error) { + alert(response.message); + } + if(response.ajaxExpired && response.ajaxRedirect) { + setLocation(response.ajaxRedirect); + } + } else { + $(categoryContainer).update(transport.responseText); } - // everything is ok - }, - onComplete: refreshTree ? refreshTreeArea.bind(this) : false, - evalScripts: true + } + catch (e) { + $(categoryContainer).update(transport.responseText); + } } - ); + }); } /** diff --git a/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml b/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml index 8356ceda65..918ead5c98 100644 --- a/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml +++ b/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml @@ -35,6 +35,7 @@ getDeleteButtonHtml() ?> getSaveButtonHtml() ?> + getAdditionalButtonsHtml(); ?> @@ -48,6 +49,7 @@
+
diff --git a/app/design/adminhtml/default/default/template/catalog/category/tree.phtml b/app/design/adminhtml/default/default/template/catalog/category/tree.phtml index 73abd16a17..a7da00986a 100644 --- a/app/design/adminhtml/default/default/template/catalog/category/tree.phtml +++ b/app/design/adminhtml/default/default/template/catalog/category/tree.phtml @@ -32,7 +32,7 @@ getAddSubButtonHtml() ?>
- getStoreSwitcherHtml() ?> + getStoreSwitcherHtml();?>
getRoot()): ?> getCollapseButtonHtml() ?> @@ -71,7 +71,7 @@ Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, { this.storeId = parameters['store_id']; - if ( this.storeId != 0) { + if ( this.storeId != 0 && $('add_root_category_button')) { $('add_root_category_button').hide(); } @@ -259,6 +259,11 @@ function _renderNewTree(config, storeParam) if (storeParam) { url = url + storeParam; } + isClearEdit()):?> + if (selectedNode) { + url = url + 'id/' + config.parameters.category_id; + } + updateContent(url); } diff --git a/app/design/adminhtml/default/default/template/catalog/product.phtml b/app/design/adminhtml/default/default/template/catalog/product.phtml index 1d0efc1f99..ce14859b63 100644 --- a/app/design/adminhtml/default/default/template/catalog/product.phtml +++ b/app/design/adminhtml/default/default/template/catalog/product.phtml @@ -34,7 +34,9 @@
-getStoreSwitcherHtml() ?> +isSingleStoreMode() ): ?> +getChildHtml('store_switcher');?> +
getGridHtml() ?>
\ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/catalog/product/attribute/js.phtml b/app/design/adminhtml/default/default/template/catalog/product/attribute/js.phtml index a5318a4f76..155d8a1fbc 100644 --- a/app/design/adminhtml/default/default/template/catalog/product/attribute/js.phtml +++ b/app/design/adminhtml/default/default/template/catalog/product/attribute/js.phtml @@ -85,6 +85,19 @@ function bindAttributeInputType() } } + if ($('frontend_input') && ($('frontend_input').value=='multiselect' + || $('frontend_input').value=='gallery' + || $('frontend_input').value=='text')) { + if ($('used_for_sort_by')) { + $('used_for_sort_by').disabled = true; + } + } + else { + if ($('used_for_sort_by')) { + $('used_for_sort_by').disabled = false; + } + } + if ($('frontend_input') && ($('frontend_input').value=='text' || $('frontend_input').value=='textarea')) { if($('is_html_allowed_on_front')){ $('is_html_allowed_on_front').disabled = false; diff --git a/app/design/adminhtml/default/default/template/catalog/product/attribute/options.phtml b/app/design/adminhtml/default/default/template/catalog/product/attribute/options.phtml index 47e6c6ae89..7b5d836a70 100644 --- a/app/design/adminhtml/default/default/template/catalog/product/attribute/options.phtml +++ b/app/design/adminhtml/default/default/template/catalog/product/attribute/options.phtml @@ -35,7 +35,7 @@
    • -
    • __('If you do not specify an option value for a store then the default value will be used.') ?>
    • +
    • __('If you do not specify an option value for a specific store view then the default (Admin) value will be used.') ?>
diff --git a/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/date.phtml b/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/date.phtml index 2c273cb78d..9fc7ca8afe 100644 --- a/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/date.phtml +++ b/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/date.phtml @@ -28,14 +28,14 @@ OptionTemplateDate = ''+ ''+ - ''+ + ''+ ''+ - ''+ + ''+ ''+ ''+ ''+ ''+ - ''+ + ''+ ''+ '
__('Price') ?> *__('Price') ?>__('Price Type') ?>__('SKU') ?> *__('SKU') ?>
getPriceTypeSelectHtml() ?>{{checkboxScopePrice}}
'; diff --git a/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/file.phtml b/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/file.phtml index c0f6751f16..73f90697d0 100644 --- a/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/file.phtml +++ b/app/design/adminhtml/default/default/template/catalog/product/edit/options/type/file.phtml @@ -28,18 +28,18 @@ OptionTemplateFile = ''+ ''+ - ''+ + ''+ ''+ - ''+ - ''+ - ''+ + ''+ + ''+ + ''+ ''+ ''+ ''+ ''+ ''+ - ''+ - ''+ + ''+ + ''+ ''+ '
__('Price') ?> *__('Price') ?>__('Price Type') ?>__('SKU') ?> *__('File Extension') ?>__('Image Size') ?>__('SKU') ?>__('Allowed File Extensions') ?>__('Maximum Image Size') ?>
getPriceTypeSelectHtml() ?> __('x') ?> __('px.') ?>
'; diff --git a/app/design/adminhtml/default/default/template/customer/edit/js.phtml b/app/design/adminhtml/default/default/template/customer/edit/js.phtml new file mode 100644 index 0000000000..b1e5d3dae1 --- /dev/null +++ b/app/design/adminhtml/default/default/template/customer/edit/js.phtml @@ -0,0 +1,33 @@ + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/dashboard/index.phtml b/app/design/adminhtml/default/default/template/dashboard/index.phtml index ab38bde59f..3b109558ff 100644 --- a/app/design/adminhtml/default/default/template/dashboard/index.phtml +++ b/app/design/adminhtml/default/default/template/dashboard/index.phtml @@ -54,7 +54,7 @@ function toggleCal(id) {
- getStoreSwitcherHtml() ?> + getChildHtml('store_switcher') ?> '+ ''+ ''+ ''+ '
'+ - ''+ + ''+ + '
'+ + '
'+ + ''+ '
'+ - ''+ ''+ ''+ ''+ ''+ ''+ '
'+ - ''+ + ''+ + '
'+ + '
'+ + ''+ '
'+ - ''+ ''+ ''+ ''+ @@ -185,9 +189,24 @@ var linkItems = { if(!data.link_id){ data = {}; data.link_id = 0; + data.link_type = 'file'; + data.sample_type = 'none'; data.number_of_downloads = 'getConfigMaxDownloads() ?>'; } + data.id = this.itemCount; + + if (data.link_type == 'url') { + data.url_checked = ' checked="checked"'; + } else if (data.link_type == 'file') { + data.file_checked = ' checked="checked"'; + } + if (data.sample_type == 'url') { + data.sample_url_checked = ' checked="checked"'; + } else if (data.sample_type == 'file') { + data.sample_file_checked = ' checked="checked"'; + } + Element.insert(this.tbody, {'bottom':this.template.evaluate(data)}); scopeTitle = $('downloadable_link_'+data.id+'_title'); @@ -281,21 +300,7 @@ var linkItems = { linkUrl.advaiceContainer = 'downloadable_link_'+data.id+'_link_container'; $('downloadable_link_'+data.id+'_file_save').advaiceContainer = 'downloadable_link_'+data.id+'_link_container'; - if (data.link_type == 'url') { - linkUrl.checked = true; - } else if (data.link_type == 'file') { - linkFile.checked = true; - } - sampleFile = $('downloadable_link_'+data.id+'_sample_file_type'); -// sampleFile.advaiceContainer = 'downloadable_link_'+data.id+'_sample_container'; -// sampleUrl.advaiceContainer = 'downloadable_link_'+data.id+'_sample_container'; - - if (data.sample_type == 'url') { - sampleUrl.checked = true; - } else if (data.sample_type == 'file') { - sampleFile.checked = true; - } this.itemCount++; this.togglePriceFields(); diff --git a/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/samples.phtml b/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/samples.phtml index 714836331f..b06a215ca2 100644 --- a/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/samples.phtml +++ b/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/samples.phtml @@ -89,7 +89,7 @@ var sampleTemplate = ''+ ''+ ''+ ''+ '
'+ - ' '+ + ' '+ + '
'+ + '
'+ + ''+ '
'+ - ''+ ''+ + ''+ ''+ ' + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals.phtml b/app/design/adminhtml/default/default/template/sales/order/totals.phtml index b076c5fb5f..026a9e8c92 100644 --- a/app/design/adminhtml/default/default/template/sales/order/totals.phtml +++ b/app/design/adminhtml/default/default/template/sales/order/totals.phtml @@ -24,102 +24,11 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -getSource() ?> -getOrder() ?> +getSource(); ?> setPriceDataObject($_source) ?> -getCurrency() ?>
getChildHtml('sales') ?> diff --git a/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/links.phtml b/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/links.phtml index b1380f8d45..0a8ba29df6 100644 --- a/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/links.phtml +++ b/app/design/adminhtml/default/default/template/downloadable/product/edit/downloadable/links.phtml @@ -126,7 +126,7 @@ var linkTemplate = '
'+ '
'+ '
'+ - ''+ + ''+ ''+ '
'+ '
'+ '
'+ - ''+ + ''+ ''+ '
'+ '
'+ '
'+ - ''+ + ''+ ''+ '
'+ '
'+ @@ -103,10 +103,13 @@ var sampleTemplate = '
'+ @@ -124,9 +127,18 @@ var sampleItems = { if(!data.sample_id){ data = {}; + data.sample_type = 'file'; data.sample_id = 0; } + data.id = this.itemCount; + + if (data.sample_type == 'url') { + data.url_checked = ' checked="checked"'; + } else if (data.sample_type == 'file') { + data.file_checked = ' checked="checked"'; + } + Element.insert(this.tbody, {'bottom':this.template.evaluate(data)}); scopeTitle = $('downloadable_sample_'+data.id+'_title'); @@ -164,12 +176,6 @@ var sampleItems = { sampleFile = $('downloadable_sample_'+data.id+'_file_type'); sampleFile.advaiceContainer = 'downloadable_sample_'+data.id+'_container'; $('downloadable_sample_'+data.id+'_file_save').advaiceContainer = 'downloadable_sample_'+data.id+'_container'; -// $('downloadable_sample_'+data.id+'_file_save').advaiceContainer = 'custom-advice-container'; - if (data.sample_type == 'url') { - sampleUrl.checked = true; - } else if (data.sample_type == 'file') { - sampleFile.checked = true; - } this.itemCount++; this.bindRemoveButtons(); diff --git a/app/design/adminhtml/default/default/template/page/footer.phtml b/app/design/adminhtml/default/default/template/page/footer.phtml index 3e4b214a8b..9387609340 100644 --- a/app/design/adminhtml/default/default/template/page/footer.phtml +++ b/app/design/adminhtml/default/default/template/page/footer.phtml @@ -44,4 +44,4 @@ } } Event.observe('interface_locale', 'change', setInterfaceLanguage) - \ No newline at end of file + diff --git a/app/design/adminhtml/default/default/template/page/header.phtml b/app/design/adminhtml/default/default/template/page/header.phtml index 1755a48df5..342f0274b3 100644 --- a/app/design/adminhtml/default/default/template/page/header.phtml +++ b/app/design/adminhtml/default/default/template/page/header.phtml @@ -48,7 +48,8 @@ paramName:"query", minChars:2, indicator:"global_search_indicator", - updateElement:getSelectionId + updateElement:getSelectionId, + evalJSON:'force' } ); function getSelectionId(li) { diff --git a/app/design/adminhtml/default/default/template/permissions/rolesedit.phtml b/app/design/adminhtml/default/default/template/permissions/rolesedit.phtml index 2f5e23043b..9888979336 100644 --- a/app/design/adminhtml/default/default/template/permissions/rolesedit.phtml +++ b/app/design/adminhtml/default/default/template/permissions/rolesedit.phtml @@ -24,6 +24,15 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> + + + +getChildHtml(); ?> +

__('Roles Resources') ?>

diff --git a/app/design/adminhtml/default/default/template/sales/items/column/name.phtml b/app/design/adminhtml/default/default/template/sales/items/column/name.phtml index 1822c3d51f..0765bbd418 100644 --- a/app/design/adminhtml/default/default/template/sales/items/column/name.phtml +++ b/app/design/adminhtml/default/default/template/sales/items/column/name.phtml @@ -38,14 +38,18 @@ getOrderOptions() as $_option): ?>
- htmlEscape(Mage::helper('core/string')->truncate($_option['value'], 55, '', $_remainder));?> - - ... htmlEscape($_remainder) ?> - + isHtmlFormattedOptionValue($_option['value'])): ?> + + + truncate($_option['value'], 55, '', $_remainder);?> + + ... + +
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml b/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml index 85b633e777..8ed8a12dd3 100644 --- a/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml +++ b/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml @@ -109,8 +109,8 @@ - helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceExclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?> __('Excl. Tax'); ?>: typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> @@ -148,8 +148,8 @@ - helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceInclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?>
__('Incl. Tax'); ?>: helper('checkout')->getPriceInclTax($_item); ?> @@ -206,8 +206,8 @@ - helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceExclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?> __('Excl. Tax'); ?>: typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> @@ -245,8 +245,8 @@ - helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceInclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?>
__('Incl. Tax'); ?>: helper('checkout')->getSubtotalInclTax($_item); ?> @@ -292,8 +292,8 @@
- helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceExclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?> __('Excl. Tax'); ?>: typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> @@ -331,8 +331,8 @@ - helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()): ?> - helper('tax')->displayCartBothPrices()): ?> + helper('tax')->displayCartPriceInclTax($this->getStore()) || $this->helper('tax')->displayCartBothPrices($this->getStore())): ?> + helper('tax')->displayCartBothPrices($this->getStore())): ?>
__('Incl. Tax'); ?>: getRowTotalWithDiscount()+$_item->getTaxAmount(); ?> diff --git a/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals.phtml b/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals.phtml deleted file mode 100644 index 044ab790ec..0000000000 --- a/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals.phtml +++ /dev/null @@ -1,102 +0,0 @@ - -getSource() ?> -setPriceDataObject($_source) ?> -getCurrency() ?> - - - - - - - - - - - - getSubtotal()): ?> - - - - - - - getTaxAmount()): ?> - - - - - - getDiscountAmount()): ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- helper('sales')->__('Total Refund') ?> - - displayPriceAttribute('grand_total', true) ?> -
helper('sales')->__('Subtotal') ?>displayPriceAttribute('subtotal') ?>
helper('sales')->__('Tax') ?>displayPriceAttribute('tax_amount') ?>
helper('sales')->__('Discount') ?>displayPriceAttribute('discount_amount') ?>
helper('sales')->__('Refund Shipping') ?>
helper('sales')->__('Adjustment Refund') ?>
helper('sales')->__('Adjustment Fee') ?>
- - \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals/adjustments.phtml b/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals/adjustments.phtml new file mode 100644 index 0000000000..5090bab2d8 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/creditmemo/create/totals/adjustments.phtml @@ -0,0 +1,67 @@ + +getSource() ?> +setPriceDataObject($_source) ?> +getCurrency() ?> + +
helper('sales')->__('Refund Shipping') ?>
helper('sales')->__('Adjustment Refund') ?>
helper('sales')->__('Adjustment Fee') ?>
- - - - - - getCanDisplayTotalPaid()): ?> - - - - - - getCanDisplayTotalRefunded()): ?> - - - - - - getCanDisplayTotalDue()): ?> - - - - - - - - getSubtotal()): ?> - - - - - - getTaxAmount()): ?> - getChild('order_totals_tax')): ?> - getChildHtml('order_totals_tax'); ?> - - - - - - - - - getShippingAmount() || $_source->getShippingDescription()): ?> - - - - - - getDiscountAmount()): ?> - - - - - - - getGiftcertAmount()): ?> - - - - - - - getAdjustmentPositive()): ?> - - - - - - - getAdjustmentNegative()): ?> - - - - - - + getChildHtml('main'); ?> + getChildHtml('footer'); ?>
- - getGrandTotalTitle()): ?> - getGrandTotalTitle() ?> - - __('Grand Total') ?> - - - displayPriceAttribute('grand_total', true) ?>
__('Total Paid') ?>displayPriceAttribute('total_paid', true) ?> -
__('Total Refunded') ?>displayPriceAttribute('total_refunded', true) ?>
__('Total Due', true) ?>displayPriceAttribute('total_due', true) ?>
__('Subtotal') ?>displayPriceAttribute('subtotal') ?>
__('Tax') ?>displayPriceAttribute('tax_amount') ?>
__('Shipping & Handling') ?>displayPriceAttribute('shipping_amount') ?>
- getCouponCode()): ?> - __('Discount (%s)', $_order->getCouponCode()) ?> - - __('Discount') ?> - - displayPriceAttribute('discount_amount') ?>
__('Gift Certificate') ?>displayPriceAttribute('giftcert_amount') ?>
__('Adjustment Refund') ?>displayPriceAttribute('adjustment_positive') ?>
__('Adjustment Fee') ?>displayPriceAttribute('adjustment_negative') ?>
\ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/discount.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/discount.phtml new file mode 100644 index 0000000000..3774c56151 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/discount.phtml @@ -0,0 +1,42 @@ + +getSource() ?> +getOrder() ?> +setPriceDataObject($_source) ?> + +getDiscountAmount()): ?> + + + getCouponCode()): ?> + __('Discount (%s)', $_order->getCouponCode()) ?> + + __('Discount') ?> + + + displayPriceAttribute('discount_amount') ?> + + diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/due.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/due.phtml new file mode 100644 index 0000000000..7385562e25 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/due.phtml @@ -0,0 +1,32 @@ + +getCanDisplayTotalDue()): ?> + + __('Total Due', true) ?> + displayPriceAttribute('total_due', true) ?> + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/footer.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/footer.phtml new file mode 100644 index 0000000000..0753c08a07 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/footer.phtml @@ -0,0 +1,29 @@ + + + getChildHtml() ?> + diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/grand.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/grand.phtml new file mode 100644 index 0000000000..04a72b39b5 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/grand.phtml @@ -0,0 +1,41 @@ + +getSource() ?> +setPriceDataObject($_source) ?> + + + + + getGrandTotalTitle()): ?> + getGrandTotalTitle() ?> + + __('Grand Total') ?> + + + + displayPriceAttribute('grand_total', true) ?> + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/item.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/item.phtml new file mode 100644 index 0000000000..f47e8f1036 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/item.phtml @@ -0,0 +1,35 @@ + +getSource() ?> +setPriceDataObject($_source) ?> + +getDataUsingMethod($this->getSourceField())): ?> + + __($this->getLabel()) ?> + getHtmlClass() ? ('class="' . $this->getHtmlClass() . '"') : '';?>>displayPriceAttribute($this->getSourceField()) ?> + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/main.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/main.phtml new file mode 100644 index 0000000000..b33c74924f --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/main.phtml @@ -0,0 +1,29 @@ + + + getChildHtml() ?> + diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/paid.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/paid.phtml new file mode 100644 index 0000000000..64f7a48507 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/paid.phtml @@ -0,0 +1,33 @@ + +getCanDisplayTotalPaid()): ?> + + __('Total Paid') ?> + displayPriceAttribute('total_paid', true) ?> + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/refunded.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/refunded.phtml new file mode 100644 index 0000000000..7bd70d6b8d --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/refunded.phtml @@ -0,0 +1,32 @@ + +getCanDisplayTotalRefunded()): ?> + + __('Total Refunded') ?> + displayPriceAttribute('total_refunded', true) ?> + + diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/shipping.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/shipping.phtml new file mode 100644 index 0000000000..2c5d7f1a89 --- /dev/null +++ b/app/design/adminhtml/default/default/template/sales/order/totals/shipping.phtml @@ -0,0 +1,35 @@ + +getSource() ?> +setPriceDataObject($_source) ?> + +getShippingAmount() || $_source->getShippingDescription()): ?> + + __('Shipping & Handling') ?> + displayPriceAttribute('shipping_amount') ?> + + diff --git a/app/design/adminhtml/default/default/template/sales/order/totals/tax.phtml b/app/design/adminhtml/default/default/template/sales/order/totals/tax.phtml index 61343e5493..b9ac9c915c 100644 --- a/app/design/adminhtml/default/default/template/sales/order/totals/tax.phtml +++ b/app/design/adminhtml/default/default/template/sales/order/totals/tax.phtml @@ -1,41 +1,74 @@ -helper('tax')->displayFullSummary()): ?> - - getFullTaxInfo() as $info): ?> - - - - - - + +getSource() ?> +getOrder() ?> +setPriceDataObject($_source) ?> +getCurrency() ?> - - - - (%)
- -
- - - displayAmount($amount, $baseAmount); ?> - - - - +getTaxAmount()): ?> + helper('tax')->displayFullSummary()): ?> + + getFullTaxInfo() as $info): ?> + + + + + + + + + + + (%)
+ +
+ + + displayAmount($amount, $baseAmount); ?> + + + + + - - + -helper('tax')->displayFullSummary()): ?> class="tax-total" onclick="expandDetails(this, '.tax-details')"> - -
- helper('tax')->displayFullSummary()): ?> - __('Total Tax') ?> - - __('Tax') ?> - -
- - - displayAmount($this->getOrder()->getTaxAmount(), $this->getOrder()->getBaseTaxAmount()); ?> - - \ No newline at end of file + helper('tax')->displayFullSummary()): ?> class="tax-total" onclick="expandDetails(this, '.tax-details')"> + +
+ helper('tax')->displayFullSummary()): ?> + __('Total Tax') ?> + + __('Tax') ?> + +
+ + + displayAmount($this->getOrder()->getTaxAmount(), $this->getOrder()->getBaseTaxAmount()); ?> + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/sales/order/view/items/renderer/default.phtml b/app/design/adminhtml/default/default/template/sales/order/view/items/renderer/default.phtml index cbee6c4fe7..96ed37d7c1 100644 --- a/app/design/adminhtml/default/default/template/sales/order/view/items/renderer/default.phtml +++ b/app/design/adminhtml/default/default/template/sales/order/view/items/renderer/default.phtml @@ -80,7 +80,7 @@ helper('tax')->displayCartBothPrices()): ?> __('Excl. Tax'); ?>: - + typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> displayPrices( @@ -91,8 +91,8 @@ displayPrices($_item->getBasePrice(), $_item->getPrice()) ?> - - + + getApplied($_item)): ?>
typeOfDisplay($_item, 1, 'sales')): ?> @@ -112,7 +112,7 @@ - + typeOfDisplay($_item, 2, 'sales')): ?>
__('Total'); ?>:
@@ -135,13 +135,13 @@ helper('checkout')->getPriceInclTax($_item); ?> helper('checkout')->getBasePriceInclTax($_item); ?> - + typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> displayPrices($_baseIncl+$_item->getBaseWeeeTaxAppliedAmount(), $_incl+$_item->getWeeeTaxAppliedAmount()); ?> displayPrices($_baseIncl-$_item->getBaseWeeeTaxDisposition(), $_incl-$_item->getWeeeTaxDisposition()) ?> - + getApplied($_item)): ?>
typeOfDisplay($_item, 1, 'sales')): ?> @@ -161,7 +161,7 @@ - + typeOfDisplay($_item, 2, 'sales')): ?>
__('Total'); ?>:
displayPrices($_baseIncl+$_item->getBaseWeeeTaxAppliedAmount(), $_incl+$_item->getWeeeTaxAppliedAmount()); ?>
@@ -179,7 +179,7 @@ helper('tax')->displayCartBothPrices()): ?> __('Excl. Tax'); ?>: - + typeOfDisplay($_item, array(0, 1, 4), 'sales')): ?> displayPrices( @@ -190,8 +190,8 @@ displayPrices($_item->getBaseRowTotal(), $_item->getRowTotal()) ?> - - + + getApplied($_item)): ?> typeOfDisplay($_item, 1, 'sales')): ?> @@ -210,7 +210,7 @@ - + typeOfDisplay($_item, 2, 'sales')): ?>
__('Total'); ?>:
@@ -238,10 +238,10 @@ displayPrices($_baseIncl-$_item->getBaseWeeeTaxRowDisposition(), $_incl-$_item->getWeeeTaxRowDisposition()) ?> - - + + getApplied($_item)): ?> - +
typeOfDisplay($_item, 1, 'sales')): ?> @@ -260,7 +260,7 @@ - + typeOfDisplay($_item, 2, 'sales')): ?>
__('Total'); ?>:
displayPrices($_baseIncl+$_item->getBaseWeeeTaxAppliedRowAmount(), $_incl+$_item->getWeeeTaxAppliedRowAmount()); ?>
diff --git a/app/design/adminhtml/default/default/template/system/config/switcher.phtml b/app/design/adminhtml/default/default/template/system/config/switcher.phtml new file mode 100644 index 0000000000..02e0c7e5d6 --- /dev/null +++ b/app/design/adminhtml/default/default/template/system/config/switcher.phtml @@ -0,0 +1,21 @@ +
+ + +

+ __('Manage Stores') ?> +

+
\ No newline at end of file diff --git a/app/design/adminhtml/default/default/template/system/config/tabs.phtml b/app/design/adminhtml/default/default/template/system/config/tabs.phtml index a598e9e104..ee7ec086e0 100644 --- a/app/design/adminhtml/default/default/template/system/config/tabs.phtml +++ b/app/design/adminhtml/default/default/template/system/config/tabs.phtml @@ -24,28 +24,6 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ ?> -
- - -

- __('Manage Stores') ?> -

-
- getTitle()): ?>

getTitle() ?>

diff --git a/app/design/adminhtml/default/default/template/urlrewrite/selector.phtml b/app/design/adminhtml/default/default/template/urlrewrite/selector.phtml index 752921bf64..8788513267 100644 --- a/app/design/adminhtml/default/default/template/urlrewrite/selector.phtml +++ b/app/design/adminhtml/default/default/template/urlrewrite/selector.phtml @@ -37,7 +37,7 @@ getSelectorLabel() ?> - + getUrl('*/*/*')?> getItems() as $_item): ?> - +
diff --git a/app/design/adminhtml/default/default/template/widget/tabshoriz.phtml b/app/design/adminhtml/default/default/template/widget/tabshoriz.phtml index c113d5177a..78e1aa887b 100644 --- a/app/design/adminhtml/default/default/template/widget/tabshoriz.phtml +++ b/app/design/adminhtml/default/default/template/widget/tabshoriz.phtml @@ -31,10 +31,10 @@ diff --git a/app/design/frontend/default/default/layout/catalog.xml b/app/design/frontend/default/default/layout/catalog.xml index 4cf45e2abf..66289b5979 100644 --- a/app/design/frontend/default/default/layout/catalog.xml +++ b/app/design/frontend/default/default/layout/catalog.xml @@ -51,7 +51,7 @@ Default layout, loads most of the pages images/media/col_left_callout.jpg - Our customer service is available 24/7. Call us at (800) DEMO-NUMBER. + Our customer service is available 24/7. Call us at (555) 555-0123. checkout/cart @@ -175,7 +175,6 @@ Product view js_csscalendar/calendar-win2k-1.css jscalendar/calendar.js - jscalendar/lang/calendar-en.js jscalendar/calendar-setup.js @@ -208,6 +207,7 @@ Product view selectcatalog/product_view_options_type_select datecatalog/product_view_options_type_date + product.tierprices @@ -330,6 +330,20 @@ SEO Site Map + + + + + + + + + seo.sitemap.tree.pager.top + seo.sitemap.tree.pager.bottom + + + + diff --git a/app/design/frontend/default/default/layout/catalogsearch.xml b/app/design/frontend/default/default/layout/catalogsearch.xml index befca23648..1ce0774bc9 100644 --- a/app/design/frontend/default/default/layout/catalogsearch.xml +++ b/app/design/frontend/default/default/layout/catalogsearch.xml @@ -78,11 +78,11 @@ js_csscalendar/calendar-win2k-1.css jscalendar/calendar.js - jscalendar/lang/calendar-en.js jscalendar/calendar-setup.js + diff --git a/app/design/frontend/default/default/template/catalog/navigation/left.phtml b/app/design/frontend/default/default/template/catalog/navigation/left.phtml index d160b89cc2..8a0611ba0b 100644 --- a/app/design/frontend/default/default/template/catalog/navigation/left.phtml +++ b/app/design/frontend/default/default/template/catalog/navigation/left.phtml @@ -33,7 +33,8 @@ */ ?> getCurrentChildCategories() ?> -count()): ?> +count(); ?> +

__('Browse By') ?>

diff --git a/app/design/frontend/default/default/template/catalog/product/compare/sidebar.phtml b/app/design/frontend/default/default/template/catalog/product/compare/sidebar.phtml index edc0c51d86..be1e6a69fd 100644 --- a/app/design/frontend/default/default/template/catalog/product/compare/sidebar.phtml +++ b/app/design/frontend/default/default/template/catalog/product/compare/sidebar.phtml @@ -45,7 +45,7 @@
__('Clear All') ?> - +

__('You have no items to compare.') ?>

diff --git a/app/design/frontend/default/default/template/catalog/product/list.phtml b/app/design/frontend/default/default/template/catalog/product/list.phtml index aa4b10c1ff..91cfb7951d 100644 --- a/app/design/frontend/default/default/template/catalog/product/list.phtml +++ b/app/design/frontend/default/default/template/catalog/product/list.phtml @@ -104,7 +104,7 @@ getPriceHtml($_product, true) ?> isSaleable()): ?> - +
__('Out of stock') ?>
diff --git a/app/design/frontend/default/default/template/catalog/product/new.phtml b/app/design/frontend/default/default/template/catalog/product/new.phtml index b1c305e3f9..de2151654c 100644 --- a/app/design/frontend/default/default/template/catalog/product/new.phtml +++ b/app/design/frontend/default/default/template/catalog/product/new.phtml @@ -41,7 +41,7 @@ getReviewsSummaryHtml($_product, 'short') ?> getPriceHtml($_product, true, '-new') ?> isSaleable()): ?> - +
__('Out of stock') ?>
diff --git a/app/design/frontend/default/default/template/catalog/product/view.phtml b/app/design/frontend/default/default/template/catalog/product/view.phtml index 180d1daff1..2d994a6d4a 100644 --- a/app/design/frontend/default/default/template/catalog/product/view.phtml +++ b/app/design/frontend/default/default/template/catalog/product/view.phtml @@ -33,7 +33,7 @@ ?> helper('catalog/output'); - $_product = $this->getProduct() + $_product = $this->getProduct(); ?> + + diff --git a/app/design/frontend/default/default/template/catalog/product/view/options/type/default.phtml b/app/design/frontend/default/default/template/catalog/product/view/options/type/default.phtml index 714dcf05d1..209edeb7f2 100644 --- a/app/design/frontend/default/default/template/catalog/product/view/options/type/default.phtml +++ b/app/design/frontend/default/default/template/catalog/product/view/options/type/default.phtml @@ -1,2 +1,28 @@ + getOption() ?> -
\ No newline at end of file +
diff --git a/app/design/frontend/default/default/template/catalog/product/view/options/type/file.phtml b/app/design/frontend/default/default/template/catalog/product/view/options/type/file.phtml index 45a4515943..a1b4219377 100644 --- a/app/design/frontend/default/default/template/catalog/product/view/options/type/file.phtml +++ b/app/design/frontend/default/default/template/catalog/product/view/options/type/file.phtml @@ -26,14 +26,16 @@ ?> getOption() ?>
- ( - getPriceType() == 'fixed'): ?> - helper('core')->currency($_option->getPrice()) ?> - - getPrice(), 0, null, '') ?> - - )
-decoratedIsLast){?> class="last"> - - - \ No newline at end of file + getFormatedPrice() ?> +decoratedIsLast){?> class="last"> + +getFileExtension()): ?> +

__('Allowed file extensions to upload')?>: getFileExtension() ?>

+ +getImageSizeX() > 0): ?> +

__('Maximum image width')?>: getImageSizeX() ?> __('px.')?>

+ +getImageSizeY() > 0): ?> +

__('Maximum image height')?>: getImageSizeY() ?> __('px.')?>

+ + diff --git a/app/design/frontend/default/default/template/catalog/seo/tree.phtml b/app/design/frontend/default/default/template/catalog/seo/tree.phtml new file mode 100644 index 0000000000..417f10f2a6 --- /dev/null +++ b/app/design/frontend/default/default/template/catalog/seo/tree.phtml @@ -0,0 +1,43 @@ + + +getCollection(); ?> +getSize()): ?> +
    + +
  • getLevel($_item)?'style="padding-left:' . $this->getLevel($_item, 2) . '0px;"':'' ?>>name ?>
  • + +
+ +

+ __('There are no %s available.', $this->getItemsTitle()); ?> +

+ diff --git a/app/design/frontend/default/default/template/checkout/cart/shipping.phtml b/app/design/frontend/default/default/template/checkout/cart/shipping.phtml index 9aadbaba6f..da9c80a3e2 100644 --- a/app/design/frontend/default/default/template/checkout/cart/shipping.phtml +++ b/app/design/frontend/default/default/template/checkout/cart/shipping.phtml @@ -12,6 +12,12 @@ * 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_default * @package Mage * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) diff --git a/app/design/frontend/default/default/template/checkout/multishipping/address/select.phtml b/app/design/frontend/default/default/template/checkout/multishipping/address/select.phtml index 2991d3e1c9..ea1c740898 100644 --- a/app/design/frontend/default/default/template/checkout/multishipping/address/select.phtml +++ b/app/design/frontend/default/default/template/checkout/multishipping/address/select.phtml @@ -26,7 +26,7 @@ ?>

__('Change Billing Address') ?>

- +
getMessagesBlock()->getGroupedHtml() ?>
@@ -36,7 +36,7 @@ +

-

diff --git a/app/design/frontend/default/default/template/checkout/multishipping/success.phtml b/app/design/frontend/default/default/template/checkout/multishipping/success.phtml index fc72f92e74..0a0c477fc3 100644 --- a/app/design/frontend/default/default/template/checkout/multishipping/success.phtml +++ b/app/design/frontend/default/default/template/checkout/multishipping/success.phtml @@ -44,5 +44,5 @@ getChildHtml() ?>
- +
diff --git a/app/design/frontend/default/default/template/checkout/onepage/billing.phtml b/app/design/frontend/default/default/template/checkout/onepage/billing.phtml index 50275a4d34..f2686b241d 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/billing.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/billing.phtml @@ -120,7 +120,7 @@

__('* Required Fields') ?>

- + diff --git a/app/design/frontend/default/default/template/checkout/onepage/login.phtml b/app/design/frontend/default/default/template/checkout/onepage/login.phtml index ccfb0f25fa..219b1bbc69 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/login.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/login.phtml @@ -95,7 +95,7 @@

__('* Required Fields') ?>

__('Forgot your password?') ?> - +
diff --git a/app/design/frontend/default/default/template/checkout/onepage/payment.phtml b/app/design/frontend/default/default/template/checkout/onepage/payment.phtml index 20e36702ab..8b41bd0498 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/payment.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/payment.phtml @@ -42,7 +42,7 @@ var payment = new Payment('co-payment-form', 'getUrl('checkout

__('* Required Fields') ?>

__('Back') ?> - + diff --git a/app/design/frontend/default/default/template/checkout/onepage/review/totals.phtml b/app/design/frontend/default/default/template/checkout/onepage/review/totals.phtml index af036bbb93..6e54e27138 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/review/totals.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/review/totals.phtml @@ -1,3 +1,29 @@ + getTotals()): ?> helper('tax')->displayCartBothPrices() ? 5 : 3; ?> diff --git a/app/design/frontend/default/default/template/checkout/onepage/shipping.phtml b/app/design/frontend/default/default/template/checkout/onepage/shipping.phtml index 469c15bc3a..263a1500e1 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/shipping.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/shipping.phtml @@ -87,7 +87,7 @@

__('* Required Fields') ?>

__('Back') ?> - + diff --git a/app/design/frontend/default/default/template/checkout/onepage/shipping_method.phtml b/app/design/frontend/default/default/template/checkout/onepage/shipping_method.phtml index 52d553d488..794a49b30a 100644 --- a/app/design/frontend/default/default/template/checkout/onepage/shipping_method.phtml +++ b/app/design/frontend/default/default/template/checkout/onepage/shipping_method.phtml @@ -41,7 +41,7 @@
__('Back') ?> - + diff --git a/app/design/frontend/default/default/template/checkout/success.phtml b/app/design/frontend/default/default/template/checkout/success.phtml index c1b1e651f8..d422811f59 100644 --- a/app/design/frontend/default/default/template/checkout/success.phtml +++ b/app/design/frontend/default/default/template/checkout/success.phtml @@ -44,5 +44,5 @@ getChildHtml() ?>

- +
\ No newline at end of file diff --git a/app/design/frontend/default/default/template/checkout/total/default.phtml b/app/design/frontend/default/default/template/checkout/total/default.phtml index b2f66604d6..695e9a620c 100644 --- a/app/design/frontend/default/default/template/checkout/total/default.phtml +++ b/app/design/frontend/default/default/template/checkout/total/default.phtml @@ -1,4 +1,29 @@ - + getRenderingArea() == $this->getTotal()->getArea()): ?> diff --git a/app/design/frontend/default/default/template/checkout/total/tax.phtml b/app/design/frontend/default/default/template/checkout/total/tax.phtml index b3f9e8d585..f190939c64 100644 --- a/app/design/frontend/default/default/template/checkout/total/tax.phtml +++ b/app/design/frontend/default/default/template/checkout/total/tax.phtml @@ -1,3 +1,29 @@ + +
diff --git a/app/design/frontend/default/default/template/page/js/calendar.phtml b/app/design/frontend/default/default/template/page/js/calendar.phtml new file mode 100644 index 0000000000..ebc0fe3517 --- /dev/null +++ b/app/design/frontend/default/default/template/page/js/calendar.phtml @@ -0,0 +1,94 @@ + + + + diff --git a/app/design/frontend/default/default/template/rating/empty.phtml b/app/design/frontend/default/default/template/rating/empty.phtml index fd9cf54cc2..6eb3e27711 100644 --- a/app/design/frontend/default/default/template/rating/empty.phtml +++ b/app/design/frontend/default/default/template/rating/empty.phtml @@ -1 +1,27 @@ +

__('Be the first to review this product') ?>

\ No newline at end of file diff --git a/app/design/frontend/default/default/template/reports/home_product_compared.phtml b/app/design/frontend/default/default/template/reports/home_product_compared.phtml index c62b87741b..0ecd06df9e 100644 --- a/app/design/frontend/default/default/template/reports/home_product_compared.phtml +++ b/app/design/frontend/default/default/template/reports/home_product_compared.phtml @@ -42,7 +42,7 @@ getReviewsSummaryHtml($_product, 'short') ?> getPriceHtml($_product, true, '-home-compared') ?> isSaleable()): ?> - +
__('Out of stock') ?>
diff --git a/app/design/frontend/default/default/template/reports/home_product_viewed.phtml b/app/design/frontend/default/default/template/reports/home_product_viewed.phtml index 7064f9d0ca..d1bcc1a5d0 100644 --- a/app/design/frontend/default/default/template/reports/home_product_viewed.phtml +++ b/app/design/frontend/default/default/template/reports/home_product_viewed.phtml @@ -48,7 +48,7 @@ getReviewsSummaryHtml($_product, 'short') ?> getPriceHtml($_product, true, '-home-viewed') ?> isSaleable()): ?> - +
__('Out of stock') ?>
diff --git a/app/design/frontend/default/default/template/tag/customer/edit.phtml b/app/design/frontend/default/default/template/tag/customer/edit.phtml index fc39c586a9..c692070e0d 100644 --- a/app/design/frontend/default/default/template/tag/customer/edit.phtml +++ b/app/design/frontend/default/default/template/tag/customer/edit.phtml @@ -41,7 +41,7 @@
« __('Back to view Tag') ?> - +