├── .gitignore ├── .travis.yml ├── .travis └── composer.json ├── README.md ├── Vagrantfile ├── composer.json ├── modman └── src └── app ├── code └── community │ └── Hackathon │ └── CustomUrls │ ├── Controller │ └── Router.php │ ├── Helper │ └── Data.php │ ├── Model │ ├── Observer.php │ ├── System │ │ └── Config │ │ │ └── Clone │ │ │ └── Customurl.php │ └── Url.php │ ├── Test │ ├── Config │ │ └── Main.php │ ├── Controller │ │ └── Router.php │ ├── Model │ │ ├── Observer.php │ │ ├── System │ │ │ └── Config │ │ │ │ └── Clone │ │ │ │ ├── Customurl.php │ │ │ │ └── _data │ │ │ │ └── fx-config.yaml │ │ └── Url.php │ └── _data │ │ └── fx-config.yaml │ └── etc │ ├── config.xml │ └── system.xml └── etc └── modules └── Hackathon_CustomUrls.xml /.gitignore: -------------------------------------------------------------------------------- 1 | magento 2 | .idea 3 | .vagrant 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.3 4 | - 5.4 5 | env: 6 | - MAGE=1.7.0.2 7 | - MAGE=1.6.2.0 8 | - MAGE=1.5.1.0 9 | before_script: 10 | # Fixing Magento hackathon installer 11 | - mkdir -p tests/magento 12 | # Copying travis composer.json to test only module 13 | - cp -f .travis/composer.json composer.json 14 | # Installing required composer packages 15 | - composer update --dev 16 | # Installing magento version with prepared DB dump 17 | - bin/mage-ci install tests/magento $MAGE magento -c -t -r http://mage-ci.ecomdev.org 18 | # Installing Custom Urls module 19 | - bin/mage-ci install-module tests/magento $(pwd) 20 | # Installing EcomDev_PHPUnit module 21 | - git clone https://github.com/EcomDev/EcomDev_PHPUnit.git -b dev ./phpunit/ 22 | - bin/mage-ci install-module tests/magento "$(pwd)/phpunit/" 23 | # Configuring EcomDev_PHPUnit module 24 | - CURRENT_DIR=$(pwd) 25 | - cd tests/magento/shell 26 | - php ecomdev-phpunit.php -a magento-config --db-name magento --same-db 1 --base_url http://test.magento.com/ 27 | - cd $CURRENT_DIR 28 | script: 29 | - bin/mage-ci phpunit tests/magento --colors --coverage-text 30 | -------------------------------------------------------------------------------- /.travis/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "ecomdev/mage-ci": "*" 4 | }, 5 | "config": { 6 | "bin-dir": "bin" 7 | }, 8 | "extra":{ 9 | "magento-root-dir": "tests/magento" 10 | } 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hackathon_CustomUrls 2 | ========================== 3 | 4 | [![Build Status](https://travis-ci.org/magento-hackathon/Hackathon_CustomUrls.png?branch=develop)](https://travis-ci.org/magento-hackathon/Hackathon_CustomUrls) 5 | 6 | Facts 7 | ----- 8 | - version: In development 9 | - extension key: Hackathon_CustomUrls 10 | - [extension on GitHub](https://github.com/IvanChepurnyi/Hackathon_CustomUrls) 11 | 12 | Description 13 | ----------- 14 | This module allows you to make Magento routes like checkout/cart, customer/account, etc with your custom urls: mycart, myaccount. 15 | 16 | Compatibility 17 | ------------- 18 | - Magento >= 1.5 19 | 20 | Support 21 | ------- 22 | If you have any issues with this extension, open an issue on [GitHub](https://github.com/IvanChepurnyi/Hackathon_CustomUrls/issues). 23 | 24 | Contribution 25 | ------------ 26 | Any contribution is highly appreciated. The best way to contribute code is to open a [pull request on GitHub](https://help.github.com/articles/using-pull-requests). 27 | 28 | Developers 29 | ---------- 30 | - Ivan Chepurnyi - [@IvanChepurnyi](https://github.com/IvanChepurnyi) 31 | - Marco De Bortoli - [@MarcoDeBortoli](https://github.com/MarcoDeBortoli) 32 | - Drew Hunter - [@drewhunter](https://github.com/drewhunter) 33 | - Sarunas Valaskevicius - [@svalaskevicius](https://github.com/svalaskevicius) 34 | 35 | Licence 36 | ------- 37 | [OSL - Open Software Licence 3.0](http://opensource.org/licenses/osl-3.0.php) 38 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.nfs.map_uid = 0 3 | config.nfs.map_gid = 0 4 | config.ssh.forward_agent = true 5 | config.hostmanager.enabled = true 6 | config.hostmanager.manage_host = true 7 | config.hostmanager.ignore_private_ip = false 8 | config.hostmanager.include_offline = true 9 | 10 | config.vm.define :dev do |dev_config| 11 | dev_config.vm.hostname = "magento-1-7" 12 | dev_config.vm.box = "precise32" 13 | dev_config.vm.network :private_network, ip: "10.11.12.14" 14 | dev_config.vm.synced_folder ".", "/vagrant", :nfs => true 15 | 16 | dev_config.vm.provider :virtualbox do |vb| 17 | vb.customize ["modifyvm", :id, "--memory", "2048", "--cpus", "4"] 18 | end 19 | 20 | dev_config.hostmanager.aliases = %w(magento.dev www.magento.dev) 21 | end 22 | 23 | 24 | end 25 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hackathon/custom_urls", 3 | "license": "OSL-3.0", 4 | "type": "magento-module", 5 | "description": "Custom Urls for system routes in Magento", 6 | "require": { 7 | "magento-hackathon/magento-composer-installer": "*" 8 | }, 9 | "require-dev": { 10 | "ecomdev/mage-ci": "dev-master", 11 | "phpunit/phpunit": "3.7.*" 12 | }, 13 | "authors":[ 14 | { 15 | "name":"Ivan Chepurnyi" 16 | }, 17 | { 18 | "name":"Marco De Bortoli" 19 | }, 20 | { 21 | "name":"Drew Hunter" 22 | }, 23 | { 24 | "name":"Sarunas Valaskevicius" 25 | } 26 | ], 27 | "extra": { 28 | "magento-root-dir": "tests/magento" 29 | } 30 | } -------------------------------------------------------------------------------- /modman: -------------------------------------------------------------------------------- 1 | src/app/code/community/Hackathon/CustomUrls app/code/community/Hackathon/CustomUrls 2 | src/app/etc/modules/Hackathon_CustomUrls.xml app/etc/modules/Hackathon_CustomUrls.xml 3 | -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Controller/Router.php: -------------------------------------------------------------------------------- 1 | getAvailableRoutes(); 12 | 13 | $pathInfo = $request->getPathInfo(); 14 | 15 | foreach ($availableRoutes as $availableRoute) { 16 | 17 | $frontName = $this->getUserDefinedRouteFrontName($availableRoute); 18 | 19 | if ($frontName && $frontName == trim($pathInfo, '/')) { 20 | 21 | $routePath = explode('/', (string) $availableRoute->route); 22 | 23 | if (!empty($routePath)) { 24 | list($routeName, $controllerName, $actionName) = array_merge( 25 | $routePath, array('index', 'index') 26 | ); 27 | 28 | $moduleName = $this->getFrontNameByRoute($routeName); 29 | 30 | $request->setModuleName($moduleName) 31 | ->setControllerName($controllerName) 32 | ->setActionName($actionName); 33 | 34 | $this->setRouteParameters($request, $availableRoute); 35 | 36 | $request->setAlias( 37 | Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, 38 | $pathInfo 39 | ); 40 | 41 | return true; 42 | } 43 | } 44 | } 45 | 46 | return false; 47 | } 48 | 49 | protected function getAvailableRoutes() 50 | { 51 | return Mage::getConfig()->getNode(self::XML_PATH_ROUTES)->children(); 52 | } 53 | 54 | protected function getUserDefinedRouteFrontName($route) 55 | { 56 | return Mage::getStoreConfig(sprintf(self::XML_PATH_FRONT_NAME, $route->getName())); 57 | } 58 | 59 | protected function setRouteParameters($request, $route) 60 | { 61 | if (isset($route->params) && $route->params->hasChildren()) { 62 | $request->setParams($route->params->asArray(true)); 63 | } 64 | } 65 | 66 | public function getFrontNameByRoute($routeName) 67 | { 68 | $frontNameInConfig = (string) Mage::getConfig()->getNode( 69 | sprintf(self::XML_PATH_FRONT_NAME_FOR_ROUTE, $routeName) 70 | ); 71 | 72 | if ($frontNameInConfig) { 73 | return $frontNameInConfig; 74 | } 75 | 76 | return parent::getFrontNameByRoute($routeName); 77 | } 78 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Helper/Data.php: -------------------------------------------------------------------------------- 1 | getFront(); 12 | $frontController->addRouter( 13 | 'customurls', 14 | new Hackathon_CustomUrls_Controller_Router() 15 | ); 16 | } 17 | 18 | public function handleGetUrl(Varien_Event_Observer $observer) 19 | { 20 | $params = $observer->getParams(); 21 | 22 | $availableRoutes = $this->getAvailableRoutes(); 23 | $routeToMatch = trim($params->routePath, '/'); 24 | 25 | if (substr_count($routeToMatch, '/') === 1) { 26 | $routeToMatch .= '/index'; 27 | } 28 | 29 | foreach ($availableRoutes as $availableRoute) { 30 | if ((string)$availableRoute->route == $routeToMatch) { 31 | if (isset($availableRoute->params)) { 32 | $hasChild = false; 33 | foreach ($availableRoute->params->children() as $param) { 34 | $hasChild = true; 35 | if (!isset($params->routeParams[$param->getName()]) 36 | || $params->routeParams[$param->getName()] != (string)$param) { 37 | continue 2; 38 | } 39 | } 40 | 41 | if (!$hasChild && $params->routeParams) { 42 | continue; 43 | } 44 | } 45 | 46 | $params->routePath = null; 47 | $params->routeParams = array('_direct' => $this->getUserDefinedRouteFrontName($availableRoute)); 48 | break; 49 | } 50 | } 51 | } 52 | 53 | protected function getAvailableRoutes() 54 | { 55 | return Mage::getConfig()->getNode(self::XML_PATH_ROUTES)->children(); 56 | } 57 | 58 | protected function getUserDefinedRouteFrontName($route) 59 | { 60 | return Mage::getStoreConfig(sprintf(self::XML_PATH_FRONT_NAME, $route->getName())); 61 | } 62 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Model/System/Config/Clone/Customurl.php: -------------------------------------------------------------------------------- 1 | getConfiguredUrlNodes() as $name => $node) { 14 | $prefixes[] = array( 15 | 'field' => $name.'_', 16 | 'label' => (string)$node->label 17 | ); 18 | } 19 | 20 | return $prefixes; 21 | } 22 | 23 | protected function getConfiguredUrlNodes() 24 | { 25 | return Mage::getConfig()->getNode('global/custom_urls')->children(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Model/Url.php: -------------------------------------------------------------------------------- 1 | routePath = $routePath; 16 | $paramsProxy->routeParams = $routeParams; 17 | 18 | Mage::dispatchEvent('hackathon_customurls_url_get_url', array( 19 | 'params' => $paramsProxy 20 | )); 21 | 22 | $routePath = $paramsProxy->routePath; 23 | $routeParams = $paramsProxy->routeParams; 24 | 25 | return parent::getUrl($routePath, $routeParams); 26 | } 27 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Config/Main.php: -------------------------------------------------------------------------------- 1 | assertModelAlias('hackathon_customurls/observer', 'Hackathon_CustomUrls_Model_Observer'); 11 | } 12 | 13 | /** 14 | * @test 15 | */ 16 | public function itProperlyResolvesTheModelAliasForConfigCloneCustomurl() 17 | { 18 | $this->assertModelAlias('hackathon_customurls/system_config_clone_customurl', 'Hackathon_CustomUrls_Model_System_Config_Clone_Customurl'); 19 | } 20 | 21 | /** 22 | * @test 23 | */ 24 | public function itDefinesTheRequiredCustomObserver() 25 | { 26 | $this->assertEventObserverDefined( 27 | 'global', 28 | 'controller_front_init_routers', 29 | 'hackathon_customurls/observer', 30 | 'handleInitRouters' 31 | ); 32 | } 33 | 34 | /** 35 | * @test 36 | */ 37 | public function itOverridesCoreUrlModel() 38 | { 39 | $this->assertModelAlias( 40 | 'core/url', 41 | 'Hackathon_CustomUrls_Model_Url' 42 | ); 43 | } 44 | 45 | /** 46 | * @test 47 | */ 48 | public function itObservesGetUrlEvent() 49 | { 50 | $this->assertEventObserverDefined( 51 | 'frontend', 52 | 'hackathon_customurls_url_get_url', 53 | 'hackathon_customurls/observer', 54 | 'handleGetUrl' 55 | ); 56 | } 57 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Controller/Router.php: -------------------------------------------------------------------------------- 1 | dispatch(null, array('_direct' => 'mycart/')); 12 | $this->assertRequestRoute('checkout/cart/index'); 13 | } 14 | 15 | function testItShouldResolveCustomCheckoutCartUrlParams() 16 | { 17 | $this->dispatch(null, array('_direct' => 'mycartwithparams/')); 18 | $this->assertRequestRoute('checkout/cart/index'); 19 | $this->assertEquals('some_value', $this->getRequest()->getParam('my_awesome_param')); 20 | } 21 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Model/Observer.php: -------------------------------------------------------------------------------- 1 | model = Mage::getModel('hackathon_customurls/observer'); 15 | } 16 | 17 | 18 | public function testItShouldAddANewRouterOnEventDispatch() 19 | { 20 | $frontController = new Mage_Core_Controller_Varien_Front(); 21 | $event = new Varien_Event(array('front' => $frontController)); 22 | $observer = new Varien_Event_Observer(); 23 | $observer->setEvent($event); 24 | $observer->setFront($frontController); 25 | 26 | $this->model->handleInitRouters($observer); 27 | 28 | $actualRouters = $frontController->getRouters(); 29 | 30 | $this->assertInstanceOf('Hackathon_CustomUrls_Controller_Router', current($actualRouters)); 31 | } 32 | 33 | protected function _getObserverForHandingGetUrlCall($routePath = null, $routeParams = null) 34 | { 35 | $params = new stdClass(); 36 | $params->routePath = $routePath; 37 | $params->routeParams = $routeParams; 38 | 39 | $event = new Varien_Event(array('params' => $params)); 40 | $observer = new Varien_Event_Observer(); 41 | $observer->setEvent($event); 42 | $observer->setParams($params); 43 | 44 | return $observer; 45 | } 46 | 47 | public function testItReplacesUrlByRoutePath() 48 | { 49 | $observer = $this->_getObserverForHandingGetUrlCall('checkout/cart'); 50 | 51 | $this->model->handleGetUrl($observer); 52 | 53 | $actualParams = $observer->getParams(); 54 | 55 | $this->assertNull($actualParams->routePath); 56 | $this->assertEquals(array('_direct' => 'mycart'), $actualParams->routeParams); 57 | } 58 | 59 | public function testItReplacesUrlByRoutePathWithSlash() 60 | { 61 | $observer = $this->_getObserverForHandingGetUrlCall('checkout/cart/index'); 62 | 63 | $this->model->handleGetUrl($observer); 64 | 65 | $actualParams = $observer->getParams(); 66 | 67 | $this->assertNull($actualParams->routePath); 68 | $this->assertEquals(array('_direct' => 'mycart'), $actualParams->routeParams); 69 | } 70 | 71 | public function testItDoesNotReplaceUrlByRoutePathThatIsNotOverridden() 72 | { 73 | $observer = $this->_getObserverForHandingGetUrlCall('cms/page'); 74 | 75 | $this->model->handleGetUrl($observer); 76 | 77 | $actualParams = $observer->getParams(); 78 | 79 | $this->assertEquals('cms/page', $actualParams->routePath); 80 | $this->assertNull($actualParams->routeParams); 81 | } 82 | 83 | public function testItDoesNotReplaceUrlByRoutePathWithParams() 84 | { 85 | $observer = $this->_getObserverForHandingGetUrlCall( 86 | 'checkout/cart/index', 87 | array('my_awesome_param' => 'some_value') 88 | ); 89 | 90 | $this->model->handleGetUrl($observer); 91 | 92 | $actualParams = $observer->getParams(); 93 | 94 | $this->assertNull($actualParams->routePath); 95 | $this->assertEquals(array('_direct' => 'mycartwithparams'), $actualParams->routeParams); 96 | } 97 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Model/System/Config/Clone/Customurl.php: -------------------------------------------------------------------------------- 1 | assertEquals( 14 | array( 15 | array( 16 | 'field' => 'checkout_cart_index_', 17 | 'label' => 'Checkout Cart Url' 18 | ), 19 | ), 20 | $model->getPrefixes() 21 | ); 22 | } 23 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Model/System/Config/Clone/_data/fx-config.yaml: -------------------------------------------------------------------------------- 1 | config_xml: 2 | global/custom_urls: --- | 3 | 4 | 5 | checkout/cart/index 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/Model/Url.php: -------------------------------------------------------------------------------- 1 | model = Mage::getModel('core/url'); 12 | $this->mockSession('core/session'); 13 | $this->app()->addEventArea('frontend'); 14 | } 15 | 16 | public function testItDispatchesEventOnGetUrlCall() 17 | { 18 | $this->model->getUrl('checkout/cart'); 19 | $this->assertEventDispatched('hackathon_customurls_url_get_url'); 20 | } 21 | 22 | public function testItReplacesUrlByRoutePath() 23 | { 24 | $actualUrl = $this->model->getUrl('checkout/cart'); 25 | $expectedUrl = $this->model->getUrl(null, array('_direct' => 'mycart')); 26 | 27 | $this->assertEquals($expectedUrl, $actualUrl); 28 | } 29 | 30 | public function testItReplacesUrlByRoutePathWithSlash() 31 | { 32 | $actualUrl = $this->model->getUrl('checkout/cart/index'); 33 | $expectedUrl = $this->model->getUrl(null, array('_direct' => 'mycart')); 34 | 35 | $this->assertEquals($expectedUrl, $actualUrl); 36 | } 37 | 38 | protected function tearDown() 39 | { 40 | $this->app()->removeEventArea('frontend'); 41 | } 42 | } -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/Test/_data/fx-config.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | default/web/custom_urls/checkout_cart_index_url: mycart 3 | default/web/custom_urls/checkout_cart_index_with_params_url: mycartwithparams 4 | config_xml: 5 | global/custom_urls: --- | 6 | 7 | 8 | checkout/cart/index 9 | 10 | 11 | 12 | checkout/cart/index 13 | 14 | 15 | some_value 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hackathon_CustomUrls_Model 6 | 7 | 8 | 9 | Hackathon_CustomUrls_Model_Url 10 | 11 | 12 | 13 | 14 | 15 | Hackathon_CustomUrls_Helper 16 | 17 | 18 | 19 | 20 | 21 | 22 | hackathon_customurls/observer 23 | handleInitRouters 24 | 25 | 26 | 27 | 28 | 29 | 30 | checkout/cart/index 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | hackathon_customurls/observer 44 | handleGetUrl 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | mycart 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/app/code/community/Hackathon/CustomUrls/etc/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 9 | hackathon_customurls/system_config_clone_customurl 10 | 300 11 | 1 12 | 1 13 | 1 14 | 15 | 16 | 17 | text 18 | 1 19 | 1 20 | 1 21 | 1 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/app/etc/modules/Hackathon_CustomUrls.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | community 6 | 7 | 8 | --------------------------------------------------------------------------------