├── .gitignore ├── LICENSE ├── README.md ├── magento-1 ├── .gitignore ├── 0_intro.markdown ├── 1_building_layouts_programatically.markdown ├── 2_page_layout.markdown ├── 3_package_layout.markdown ├── 4_bringing_it_together.markdown ├── 5_advanced_layout_features.markdown ├── 6_cms_page.markdown ├── 7_widgets.markdown ├── LICENSE ├── No_Frills_Magento_Layout.tex ├── README.md ├── a_appendix_blocks.markdown ├── b_appendix_class_alias.markdown ├── bin │ ├── build-html.bash │ ├── build-latex.bash │ ├── build-sample.bash │ ├── build.bash │ ├── chapters_to_html.php │ ├── chapters_to_tex.php │ ├── chapters_to_tex_sample.php │ ├── cleanup.php │ ├── code_from_chapters.php │ ├── color_code.php │ ├── combine_html_chapters.php │ ├── editing-regex.txt │ ├── files.php │ ├── finalize.php │ ├── finalize_sample.php │ ├── hyphenate.php │ ├── markdown.php │ ├── remove_code.php │ ├── search.php │ ├── ss.php │ ├── to_shell.php │ └── xmlverbatim.xsl ├── c_appendix_creating_modules.markdown ├── code │ ├── 1.4.2 │ │ ├── No_Frills_Magento_Layout_1_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_1_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_2_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_2_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_3_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_3_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_5_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_5_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_7_end-1.0.0.tgz │ │ └── No_Frills_Magento_Layout_7_start-1.0.0.tgz │ └── 1.5 or higher │ │ ├── No_Frills_Magento_Layout_1_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_1_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_2_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_2_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_3_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_3_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_5_end-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_5_start-1.0.0.tgz │ │ ├── No_Frills_Magento_Layout_7_end-1.0.0.tgz │ │ └── No_Frills_Magento_Layout_7_start-1.0.0.tgz ├── cover.html ├── d_block_action_reference.html ├── d_block_action_reference.markdown ├── e_theme_and_layout_resolution.markdown ├── f_appendix_clearing_cache.markdown ├── g_appendix_setters_and_getters.markdown ├── h_widget_field_rendering_options.markdown ├── i_system_config.markdown ├── images │ ├── appendix_f │ │ └── cache-manage.png │ ├── appendix_g │ │ └── field.png │ ├── chapter1 │ │ ├── helloworld.png │ │ ├── nofirst.png │ │ ├── start.png │ │ └── twocities.png │ ├── chapter2 │ │ ├── after.png │ │ ├── before.png │ │ ├── complex.png │ │ └── with-content.png │ ├── chapter3 │ │ ├── blank-theme.png │ │ ├── blank-with-handles.png │ │ └── config-package.png │ ├── chapter4 │ │ ├── package-layout-files.png │ │ ├── page-layout.gif │ │ └── page-layout.png │ ├── chapter5 │ │ ├── order-base.png │ │ └── order-before-two.png │ ├── chapter6 │ │ ├── cms-page.png │ │ ├── page-info.png │ │ └── page1.png │ └── chapter7 │ │ ├── instance-displayon.png │ │ ├── instance-pageselected.png │ │ ├── instance-set-data.png │ │ ├── instance-step1.png │ │ ├── instance-step2-always.png │ │ ├── invalidated.png │ │ ├── show-hide.png │ │ ├── widget-window-with-data.png │ │ ├── widget-window.png │ │ └── with-template.png ├── j_magento_connect.markdown ├── nofrills.latex ├── subs.php ├── test.php ├── texput.log └── var │ ├── guide.html │ ├── h.js │ ├── shell.html │ └── shell.tex └── magento-2 ├── .gitignore ├── LICENSE ├── README.md ├── build.php ├── nofrills.latex └── src ├── .DS_Store ├── _url_writing.md ├── appendix-areas.md ├── appendix-autoload.md ├── appendix-cache.md ├── appendix-cli.md ├── appendix-components.md ├── appendix-curl.md ├── appendix-di.md ├── appendix-frontend-build.md ├── appendix-install-module.md ├── appendix-interfaces.md ├── appendix-magento-modes.md ├── appendix-unix-find.md ├── appendix-view-source.md ├── chapter-0-introduction.md ├── chapter-1-blocks-template-php.md ├── chapter-10-knockout-scopes.md ├── chapter-2-layout-xml.md ├── chapter-3-layouthandles.md ├── chapter-4-page-layout.md ├── chapter-5-themes.md ├── chapter-6-advanced-xml-loading.md ├── chapter-7-frontend-css.md ├── chapter-8-frontend-javascript.md └── chapter-9-frontend-advanced-topics.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ALL RIGHTS RESERVED Copyright © Pulse Storm LLC and Alana Storm -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # magento-layout-no-frills 2 | 3 | Repo for No Frills Magento Layout Copyright © Pulse Storm LLC and Alana Storm 4 | 5 | ## Next Steps 6 | 7 | Here's where this repo is headed over the next `[regional time period]`. If you're feeling excited about taking something on just say hello first to make sure the change would be welcome, and then have at it. 8 | 9 | Also, pull requests to fix grammar, typos, or technical content will _always_ be engaged with. 10 | 11 | - [ ] Get Source for both Magento 1 and Magento 2 No Frills Magento Layout uploaded to repo and building with manual build steps 12 | - [ ] Magento 2: Are there Modules to include? 13 | - [ ] Automate the build via docker, github actions, etc. 14 | - [ ] Reconsider pandoc + LaTeX as the build system -- is there a better way to make an ebook in 20xx? 15 | - [ ] Make a grammar/typo pass using more modern tools/checkers 16 | 17 | 18 | -------------------------------------------------------------------------------- /magento-1/.gitignore: -------------------------------------------------------------------------------- 1 | _nofrills_layout_pandoc 2 | deliverable -------------------------------------------------------------------------------- /magento-1/0_intro.markdown: -------------------------------------------------------------------------------- 1 | No Frills Magento Layout: Introduction 2 | ================================================== 3 | 4 | If you're reading this intro, chances are you know something about Magento. Maybe you've chosen it for your new online store, maybe it's been chosen for you, or maybe you're just the curious type. Whatever the reason you've kicked the tires, liked what you've seen, and ran to this book for help once you opened the hood. 5 | 6 | Magento isn't **just** a shopping cart. It's an entire system for programming web applications and performing system integrations. The PHP you see here is not your your father's PHP. It's probably not even your PHP. Magento takes enterprise java patterns and applies them to the PHP language. More than any system available today, it's pushing the limits of what's possible with object oriented PHP code. 7 | 8 | When it comes to layout engines, Most PHP MVC systems use a simple outer-shell/inner-include approach. Magento does not. At the top of the Magento view layer there's a layout object, which controls a tree of nested block objects. Magento uses a domain specific programming language, implemented in XML, to create, configure, and render this nested tree of block objects into HTML. This layer is separate from the rest of the application, allowing non-PHP developers an unprecedented level of power to change their layouts without having to touch a single line of PHP code. 9 | 10 | If the above paragraph was greek to you don't worry, you're not alone. With all that power available there's a learning curve to Magento that can be hard to climb by yourself. This book is your guide up that learning curve. We'll tell you what you need to know to quickly become a Magento Layout master. 11 | 12 | 13 | Who this Book is For 14 | -------------------------------------------------- 15 | This book is for interactive developers and software engineers who want to fully understand Magento's XML based Layout system. 16 | 17 | By interactive developer we mean someone who both designs online experiences, and **implements** them using a mix of HTML/CSS/Javascript and some glue/template programming in a dynamic language like PHP, Ruby, Python, or one of those language's many template systems. There are parts of the book where we'll dive in depth into how a particular system is built, but only so that you can better understand the context of where and when to use it. Designer-coders are quickly taking over the agency world, and this book seeks to give them the tools they need to succeed. 18 | 19 | Software engineer always seemed a fancier title than most jobs entail, so substitute software developer, or even PHP developer, if you're uncomfortable with engineer. Chances are if you work for a shop that does more than just crank out web stores you're going to be asked to extend, enhance, and generally abuse Magento, including the Layout system. In teaching you the practical, this book will also teach and inform on the engineering assumptions of the Layout system. After reading through this book you'll not only understand how to use the Layout system, you'll understand why it was built the way it was, which in turn will help you make better engineering decisions on your own project. 20 | 21 | This book assumes some basic PHP and Magento knowledge. If you haven't already done so, reviewing the Magento Knowledge Base, as well as the additional articles on the author's website will help you get where you need to with Magento. 22 | 23 | > http://www.magentocommerce.com/knowledge-base 24 | > http://alanastorm.com/category/magento 25 | 26 | You don't need to be a Magento master, but you should be passably familiar with the application. If you aren't, you will be by the time you're done! While the main text of the Book is focused on the Layout and related systems, whenever a deeper knowledge of Magento is needed the Appendixes will give you the overview you need to keep working. 27 | 28 | No Frills 29 | -------------------------------------------------- 30 | Why No Frills? Because we tell you what you need to know, and nothing more. Mandated book lengths make sense in a physical retail environment, but with the internet being the preferred way of distributing technical prose, there's no need to pad things out. 31 | 32 | With that in mind, lets get started! 33 | 34 | Installing Modules 35 | -------------------------------------------------- 36 | This book was distributed with an archive containing several versions of a Magento module named Nofrills\_Booklayout. If you want to add code to a Magento system, you create a module. The Nofrills\_Booklayout module is where the example code in this book will go. You'll be building this module up as you go along. For each chapter in the book, we've included the module as it should be at the start of the chapter, and how it should be at the end. 37 | 38 | You'll also find a copy of each and every code example in the code/all folder. If you don't want to manually type in code examples from the book, copy and paste the contents of these files into your source code editor. 39 | 40 | There are two ways to install the module. The first is manually. If you extract the files, you'll see a folder structure like 41 | 42 | app/code/local/Nofrills_Magento 43 | app/module/etc/Nofrills_Magento.xml 44 | app/..... 45 | 46 | The archive structure mirrors where the files should be placed in your system. This is the standard layout of a Magento extension. Place the files in the same location on your own installation, clear your cache, and the extension will be loaded into the system on the next page request. For more background, read the Magento Controller Dispatch and Hello World article online 47 | 48 | > http://alanastorm.com/magento\_controller\_hello\_world 49 | 50 | If you're not up for a manual install, each archive is also a fully valid Magento Connect package. Magento Connect is Magento Inc's online marketplace of free extensions. It's also a package management system. For background on Magento Connect and instructions for installing its packages, please see Appendix J. 51 | 52 | Parting Words 53 | -------------------------------------------------- 54 | A few last things before we start. Magento has a special operating mode called DEVELOPER\_MODE. When running in DEVELOPER\_MODE Magento is less tolerant of small coding errors, and will not hide fatal errors and uncaught exceptions from the end user. You'd never want to run a production store in DEVELOPER\_MODE, but it can make working with and learning the system much easier. You'll want to turn DEVELOPER\_MODE on while working your way through this book. You can do this by either 55 | 56 | 1. Adding SetEnv MAGE\_IS\_DEVELOPER_MODE 1 to your .htaccess file 57 | 58 | 2. Alternately, editing index.php 59 | 60 | If you choose the second option, look for lines in your index.php file something like 61 | 62 | if (isset($_SERVER['MAGE_IS_DEVELOPER_MODE'])) { 63 | Mage::setIsDeveloperMode(true); 64 | } 65 | 66 | You'll want to make sure the Mage::setIsDeveloperMode(true); call is made. Also, while you're in index.php, it'd be a good idea to tell PHP to show errors by changing this 67 | 68 | #ini_set('display_errors', 1); 69 | 70 | to this 71 | 72 | ini_set('display_errors', 1); 73 | 74 | Seemingly invisible errors are one of the most frusting things for a developer new to any system. By configuring Magento to fail fast we'll be setting ourselves up to better learn what needs to be done for any given task. 75 | 76 | Magento's a fast changing platform, and while the concepts in this book will apply to all versions the specifics may change as Magento Inc changes its focus. It should go without saying you should run the exercises presented here on a development or testing server, and **not** your production environment. The following legal notice is the fancy way of saying that 77 | 78 | THIS BOOK AND SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 79 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 80 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 81 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 82 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 83 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 84 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 85 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 86 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 87 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 88 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 89 | THE USE OF THIS BOOK AND SOFTWARE, EVEN IF ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | Bugs in the Book 93 | -------------------------------------------------- 94 | If you're having trouble working your way through the examples, post a detailed question to the programming Q&A site Stack Overflow 95 | 96 | > http://stackoverflow.com/tags/magento 97 | 98 | with the following tags 99 | 100 | magento magento-nofrills 101 | 102 | We'll be monitoring the site for any problems with code examples, and by asking your questions in a public forum you'll be helping the global Magento developer community. Developers are often amazed when they find people across the world are having the same problems they are, and often already have a solution ready to share. 103 | 104 | Additionally, each chapter will contain a link to a site online for discussions specific to each chapter. You're not just getting a book, you're joining a community. 105 | 106 | 107 | About the Author 108 | -------------------------------------------------- 109 | No Frills Magento Layout was written by Alana Storm. Alana's an industry veteran with over 12 years on-the-job experience, and an active member of the Magento community. He's written the go-to developer documentation for the Magento Knowledge Base, and is the author of the popular debugging extension Commerce Bug. You can read more about Alana and her Magento products at the following URLs 110 | 111 | > http://alanastorm.com/ 112 | > http://store.pulsestorm.net/ 113 | 114 | Let's Go 115 | -------------------------------------------------- 116 | That's it for pleasantries, let's get started. In the first chapter we're going to start by creating Magento layouts using PHP code. 117 | 118 | *Visit http://www.pulsestorm.net/nofrills-layout-introduction to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/4_bringing_it_together.markdown: -------------------------------------------------------------------------------- 1 | Bringing it All Together 2 | ================================================== 3 | We've just spent the last three chapters reviewing some complicated concepts and **the interaction** of complicated concepts. We're going to pause for a moment to review what we've learned, as well as provide an overall picture of how Magento builds a Page Layout. Original drafts had this brief, mini-chapter at the start of the book, but it made people's head explode. Hopefully it's safe enough to cover now 4 | 5 | 6 | How a Magento Layout is Built 7 | -------------------------------------------------- 8 | Somewhere in a controller action, the programmer creating the controller action method tells Magento that it's time to load the layout. The end result of loading a layout is a Page Layout XML tree, (see *Figure 4.1*) 9 | 10 | 11 | 12 | To load a Page Layout, Magento will pick and choose Layout Update XML fragments from a repository of Layout Update XML fragments. This repository of Layout Update XML fragments is known as the Package Layout. The Package Layout is loaded from disk by combining several XML files into a single tree, (see *Figure 4.2*) 13 | 14 | 15 | 16 | Users of the Magento system can add to the Package Layout by 17 | 18 | 1. Creating and editing a local.xml file 19 | 2. Adding a custom XML file to the Layout via a module's config.xml file 20 | 3. Least desirably, but most commonly, editing or replacing existing Package Layout files in their their theme's layout 21 | 22 | The Package Layout organizes its many Layout Update XML fragments by handle. During a normal page request life cycle, various parts of the Magento system will tell the Layout Update Manager that, when the time comes, Layout Update XML fragments from "handle x" should be loaded. When the Controller Action developer tells Magento to load the layout, the Layout Update Manager checks this list, and asks the Package Layout for a copy of the Layout Update XML fragments contained within those particular handles. 23 | 24 | Also, each fetched Layout Update XML fragment is processed at this time for an <update handle="..."/> node. This node can be used to tell the manager to fetch **additional nodes** based on the specified handle. 25 | 26 | Finally, a copy of all Layout Update XML fragments in hand, the Layout Update Manager combines them into a single XML tree. This is the Page Layout. 27 | 28 | 29 | What is the Page Layout 30 | -------------------------------------------------- 31 | The Page Layout is a list of instruction for Magento. Programmer types may call it a meta-programing language, or a domain-specific language. Regardless of what you call, the last step of **loading** a Layout is for Magento to use the Page Layout to create and instantiate a nested tree of block objects. These are PHP Objects, each one ultimately responsible for rendering a chunk of HTML. 32 | 33 | That's the layout loaded. The controller action programer may, at this point, choose to manipulate the layout object further. This may include adding, removing, or setting properties on blocks. The Magento Admin Console application does this regularly. The Magento frontend (cart) application tends not to do this. Irrespective of how, after loading a Layout and fiddling with it if they wish, the controller action developer then tells Magento it's time to render the layout object 34 | 35 | Rendering a Layout 36 | -------------------------------------------------- 37 | During the creation of Page Layout, certain Layout Update XML fragments marked certain blocks as "output blocks". When we say certain blocks, this is almost always a single block, and equally almost always this is the block named root. This root block renders a page template. This template, in turn, includes calls to render child blocks. Some of these child blocks render via a template file, others are core/text\_list blocks which automatically render all their children. Others render via pure PHP in the \_toHtml method. This blocks rendering sub-blocks, rending sub-sub-blocks can continue many layers deep. 38 | 39 | The end result of this rendering is a single string variable containing all the HTML from the cascading render. The string is then passed into a Magento response object, which is responsible for outputting the HTML page. 40 | 41 | That, in a nutshell, is the Layout system. 42 | 43 | *Visit http://www.pulsestorm.net/nofrills-layout-chapter-four to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/LICENSE: -------------------------------------------------------------------------------- 1 | ALL RIGHTS RESERVED Copyright © Pulse Storm LLC and Alana Storm -------------------------------------------------------------------------------- /magento-1/README.md: -------------------------------------------------------------------------------- 1 | # No Frills Magento 1 Layout 2 | 3 | Build is currently a manual process. You'll need 4 | 5 | - PHP 6 | 7 | - A LaTeX with `pdflatex` 8 | 9 | installed. To run the build invoke the following command 10 | 11 | % ./bin/build.bash 12 | 13 | Build will drop files in 14 | 15 | ./deliverable/nofrills_layout 16 | 17 | Build PDF with 18 | 19 | pdflatex deliverable/nofrills_layout/No_Frills_Magento_Layout.tex 20 | -------------------------------------------------------------------------------- /magento-1/b_appendix_class_alias.markdown: -------------------------------------------------------------------------------- 1 | Class Aliases 2 | ================================================== 3 | Magento uses a factory pattern for instantiating certain objects. Don't let the design patterny name scare you though, it's not that complicated. 4 | 5 | In raw PHP, if you wanted to instantiate an object from a class, you'd say something like 6 | 7 | $customer = new Product(); 8 | 9 | There's nothing in Magento stopping you from doing this. However, most of the Magento core code and its various sub-systems do things a little differently. 10 | 11 | In Magento, when you want to instantiate an object from a class, you use code like this 12 | 13 | $customer = Mage::getModel('catalog/product'); 14 | 15 | This is calling a static method on the Mage class named getModel. This method will examine Magento's configuration, and ask 16 | 17 | > What model class does the string catalog/product associate with. 18 | 19 | Magento will answer back "Mage\_Catalog\_Model\_Product", and then a "Mage\_Catalog\_Model\_Product" will be instantiated. This catalog/product string is known as the class alias. 20 | 21 | Magento uses this instantiation method for 22 | 23 | 1. Block classes: $layout->createBlock('foo/bar') 24 | 2. Helper classes: Mage::helper('foo/bar') 25 | 3. Model classes: Mage::getModel('foo/bar'),Mage::getModel('foo/bar') 26 | 27 | The createBlock, helper, and getModel methods are all factories. They make objects or a particular type. 28 | 29 | Why so Complicated? 30 | -------------------------------------------------- 31 | This may seem like a lot of misdirection for something as simple as a class declaration, but that misdirection brings some benefits along for the ride. It helps create a type system around classes, Magento itself knows what classes have or have not been declared at any one time, the shorthand saves some verbosity in typing, and it helps enable one of Magento's unique PHP feature, class rewrites (similar to duck-typing or monkey-patching in the Ruby and Python communities) 32 | 33 | What Class? 34 | -------------------------------------------------- 35 | This is all well and good, but can sometimes leave you wondering what class alias corresponds to what class definition. The easiest thing to do is use the free, online demo of Commerce Bug 36 | 37 | http://commercebugdemo.pulsestorm.net/ 38 | 39 | The class URI lookup tab will let you lookup which class aliases correspond to which PHP classes for a core system. 40 | 41 | The way Magento actually looks up class definitions is via its configuration system. All the config.xml files in a Magento install are merged into one, large, global config. This giant tree contains a top level <global/> node that looks something like this 42 | 43 | 44 | 45 | ... 46 | ... 47 | ... 48 | 49 | 50 | 51 | The first thing Magento does when you use a class alias to instantiate a class is determine the context (model, helper, block), and then look in an appropriate node (<models>, <helpers>, and <blocks>). 52 | 53 | Next, each of the <models>, <helpers>, and <blocks> contains a number of "group" nodes 54 | 55 | 56 | ... 57 | ... 58 | ... 59 | 60 | 61 | If you look at a class alias 62 | 63 | catalog/product 64 | 65 | The portion to the left of the / is the group name. Magento will use this to determine which of the group nodes it should look in next. 66 | 67 | Finally, each group node contains, at minimum, a class node <class> 68 | 69 | 70 | 71 | Mage_Catalog_Model 72 | 73 | 74 | 75 | This node contains the **base** PHP class name for the model (or helper, or block) group. This base name in place, the non-group portion of the class alias is appended to the base class name, with the first letter of each underscored word uppercased 76 | 77 | catalog/product 78 | Mage_Catalog_Model_Product 79 | 80 | catalog/product_review 81 | Mage_Catalog_Model_Product_Review 82 | 83 | That's how Magento resolves which PHP class to use for a class alias. 84 | 85 | Class Rewrites 86 | -------------------------------------------------- 87 | There's one additional node in the config that Magento will check while looking up a class name. End users of the system (that means you) may provide a <rewrite/> node that will tell Magento to replace one class with another. This is Magento's famous class rewrite system. Using the following 88 | 89 | 90 | 91 | 92 | Yourpackage_Yourmodule_Model_Someclass 93 | 94 | 95 | 96 | 97 | would tell Magento that whenever a catalog/product_review is instantiated, is should use a Yourpackage\_Yourmodule\_Model\_Someclass. 98 | 99 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-b to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/bin/build-html.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bin/chapters_to_html.php 4 | bin/code_from_chapters.php 5 | bin/to_shell.php book.html 6 | bin/color_code.php book.html 7 | bin/hyphenate.php book.html 8 | bin/finalize.php 9 | bin/cleanup.php 10 | #bin/remove_code.php /tmp/book_in_shell.html > /tmp/no_code.html -------------------------------------------------------------------------------- /magento-1/bin/build-latex.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bin/chapters_to_html.php 4 | bin/code_from_chapters.php 5 | bin/chapters_to_tex.php 6 | 7 | #bin/to_shell.php book.html 8 | #bin/color_code.php book.html 9 | #bin/hyphenate.php book.html 10 | bin/finalize.php 11 | bin/cleanup.php -------------------------------------------------------------------------------- /magento-1/bin/build-sample.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bin/chapters_to_html.php 4 | bin/code_from_chapters.php 5 | bin/chapters_to_tex_sample.php 6 | bin/finalize_sample.php 7 | bin/cleanup.php -------------------------------------------------------------------------------- /magento-1/bin/build.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | bin/chapters_to_html.php 4 | bin/code_from_chapters.php 5 | bin/to_shell.php book.html 6 | bin/color_code.php book.html 7 | bin/hyphenate.php book.html 8 | bin/finalize.php 9 | bin/chapters_to_tex.php 10 | bin/cleanup.php 11 | mv book.html deliverable/nofrills_layout 12 | #bin/remove_code.php /tmp/book_in_shell.html > /tmp/no_code.html -------------------------------------------------------------------------------- /magento-1/bin/chapters_to_html.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | asXml(); 14 | } 15 | $string = substr($string, strlen($tag)+2); 16 | $string = substr($string, 0,strlen($string)-(strlen($tag)+3)); 17 | return $string; 18 | } 19 | 20 | function format_blockquote($node) 21 | { 22 | $string = trim(remove_start_and_end('blockquote',$node)); 23 | if(strpos($string, '

') !== 0) 24 | { 25 | throw new Exception("Unexpected format at " . __LINE__ . " in " . __FILE__); 26 | } 27 | else 28 | { 29 | $string = trim(remove_start_and_end('p',$string)); 30 | } 31 | return '\begin{quote}' . "\n" . 32 | escape_tex_characters($string) . "\n" . 33 | '\end{quote}'; 34 | //return '\subparagraph{'.escape_tex_characters($string).'} ' . "\n";; 35 | } 36 | 37 | function format_p($node) 38 | { 39 | $string = remove_start_and_end('p',$node); 40 | return escape_tex_characters($string); 41 | } 42 | 43 | function format_h3($node) 44 | { 45 | $section = remove_start_and_end('h2',$node); 46 | return sprintf('\subsection{%s}',escape_tex_characters($section)); 47 | } 48 | 49 | function format_h2($node) 50 | { 51 | $section = remove_start_and_end('h2',$node); 52 | return sprintf('\section{%s}',escape_tex_characters($section)); 53 | } 54 | 55 | function format_pre($node) 56 | { 57 | $code = remove_start_and_end('pre',$node); 58 | $code = remove_start_and_end('code',$code); 59 | $code = str_replace("\n\n","\n",$code); //not sure why 60 | 61 | //unspecialchars 62 | $code = htmlspecialchars_decode($code); 63 | //no tex escpanig for listings 64 | // \begin{lstlisting} 65 | // (.+?)}six',$string,$matches); 80 | $items = array(); 81 | foreach($matches[1] as $line) 82 | { 83 | $final_line = $line; 84 | if(strpos($final_line,'

') === 0) 85 | { 86 | $final_line = remove_start_and_end('p',$line); 87 | } 88 | $items[] = $final_line; 89 | } 90 | $s_items = ''; 91 | foreach($items as $item) 92 | { 93 | $s_items .= '\item ' . escape_tex_characters($item) . "\n"; 94 | } 95 | return $s_items; 96 | } 97 | 98 | function format_ul($node) 99 | { 100 | $s_items = get_list_items_from_node($node); 101 | $list = '\begin{itemize}' . "\n" . 102 | $s_items . 103 | '\end{itemize}' . "\n"; 104 | return $list; 105 | } 106 | 107 | function format_ol($node) 108 | { 109 | file_put_contents('/tmp/test.log',"--------------------------------------------------\n",FILE_APPEND); 110 | file_put_contents('/tmp/test.log',$node->asXml()."\n",FILE_APPEND); 111 | $s_items = get_list_items_from_node($node); 112 | file_put_contents('/tmp/test.log',"$s_items\n",FILE_APPEND); 113 | file_put_contents('/tmp/test.log',"--------------------------------------------------\n",FILE_APPEND); 114 | 115 | $list = '\begin{enumerate}' . "\n" . 116 | $s_items . 117 | '\end{enumerate}' . "\n"; 118 | return $list; 119 | } 120 | 121 | function html_to_tex($contents) 122 | { 123 | $tex = array(); 124 | $xml = simplexml_load_string('' . $contents . ''); 125 | foreach($xml->children() as $child) 126 | { 127 | $tex[] = call_user_func('format_'.$child->getName(),$child); 128 | } 129 | 130 | return implode("\n\n",$tex); 131 | } 132 | 133 | function escape_tex_characters($string) 134 | { 135 | $string = str_replace('\\','\\backslash',$string); //stand alone backspaces 136 | $string = preg_replace('/([#$%^&_{}~])/','\\'.'\$1',$string); //LaTeX things that need escaping 137 | $string = preg_replace('{(.+?)}six','\textbf{$1}',$string); //strong text 138 | $string = preg_replace('{(.+?)}six','\emph{$1}',$string); //emphasize 139 | $string = preg_replace_callback('{(.+?)}six','format_inline_code',$string); //code samples 140 | $string = str_replace('\\>','\\textgreater ',$string); //escaped htmlspecialchars 141 | $string = str_replace('\\<','\\textless ',$string); //escaped htmlspecialchars 142 | $string = str_replace('\\&','\\&',$string); //escaped htmlspecialchars 143 | $string = preg_replace_callback('{}','format_images',$string); //images 144 | $string = str_replace('appendix\_f','appendix_f',$string); //lazy fixing 145 | $string = str_replace('appendix\_g','appendix_g',$string); //lazy fixing 146 | 147 | #could probably combine some of these, but seems cleaner to do one by one 148 | //inline code end of sentence 149 | $string = preg_replace('%(texttt\{.+?\}) ([\\\]normalsize) \.%','$1$2.',$string); 150 | 151 | //inline code wuth a following comma 152 | $string = preg_replace('%(texttt\{.+?\}) ([\\\]normalsize) ,%','$1$2,',$string); 153 | 154 | //inline code wuth a following a paren 155 | $string = preg_replace('%(texttt\{.+?\}) ([\\\]normalsize) \)%','$1$2)',$string); 156 | 157 | //inline code wuth a following a quote 158 | $string = preg_replace('%(texttt\{.+?\}) ([\\\]normalsize) \'%','$1$2\'',$string); 159 | 160 | //one offs 161 | $string = preg_replace('%(texttt\{insert}) ([\\\]normalsize) (ing)%','$1$2 $3',$string); 162 | 163 | //one offs 164 | $string = preg_replace('%(texttt\{foreach}) ([\\\]normalsize) (ing)%','$1$2 $3',$string); 165 | 166 | return $string; 167 | } 168 | 169 | function format_images($matches) 170 | { 171 | $string = '\begin{figure}[htb] 172 | \begin{center} 173 | \leavevmode 174 | \includegraphics[width=1\textwidth]{'.$matches[1].'} 175 | \end{center} 176 | \caption{} 177 | %\label{fig:awesome_image} 178 | \end{figure}' . "\n"; 179 | return $string; 180 | } 181 | function format_inline_code($matches) 182 | { 183 | // $inside = str_replace('\_','_',$matches[1]); 184 | $inside = $matches[1]; 185 | return '\footnotesize\texttt{'.$inside.'} \normalsize '; 186 | } 187 | 188 | function get_chapter_contents() 189 | { 190 | include('files.php'); 191 | $files = array_map('markdown_to_html',$files); 192 | 193 | $chapter_contents = array(); 194 | foreach($files as $file) 195 | { 196 | $lines = file('build/' . $file); 197 | $title = array_shift($lines); 198 | $contents = trim(implode("\n",$lines)); 199 | $contents = html_to_tex($contents); 200 | 201 | $chapter_contents[trim(strip_tags($title))] = $contents; 202 | } 203 | return $chapter_contents; 204 | } 205 | function main($argv) 206 | { 207 | $contents = get_chapter_contents(); 208 | 209 | $main_file = array(); 210 | $appendix = false; 211 | foreach($contents as $title=>$contents) 212 | { 213 | $file_name = preg_replace('{[^a-z0-9]}i','_',$title); 214 | $full_path = 'build/'.$file_name.'.tex'; 215 | file_put_contents($full_path,$contents); 216 | if(!$appendix && strpos($title, 'Magento Block Hierarchy') === 0) 217 | { 218 | $main_file[] = '\appendix'; 219 | } 220 | $main_file[] = '\chapter{'.$title.'}'; 221 | 222 | $main_file[] = $contents; 223 | // $main_file[] = '\input{'.$full_path.'}'; 224 | } 225 | $for_main_file = implode("\n",$main_file); 226 | $book = file_get_contents('var/shell.tex'); 227 | $book = str_replace('includeshere',$for_main_file,$book); 228 | file_put_contents('No_Frills_Magento_Layout.tex',$book); 229 | } 230 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/chapters_to_tex_sample.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | $contents) 27 | { 28 | $file_name = preg_replace('{[^a-z0-9]}i','_',$title); 29 | $full_path = 'build/'.$file_name.'.tex'; 30 | file_put_contents($full_path,$contents); 31 | if(is_full_chapter($file_name)) 32 | { 33 | if(!$appendix && strpos($title, 'Magento Block Hierarchy') === 0) 34 | { 35 | $main_file[] = '\appendix'; 36 | } 37 | $main_file[] = '\chapter{'.$title.'}'; 38 | $main_file[] = $contents; 39 | } 40 | else 41 | { 42 | if(!$appendix && strpos($title, 'Magento Block Hierarchy') === 0) 43 | { 44 | $main_file[] = '\appendix'; 45 | } 46 | $main_file[] = '\chapter{'.$title.'}'; 47 | $main_file[] = 'This PDF is a sample, and contains Chapter 0, Chapter 7, and ' . 48 | 'Appendix B. Get the entire book online!' . "\n\n" . 49 | "http://store.pulsestorm.net/products/no-frills-magento-layout" . "\n"; 50 | $main_file[] = parse_sub_sections($contents); 51 | } 52 | } 53 | $for_main_file = implode("\n",$main_file); 54 | $book = file_get_contents('var/shell.tex'); 55 | $book = str_replace('includeshere',$for_main_file,$book); 56 | $book = str_replace('Prepared for Robert Hoffner; ','',$book); 57 | file_put_contents('No_Frills_Magento_Layout.tex',$book); 58 | } 59 | main_sample($argv); -------------------------------------------------------------------------------- /magento-1/bin/cleanup.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | (.+?)}six',$chapter,$matches); 17 | $fragments = $matches[1]; 18 | 19 | $dir_name = 'code/all/' . str_replace('.html','',$file); 20 | if(!is_dir($dir_name)) 21 | { 22 | mkdir($dir_name); 23 | } 24 | 25 | $c=1; 26 | foreach($fragments as $fragment) 27 | { 28 | file_put_contents($dir_name . '/' 29 | . $c . '.txt',htmlspecialchars_decode($fragment)); 30 | $c++; 31 | } 32 | } 33 | } 34 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/color_code.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 1 && count($gt) != count($lt)) 52 | { 53 | return 'PHP'; 54 | } 55 | 56 | if(count($brackets) > 1) 57 | { 58 | return 'PHP'; 59 | } 60 | 61 | if(count($gt) == count($lt) && count($lt) > 1) 62 | { 63 | return 'XML'; 64 | } 65 | 66 | return 'Unknown'; 67 | } 68 | 69 | function nf_format_php($code) 70 | { 71 | $code = trim(htmlspecialchars_decode($code)); 72 | $added = false; 73 | if(strpos($code,'' 82 | . "\n" 83 | . '<?php
', 84 | '', 85 | $code); 86 | } 87 | 88 | $code = str_replace('->','‑>',$code); 89 | 90 | return $code; 91 | } 92 | 93 | function nf_format_navigation($code) 94 | { 95 | return "

$code
"; 96 | } 97 | 98 | function nf_format_xml($code) 99 | { 100 | // $code = trim(htmlspecialchars_decode($code)); 101 | // $xp = new XsltProcessor(); 102 | // $xsl = new DomDocument; 103 | // $xsl->load('bin/xmlverbatim.xsl'); 104 | // $xp->importStyleSheet($xsl); 105 | // 106 | // $xml= new DomDocument; 107 | // $xml->loadXml('' . $code . ''); 108 | // return $xp->transformToXML($xml); 109 | // exit; 110 | return "
$code
"; 111 | } 112 | 113 | function nf_format_unknown($code) 114 | { 115 | return "
$code
"; 116 | } 117 | 118 | 119 | function format_code($code) 120 | { 121 | $type = code_type($code[1]); 122 | $callback = strtolower('nf_format_'.$type); 123 | return $callback($code[1]); 124 | } 125 | 126 | function main($argv) 127 | { 128 | $book = file_get_contents($argv[1]); 129 | $book = preg_replace_callback('{
(.+?)
}six', 130 | 'format_code', 131 | $book); 132 | 133 | file_put_contents($argv[1], $book); 134 | } 135 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/combine_html_chapters.php: -------------------------------------------------------------------------------- 1 | Prepared for Lucas Radaelli. Contents Copyright 2011 Pulse Storm LLC'; 12 | } 13 | 14 | file_put_contents('build/all.html',$html); 15 | symlink('../images','build/images'); 16 | } 17 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/editing-regex.txt: -------------------------------------------------------------------------------- 1 | Checking for a possible miscapitolized Block 2 | 3 | ack '[^a-zA-Z_/]Block' *.markdown 4 | 5 | Lowercased HTML in prose 6 | 7 | ack '[^a-zA-Z_/$.]html' *.markdown 8 | 9 | test list instead of text list 10 | 11 | ack -i 'test[ _]list' *.markdown 12 | 13 | Word "out" in a sentance. Won't catch the first sentance of a paragrapth 14 | 15 | [\.\!\?].+?\bout\b.*?[\.\!\?] 16 | 17 | Out Examples 18 | 19 | ack -i '\bout example' 20 | 21 | No plurel 22 | 23 | ack 'name which' *.markdown 24 | 25 | Checking for a possible miscapitolized Helper 26 | 27 | ack '[^a-zA-Z_/]Helper' *.markdown 28 | 29 | Checking for bad plural 30 | 31 | ack -i 'it add the' *.markdownAlan 32 | 33 | Checking for a possible miscapitolized Helper 34 | ack '[^a-zA-Z_/]Model' *.markdown 35 | -------------------------------------------------------------------------------- /magento-1/bin/files.php: -------------------------------------------------------------------------------- 1 | }m','

',$book); 8 | file_put_contents($argv[1], $book); 9 | } 10 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/remove_code.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | .+?}six','',$contents); 7 | } 8 | main($argv); 9 | exit(0); -------------------------------------------------------------------------------- /magento-1/bin/search.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 16 | 31 | '; 32 | 33 | echo str_replace('####',$argv[1],$template), "\n\n"; 34 | } 35 | main($argv); -------------------------------------------------------------------------------- /magento-1/bin/to_shell.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | (.*)}six', 20 | '' . 21 | $book . 22 | '',$shell); 23 | file_put_contents($argv[1],$book); 24 | } 25 | main($argv); -------------------------------------------------------------------------------- /magento-1/c_appendix_creating_modules.markdown: -------------------------------------------------------------------------------- 1 | Creating Code Modules 2 | ================================================== 3 | The word **module** has come to be one of the most abused in software development. If a designer's adding a table to a side bar, they call it a module. If a developer is adding a class to a system, they call it a module. If the project manager wants to sound tech savvy, they call everything a module. 4 | 5 | The word **module** has a very specific meaning in Magento. If referes to a particular organization of code, such that it may be loaded into an existing Magento system in a defined way, with the loading requiring no knowledge of what other Magento modules are doing. In layman's terms, everyone keeps their code separate, and Magento is smart enough to know where to look for it. 6 | 7 | If you look in 8 | 9 | app/code/core/Mage 10 | 11 | you'll see around 50 - 60 different folders. Each of these is a single module. A module may contain controllers, models, helpers, blocks, SQL Install files, extra configuration files for changing Magento system behavior, new classes for Extending the SOAP and RPC APIs, the list goes on and on. Rather than have a single folder with, say, 200 controller files, Magento uses code modules to organize them by functionality. 12 | 13 | When you want to add code to Magento, either to change existing functionality or add new functionality, you'll also add a new module. However, your module will go in 14 | 15 | app/code/local/* 16 | 17 | instead of app/code/core. This is part of Magento's Code Pool feature, which is separate from the module feature. The local code pool is where you're can put your own code, such that it won't be overridden by Magento's system updates. Magento also has a 18 | 19 | app/code/community/* 20 | 21 | code pool, which is meant for installation of modules from third-parties. 22 | 23 | Adding a Module 24 | -------------------------------------------------- 25 | The first step to creating a module is picking a *Package Name* or *Namespace*. If Bill Gates was making a Magento module, he might pick the name *Microsoft*. Once you've selected your name, create a folder in local 26 | 27 | mkdir app/code/local/Packagename 28 | 29 | This package name can contain multiple code modules. Consider Magento Inc. They use the package name Mage (short for Magento). While not necessary, the general consensus is that the package name should contain only alphanumeric characters, and be single word cased. This helps avoid autoload problems when developing on case insensitive file systems (Windows, OS X sort of) that deploy to case sensitive systems (Linux). The Packagename **will** be used as part of PHP class names, so it also must meet those naming conventions as well. 30 | 31 | Next, pick a name for your module. Strive for something simple that describes what the module is for. **Important**: There's many tutorials that recommend you use names that are the same as Magento's module names if you're rewriting or changing the functionality of a core Magento class. While there's nothing stopping you from doing this, it's not required and can actually cause mass confusion to developers when they're new to the system. 32 | 33 | When you've picked a name, create a folder inside your package name folder 34 | 35 | mkdir app/code/local/Packagename/Modulename 36 | 37 | Finally, every module in Magento needs one more file, a configuration file. This file will contain information about the module's features, and will be merged into Magento's main config, along with all the other modules. Create the following folder 38 | 39 | mkdir app/code/local/Packagename/Modulename/etc 40 | 41 | and then create the following file 42 | 43 | 44 | 45 | 46 | 47 | 1.0.0 48 | 49 | 50 | 51 | 52 | The <Packagename_Modulename/> node should be named using the package name and module name you chose. This unique string will be used to identify your modules. It will also, (and should also), be used as the base name for any classes in your module 53 | 54 | class Packagename_Modulename_IndexController {} 55 | class Packagename_Modulename_Block_Myblock {} 56 | 57 | Enabling your Module 58 | -------------------------------------------------- 59 | There's one last step you'll need to take if you want to let Magento know about your module. If you browse to 60 | 61 | app/etc/modules/ 62 | 63 | you'll see a number of XML files. Think of the etc folder in Magento the same way you would on a *nix system. It contains configuration files for your store's core systems. These XML files tell Magento that you'd like to "turn on" a particular module. Create an XML file using the unique Packagename_Modulename string with the following contents. 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | local 72 | 73 | 74 | 75 | 76 | Again, the <Packagename_Modulename/> node should use the unique string that identifies your own module. The <active>true</active> node determines if Magento loads this particular module's config.xml into the system. You can use this to completely shut off a module (although, if other module's attempt to use that module's functionality, object instantiations will fail). The <codePool>local</codePool> node lets the system know where it can find your module files. The three valid values are core, community, and local 77 | 78 | app/code/core 79 | app/code/community 80 | app/code/local 81 | 82 | With all of the above in place, clear your cache and load up the Admin Console. Head over to 83 | 84 | System -> Configuration -> Advanced -> Disable Module's Output 85 | 86 | This configuration panel is one of the few areas of Magento where you can see a list of all the installed modules. If you followed the above steps correctly, you should see your module listed. Congratulations, you've added a module to the system! 87 | 88 | Next Steps 89 | -------------------------------------------------- 90 | Of course, a module is useless without additional code. Going into everything you can do with a module would be a book in and of itself. However, the general pattern is, before you can add a type of class to your module (model, helper, etc.) you need to add some code to your config.xml. This lets the system know that "hey, this module has feature X and use these classes". This is what makes Magento a **configuration** based MVC system, rather than a convention based one. 91 | 92 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-c to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_1_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_1_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_1_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_1_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_2_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_2_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_2_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_2_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_3_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_3_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_3_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_3_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_5_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_5_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_5_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_5_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_7_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_7_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.4.2/No_Frills_Magento_Layout_7_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.4.2/No_Frills_Magento_Layout_7_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_1_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_1_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_1_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_1_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_2_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_2_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_2_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_2_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_3_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_3_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_3_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_3_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_5_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_5_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_5_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_5_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_7_end-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_7_end-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/code/1.5 or higher/No_Frills_Magento_Layout_7_start-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/code/1.5 or higher/No_Frills_Magento_Layout_7_start-1.0.0.tgz -------------------------------------------------------------------------------- /magento-1/cover.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Untitled 6 | 40 | 41 | 42 | 43 |

...
44 | 45 |
46 |

No Frills Magento Layout

47 |

By Alana Storm

48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /magento-1/d_block_action_reference.markdown: -------------------------------------------------------------------------------- 1 | Block Action Reference 2 | ================================================== 3 | The Block Action reference ended up being ludicrously huge. See the d\_block\_action\_reference.html file, distributed with this book. 4 | 5 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-d to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/e_theme_and_layout_resolution.markdown: -------------------------------------------------------------------------------- 1 | Theme and Layout Resolution 2 | ================================================== 3 | The default Magento design package ships with a default Magento theme. 4 | 5 | #Location of default theme 6 | app/design/frontend/default/default/* 7 | 8 | You could (and can) change the location of this default theme in the Admin Console 9 | 10 | System -> Configuration -> Design -> Themes -> Default 11 | 12 | but even with a new folder name this theme is still your **default** theme. It's meant to contain the main design of your store. 13 | 14 | If you navigate to 15 | 16 | System -> Design 17 | 18 | Magento will allow you select a **custom** theme for a particular date range. The most obvious use case of this is the holiday special. Put Santa on your store, watch those sales soar. 19 | 20 | Template Resolution 21 | -------------------------------------------------- 22 | Prior to Magento 1.4.1, when Magento went looking for a block's template file, it would check if a custom design was set, and 23 | 24 | 1. If no custom design was set, the default theme folder was used 25 | 26 | 2. If a custom design **was** set, Magento was first look for a template there. If it didn't find one, it would fallback to the default theme 27 | 28 | This system worked, but had a small problem. Many stores would never change the default theme. They'd leave it 29 | 30 | default/default 31 | 32 | and just modify those files to skin their store. When they upgraded their system, the default/default theme would also be updated, wiping out their changes. This was viewed as a untenable state of affairs, and the concept of the base design package and theme was created. 33 | 34 | The Base Package 35 | -------------------------------------------------- 36 | The Magento theming system still operates as described above. However, if a template isn't found in the default theme rather than render nothing Magento will look in one final place for the template file in **the base package's default theme** 37 | 38 | app/design/frontend/base/default/* 39 | 40 | This is the **final** fallback. Currently, the default theme that ships with Magento is mostly implemented in the base design package. This allows designers and developers to **selectively** update phtml in the **default** theme if they want to change the behavior of something. The intent is that you **never** edit the base design package. If you want to change a particular template you add it to your default theme. 41 | 42 | Layout Files 43 | -------------------------------------------------- 44 | Layout files follow the same cascading loading rules. First the current custom design is checked, then the default theme, and the default theme in the base design package. Layout files were included in this grand design of the base theme system, as many developers ignore, or are unaware of, local.xml for layout updates. This led many system owners to edit the default Package Layout files to achieve their final design goals, resulting in the same upgrade problems mentioned above. 45 | 46 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-e to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/f_appendix_clearing_cache.markdown: -------------------------------------------------------------------------------- 1 | The Hows and Whys of Clearing Magento's Cache 2 | ================================================== 3 | In layman's terms, caching in computer science/software engineering refers to the practice of doing something that's resource intensive once, storing the results somewhere else, and then the next time someone wants it you hand them the stored result. The most common example of this for web developers is browser caching. Asset files (images, CSS, Javascript) will be downloaded once, and then stored locally for a period of time. This results in better network performance, and hair pulling by web developers at 2am wondering why their CSS files aren't being updated. 4 | 5 | Magento, like most modern web frameworks, heavily utilizes a caching system to improve performance. For example, certain configuration files are loaded once from disk once, combined, and then the combined config is stored on disk for later use. This includes the Layout XML files. This means if you have caching turned on (CE ships with caching on out of the box), you'll need to clear your cache after making any changes to the layout files. Otherwise, the old, cached version of the Package Layout will be loaded and Magento won't see your changes, and you'll be left wondering why your new block isn't showing up. 6 | 7 | You can control cache settings by navigating to 8 | 9 | System -> Cache Managment 10 | 11 | in the Admin Console, (see *Figure F.1*) 12 | 13 | 14 | 15 | From this page you can clear out the cache, or turn it off entirely. 16 | 17 | Occasionally, a cached configuration may prevent you from getting to the Magento Admin Console. For example, consider an event observer with an invalid class name. If this happens, you'll want to look in the var/cache folder 18 | 19 | ls -l var/cache 20 | total 0 21 | drwxrwxrwx 10 _www staff 340 Mar 15 16:10 mage--0 22 | drwxrwxrwx 10 _www staff 340 Mar 15 16:10 mage--1 23 | drwxrwxrwx 6 _www staff 204 Mar 15 16:02 mage--2 24 | drwxrwxrwx 8 _www staff 272 Mar 15 16:02 mage--3 25 | drwxrwxrwx 8 _www staff 272 Mar 15 16:10 mage--4 26 | drwxrwxrwx 12 _www staff 408 Mar 15 16:02 mage--5 27 | drwxrwxrwx 10 _www staff 340 Mar 15 16:02 mage--6 28 | drwxrwxrwx 8 _www staff 272 Mar 15 16:02 mage--7 29 | drwxrwxrwx 12 _www staff 408 Mar 15 16:02 mage--8 30 | drwxrwxrwx 10 _www staff 340 Mar 15 16:02 mage--9 31 | drwxrwxrwx 6 _www staff 204 Mar 15 16:02 mage--a 32 | drwxrwxrwx 10 _www staff 340 Mar 15 16:02 mage--b 33 | drwxrwxrwx 164 _www staff 5576 Mar 15 16:02 mage--c 34 | drwxrwxrwx 172 _www staff 5848 Mar 15 16:02 mage--d 35 | drwxrwxrwx 4 _www staff 136 Mar 15 16:10 mage--e 36 | drwxrwxrwx 12 _www staff 408 Mar 15 16:10 mage--f 37 | 38 | 39 | This folder is where Magento stores its cached data. Delete everything in this folder to manually clear the Magento cache and restore you store's functionality. 40 | 41 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-f to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/g_appendix_setters_and_getters.markdown: -------------------------------------------------------------------------------- 1 | Magento Setters and Getters 2 | ================================================== 3 | In most MVC model systems a common pattern develops. Developers find they need to store two general types of data 4 | 5 | 1. "Business Logic" data (ex. a product's SKU) 6 | 7 | 2. Data that allows the model to function (ex. the database table name) 8 | 9 | It's very common to see developers use a single array (or similar, hash table like structure) property to store the business logic data, allowing the other class/object properties to be used for system functionality. Magento is no different. Any object that comes from a class that inherits from Varien\_Object (which includes both models and blocks) has a protected $\_data property 10 | 11 | /** 12 | * Object attributes 13 | * 14 | * @var array 15 | */ 16 | protected $_data = array(); 17 | 18 | This array holds all the object's business logic data. You can get an array of key/value pairs for this data with the getData method. 19 | 20 | var_dump($object->getData()); 21 | 22 | If you want to **set** a specific data field, use 23 | 24 | $object->setData('the_key', 'value'); 25 | 26 | similarly, if you want a specific field back from an object, you can use 27 | 28 | $value = $object->getData('the_key'); 29 | 30 | and you can set multiple keys at once by using setData with an array. 31 | 32 | $value = $object->setData(array( 33 | 'the_key'=>'value' 34 | 'the_thing'=>$thing, 35 | )); 36 | 37 | You've probably noticed we're naming our keys using an all lower-case, underscore-for-spaces convention. While nothing enforces this, it *is* the standard Magento convention. Beyond consistency, this also helps when it comes to Magento's magic getter and setter methods. 38 | 39 | Getter and Setter 40 | -------------------------------------------------- 41 | In addition to the data getting and setting methods mentioned above, there's also a more "magic" syntax. 42 | 43 | $key = $object->getTheKey(); 44 | $object->setTheKey('value'); 45 | 46 | Using PHP's \_\_call method, Magento has implemented their own get and set methods. If you call a method on an object (with Varien_Objectin the inheritance chain) whose name begins with get or set, **and** there isn't an existing method already with the same name, Magento will use the remainder of the method name to create a data property key, and either get or set the value. That means this 47 | 48 | $object->setTheKey('value'); 49 | 50 | is equivalent to this 51 | 52 | $object->setData('the_key','value'); 53 | 54 | That's why it's important to keep with the lowercase/underscore key convention. Magento will convert the leading-camel-case 55 | 56 | TheKey 57 | 58 | into a key named 59 | 60 | the_key 61 | 62 | Another neat feature here is that the set method will always return an instance of the object being set, which enables method chaining 63 | 64 | $object->setFoo('bar')->setBaz('hola')->save(); 65 | 66 | After using this style interface for a few weeks you'll be loath to return to typing out array brackets. 67 | 68 | Other Magic Methods 69 | -------------------------------------------------- 70 | Magento also has magic methods for unsetting, and checking for the existence of a property 71 | 72 | $this->unsTheKey(); 73 | $this->hasTheKey(); 74 | 75 | Checkout the source of Varien_Object for more information 76 | 77 | public function __call($method, $args) 78 | { 79 | switch (substr($method, 0, 3)) { 80 | case 'get' : 81 | //Varien_Profiler::start('GETTER: '.get_class($this).'::'.$method); 82 | $key = $this->_underscore(substr($method,3)); 83 | $data = $this->getData($key, isset($args[0]) ? $args[0] : null); 84 | //Varien_Profiler::stop('GETTER: '.get_class($this).'::'.$method); 85 | return $data; 86 | 87 | case 'set' : 88 | //Varien_Profiler::start('SETTER: '.get_class($this).'::'.$method); 89 | $key = $this->_underscore(substr($method,3)); 90 | $result = $this->setData($key, isset($args[0]) ? $args[0] : null); 91 | //Varien_Profiler::stop('SETTER: '.get_class($this).'::'.$method); 92 | return $result; 93 | 94 | case 'uns' : 95 | //Varien_Profiler::start('UNS: '.get_class($this).'::'.$method); 96 | $key = $this->_underscore(substr($method,3)); 97 | $result = $this->unsetData($key); 98 | //Varien_Profiler::stop('UNS: '.get_class($this).'::'.$method); 99 | return $result; 100 | 101 | case 'has' : 102 | //Varien_Profiler::start('HAS: '.get_class($this).'::'.$method); 103 | $key = $this->_underscore(substr($method,3)); 104 | //Varien_Profiler::stop('HAS: '.get_class($this).'::'.$method); 105 | return isset($this->_data[$key]); 106 | } 107 | throw new Varien_Exception("Invalid method " . get_class($this) . "::" . 108 | $method."(".print_r($args,1).")"); 109 | } 110 | 111 | 112 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-g to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/h_widget_field_rendering_options.markdown: -------------------------------------------------------------------------------- 1 | Widget Field Rendering Options 2 | ================================================== 3 | The simplest configuration for a Magento widget data parameter is 4 | 5 | 6 | 7 | 0 8 | 1 9 | foobazbar 10 | text 11 | 12 | 13 | 14 | This creates a hidden field (<visible>0</visible>) that will always be populated with the value 'foobazbar' (<value>foobazbar</value>). 15 | 16 | While hidden fields are useful for widgets entered via a CMS content area, it's far more common for parameters to have a visible user interface element that allows end-system-users to enter data. That is to say, a visible text field is more common 17 | 18 | 19 | 20 | 1 21 | 1 22 | 23 | text 24 | bazbarfoo 25 | 10 26 | 27 | 28 | 29 | We've changed the <visible/> tag so it contains the value "1" (boolean for true). We've also added a <label> tag which will be used as the text label which describes the field, and a <sort_order> field which control where (above or below) a particular UI element will show up compared to others. The <value>bazbarfoo</value> tag will set the **default** value for the UI element. 30 | 31 | 32 | 33 | You can also augment your fields with some instructional text by using the <description/> node. 34 | 35 | 36 | 37 | 1 38 | 1 39 | 40 | text 41 | bazbarfoo 42 | 10 43 | 44 | This is the field where we put the thing 45 | 46 | 47 | 48 | 49 | Sometimes a free form text field gives users too much control over what values they enter in a widget. For cases where we want to restrict a user's choices, we can use a select or multiselect. 50 | 51 | 52 | 53 | 1 54 | 1 55 | 56 | select 57 | stay 58 | 59 | 60 | stay 61 | 62 | 63 | 64 | go 65 | 66 | 67 | 68 | 10 69 | 70 | 71 | 72 | The important changes here are we've changed our to <type/> tag to select, and added a new <values/> node. The sub-nodes of the <values/> node will be used to create the label/value pairs for the HTML <select> elements generated for the front end. Alternatly, you can provide the name of a source model. 73 | 74 | 75 | 76 | 1 77 | 1 78 | 79 | select 80 | stay 81 | adminhtml/system_config_source_yesno 82 | 10 83 | 84 | 85 | 86 | The string adminhtml/system\_config\_source\_yesno is a class alias for a Magento model (in this case Mage\_Adminhtml\_Model\_System\_Config\_Source\_Yesno). Source models are special model classes with a toOptionArray method. 87 | 88 | class Mage_Adminhtml_Model_System_Config_Source_Yesno 89 | { 90 | 91 | /** 92 | * Options getter 93 | * 94 | * @return array 95 | */ 96 | public function toOptionArray() 97 | { 98 | return array( 99 | array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('Yes')), 100 | array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('No')), 101 | ); 102 | } 103 | 104 | } 105 | 106 | This method returns a set of key/value pairs for your select. You may create your own source models, or use one the models that ships with Magento. Checkout the PHP files in 107 | 108 | app/code/core/Mage/Adminhtml/Model/System/Config/Source 109 | 110 | for a list of the source models that ship with Magento. 111 | 112 | Creating Your Own Form Elements 113 | -------------------------------------------------- 114 | Sometimes you're going to want a form element that's more interactive than a single text or a select. The widget system has a mechanism that allows you to build your own form elements for the widget UI. 115 | 116 | First, your parameter configuration should look like the following 117 | 118 | 119 | 1 120 | 1 121 | 122 | label 123 | 124 | yourpackage_yourmodule/widgettest 125 | 126 | 10 127 | This is the field where you'll put the synergy. 128 | 129 | 130 | The key nodes here are <type> and <helper_block>. Our field type here is label. Normally, a field type of label will render the label for a field without any form element. In other words, a form element with no functional value, only instructional/branding/experience. However, we've also included a <helper\_block> node. This node (via the <type/> sub-node) configures a block class that will render our form. 131 | 132 | After configuring this parameter, you'll need to define your block class. Despite living in the standard block heirarchy, we **do not** want to implement our rendering in its \_toHtml method. Instead, this class needs a special method named prepareElementHtml 133 | 134 | #File: app/code/local/Yourpackage/Yourmodule/Block/Widgettest.php 135 | class Yourpackage_Yourmodule_Block_Widgettest extends Mage_Core_Block_Abstract 136 | { 137 | /** 138 | * Overly simple example 139 | */ 140 | public function prepareElementHtml( 141 | Varien_Data_Form_Element_Abstract $element) 142 | { 143 | $simple_input = ''; 148 | 149 | $element->setData('after_element_html', $simple_input); 150 | 151 | $element->setValue(''); //blank out value 152 | return $element; 153 | } 154 | } 155 | 156 | During the rendering of your parameter's UI, Magento will call the prepareElementHtml method of your helper\_block, passing in a Varien\_Data\_Form\_Element\_Abstract object. This $element is the object that Magento will use to render out your form element. To implement a custom form element, your job is 157 | 158 | 1. Grab the form element's name and value from $element. The value will contain previously saved values, and the name will be the correct name for the HTML form element to ensure the form data is saved on post 159 | 160 | 2. Add HTML to the form element's rendering process to implement your custom element 161 | 162 | 3. Optionally, if you don't want the default value rendering to take place, clear the value from $element before returning it. 163 | 164 | In our example above, we've created a ludicrously simple example to demonstrate how you might acheive this. We've 165 | 166 | 1. Created a HTML element ($simple_input) using string concatenation. 167 | 168 | 2. Added this HTML to the element with $element->setData('after\_element\_html', $simple\_input); 169 | 170 | 3. Zeroed out the value of $element 171 | 172 | Advanced Examples 173 | -------------------------------------------------- 174 | As mentioned, our example above is ludicrously simple. However, with the power to create any arbitrary HTML, CSS or Javascript for your form, the possibilities are endless. Look to a few of Magento's <block\_helper>s for inspiration 175 | 176 | app/code/core/Mage/Adminhtml/Block/Catalog/Category/Widget/Chooser.php 177 | app/code/core/Mage/Adminhtml/Block/Catalog/Product/Widget/Chooser.php 178 | app/code/core/Mage/Adminhtml/Block/Cms/Block/Widget/Chooser.php 179 | app/code/core/Mage/Adminhtml/Block/Cms/Page/Widget/Chooser.php 180 | 181 | 182 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-h to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/i_system_config.markdown: -------------------------------------------------------------------------------- 1 | System Configuration Variables 2 | ================================================== 3 | A simple system configuration system might store a set of key/value pairs something like this. 4 | 5 | $config['db_name'] = 'localhost'; 6 | $config['db_password'] = '12345'; 7 | $config['logo'] = 'awesomelogo.gif'; 8 | etc. 9 | 10 | However, in keeping with its core philosophy of "When in doubt, use XML", Magento stores its system configuration values in *tree* format. The above might be represented something like this 11 | 12 | 13 | 14 | 15 | localhost 16 | 12345 17 | 18 | 19 | awesomelogo.gif 20 | 21 | 22 | 23 | 24 | This is a common approach to modern configuration systems, as it allows you to develop a hierarchy of organized values as more and more sections of your system or application become configurable. What's really interesting is, using xpath-like expressions, you can still treat a node-based configuration system as a set of key/value pairs. That's exactly how you fetch a Magento System Configuration value 25 | 26 | Mage::getStoreConfig('store/database/name'); 27 | Mage::getStoreConfig('store/database/password'); 28 | Mage::getStoreConfig('store/design/logo'); 29 | 30 | Magento allows each module to define new nodes for this configuration tree, as well as user interfaces for store owners to enter configuration values in the Admin Console under 31 | 32 | System -> Configuration 33 | 34 | This system is beyond the scope of this book, but there's plenty of information online. If you're interested, you can start reading here 35 | 36 | http://alanstorm.com/custom_magento_system_configuration 37 | 38 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-i to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/images/appendix_f/cache-manage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/appendix_f/cache-manage.png -------------------------------------------------------------------------------- /magento-1/images/appendix_g/field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/appendix_g/field.png -------------------------------------------------------------------------------- /magento-1/images/chapter1/helloworld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter1/helloworld.png -------------------------------------------------------------------------------- /magento-1/images/chapter1/nofirst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter1/nofirst.png -------------------------------------------------------------------------------- /magento-1/images/chapter1/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter1/start.png -------------------------------------------------------------------------------- /magento-1/images/chapter1/twocities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter1/twocities.png -------------------------------------------------------------------------------- /magento-1/images/chapter2/after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter2/after.png -------------------------------------------------------------------------------- /magento-1/images/chapter2/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter2/before.png -------------------------------------------------------------------------------- /magento-1/images/chapter2/complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter2/complex.png -------------------------------------------------------------------------------- /magento-1/images/chapter2/with-content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter2/with-content.png -------------------------------------------------------------------------------- /magento-1/images/chapter3/blank-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter3/blank-theme.png -------------------------------------------------------------------------------- /magento-1/images/chapter3/blank-with-handles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter3/blank-with-handles.png -------------------------------------------------------------------------------- /magento-1/images/chapter3/config-package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter3/config-package.png -------------------------------------------------------------------------------- /magento-1/images/chapter4/package-layout-files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter4/package-layout-files.png -------------------------------------------------------------------------------- /magento-1/images/chapter4/page-layout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter4/page-layout.gif -------------------------------------------------------------------------------- /magento-1/images/chapter4/page-layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter4/page-layout.png -------------------------------------------------------------------------------- /magento-1/images/chapter5/order-base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter5/order-base.png -------------------------------------------------------------------------------- /magento-1/images/chapter5/order-before-two.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter5/order-before-two.png -------------------------------------------------------------------------------- /magento-1/images/chapter6/cms-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter6/cms-page.png -------------------------------------------------------------------------------- /magento-1/images/chapter6/page-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter6/page-info.png -------------------------------------------------------------------------------- /magento-1/images/chapter6/page1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter6/page1.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/instance-displayon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/instance-displayon.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/instance-pageselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/instance-pageselected.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/instance-set-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/instance-set-data.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/instance-step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/instance-step1.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/instance-step2-always.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/instance-step2-always.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/invalidated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/invalidated.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/show-hide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/show-hide.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/widget-window-with-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/widget-window-with-data.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/widget-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/widget-window.png -------------------------------------------------------------------------------- /magento-1/images/chapter7/with-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-1/images/chapter7/with-template.png -------------------------------------------------------------------------------- /magento-1/j_magento_connect.markdown: -------------------------------------------------------------------------------- 1 | Magento Connect 2 | ================================================== 3 | Magento Connect is a lot of things. First and foremost, it's Magento Inc's online repository for free, downloadable extensions. It's also a package management system that was, originally, based on the PHP PEAR packaging format. Magento Connect 2.0 was released along with Magento CE 1.5. This means there's two separate package file formats, which is why we've included two different sets of modules. 4 | 5 | What is an Extension 6 | -------------------------------------------------- 7 | As you may already know, Magento separates its "backend" code into formal code modules. A Magento Connect extension may **contain** modules, but a Magento Connect extension is not **just** a code module. 8 | 9 | A Magento Connect extension is a packaged collection of files that Magento will install into your system. Each file in the package has a Magento Connect type, which will control where Magento installs the file. For example, a local module file knows to install itself in ./app/code/local, whereas a PHP Library file installs itself in ./lib. See 10 | 11 | > System -> Connect -> Package Extensions 12 | 13 | for a full list of types. 14 | 15 | There's one type in particular you'll want to be aware of. That's the other type. This type's base folder is Magento's base installation folder, which gives a Magento extension the ability to install a file **anywhere** in your system, and in turn you can create a package that includes files from anywhere. 16 | 17 | Installing Extensions: The GUI Way 18 | -------------------------------------------------- 19 | There's a GUI admin for Magento Connect. You can reach it from the Admin Console by navigating to 20 | 21 | System -> Magento Connect -> Magento Connect Manager 22 | 23 | You'll need to reauthorize your session as the admin user, (or any user with Magento Connect ACL rights). The code that bootstraps the Magento Connect Manager is separate from the source code of your Magento system proper. 24 | 25 | Installing extensions that have been uploaded to Magento Inc's central server is as easy as entering the extension key into the installation field. 26 | 27 | If you've downloaded a .tgz package file from the internet, Magento 1.5 also offers a handy upload form, allows you to directly upload an extension 28 | 29 | 30 | Installing Extensions: The Command Line Way 31 | -------------------------------------------------- 32 | Both the 1.4x and 1.5x branches of Magento offer the ability to install extension from the command line. However, the tools used for each version differ slightly. 33 | 34 | ###Magento Connect CLI install for Magento 1.42 35 | 36 | In the root folder of Magento 1.4.2 there's a shell script named pear. This shell script in **not** the standard PEAR installer. It's a customized installer you may use to install Magento Connect extensions. To use it, you'll need to tell your operating system its allowed to execute it as a program 37 | 38 | chmod +x pear 39 | 40 | After that, you'll need to run 41 | 42 | ./pear mage-setup 43 | 44 | After setting a number of configuration variables and initializing two channels 45 | 46 | connect.magentocommerce.com/core 47 | connect.magentocommerce.com/community 48 | 49 | the script will exit. You're now ready to install and uninstall packages using the command line installer 50 | 51 | ./pear install No_Frills_Magento_Layout_1_start-1.0.0.tgz 52 | ./pear uninstall \ 53 | channel://connect.magentocommerce.com/community/No_Frills_Magento_Layout_1_sta... 54 | 55 | ###Magento Connect CLI install for Magento 1.5+ 56 | 57 | Magento 1.5 removed the pear installer, and introduced a new command line script (mage) that offers a similar function. Again, you'll need to give it executable permissions 58 | 59 | chmod +x mage 60 | 61 | and then initialize it with 62 | 63 | ./mage mage-setup 64 | 65 | After the setup script finishes running, you'll be able to install extensions from a file. **NOTE**: The command has changed to install-file, and the arguments to uninstall have changed as well 66 | 67 | ./mage install-file No_Frills_Magento_Layout_3_start-1.0.0.tgz 68 | ./mage uninstall community No_Frills_Magento_Layout_3_start 69 | 70 | *Visit http://www.pulsestorm.net/nofrills-layout-appendix-j to join the discussion online.* -------------------------------------------------------------------------------- /magento-1/nofrills.latex: -------------------------------------------------------------------------------- 1 | \documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$} 2 | \usepackage{titlesec} 3 | \usepackage[toc,page]{appendix} 4 | $if(fontfamily)$ 5 | \usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$} 6 | $else$ 7 | \usepackage{lmodern} 8 | $endif$ 9 | $if(linestretch)$ 10 | \usepackage{setspace} 11 | \setstretch{$linestretch$} 12 | $endif$ 13 | \usepackage{amssymb,amsmath} 14 | \usepackage{ifxetex,ifluatex} 15 | \usepackage{fixltx2e} % provides \textsubscript 16 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 17 | \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc} 18 | \usepackage[utf8]{inputenc} 19 | $if(euro)$ 20 | \usepackage{eurosym} 21 | $endif$ 22 | \else % if luatex or xelatex 23 | \ifxetex 24 | \usepackage{mathspec} 25 | \else 26 | \usepackage{fontspec} 27 | \fi 28 | \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase} 29 | $for(fontfamilies)$ 30 | \newfontfamily{$fontfamilies.name$}[$fontfamilies.options$]{$fontfamilies.font$} 31 | $endfor$ 32 | $if(euro)$ 33 | \newcommand{\euro}{€} 34 | $endif$ 35 | $if(mainfont)$ 36 | \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$} 37 | $endif$ 38 | $if(sansfont)$ 39 | \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$]{$sansfont$} 40 | $endif$ 41 | $if(monofont)$ 42 | \setmonofont[Mapping=tex-ansi$if(monofontoptions)$,$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$endif$]{$monofont$} 43 | $endif$ 44 | $if(mathfont)$ 45 | \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$} 46 | $endif$ 47 | $if(CJKmainfont)$ 48 | \usepackage{xeCJK} 49 | \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$} 50 | $endif$ 51 | \fi 52 | % use upquote if available, for straight quotes in verbatim environments 53 | \IfFileExists{upquote.sty}{\usepackage{upquote}}{} 54 | % use microtype if available 55 | \IfFileExists{microtype.sty}{% 56 | \usepackage{microtype} 57 | \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts 58 | }{} 59 | $if(geometry)$ 60 | \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} 61 | $endif$ 62 | \usepackage{hyperref} 63 | $if(colorlinks)$ 64 | \PassOptionsToPackage{usenames,dvipsnames}{color} % color is loaded by hyperref 65 | $endif$ 66 | \hypersetup{unicode=true, 67 | $if(title-meta)$ 68 | pdftitle={$title-meta$}, 69 | $endif$ 70 | $if(author-meta)$ 71 | pdfauthor={$author-meta$}, 72 | $endif$ 73 | $if(keywords)$ 74 | pdfkeywords={$for(keywords)$$keywords$$sep$; $endfor$}, 75 | $endif$ 76 | $if(colorlinks)$ 77 | colorlinks=true, 78 | linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$, 79 | citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$, 80 | urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$, 81 | $else$ 82 | pdfborder={0 0 0}, 83 | $endif$ 84 | breaklinks=true} 85 | \urlstyle{same} % don't use monospace font for urls 86 | $if(lang)$ 87 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 88 | \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel} 89 | $if(babel-newcommands)$ 90 | $babel-newcommands$ 91 | $endif$ 92 | \else 93 | \usepackage{polyglossia} 94 | \setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$} 95 | $for(polyglossia-otherlangs)$ 96 | \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$} 97 | $endfor$ 98 | \fi 99 | $endif$ 100 | $if(natbib)$ 101 | \usepackage{natbib} 102 | \bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} 103 | $endif$ 104 | $if(biblatex)$ 105 | \usepackage$if(biblio-style)$[style=$biblio-style$]$endif${biblatex} 106 | $if(biblatexoptions)$\ExecuteBibliographyOptions{$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$}$endif$ 107 | $for(bibliography)$ 108 | \addbibresource{$bibliography$} 109 | $endfor$ 110 | $endif$ 111 | $if(listings)$ 112 | \usepackage{listings} 113 | \newcommand{\passthrough}[1]{#1} 114 | $endif$ 115 | $if(lhs)$ 116 | \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} 117 | $endif$ 118 | $if(highlighting-macros)$ 119 | $highlighting-macros$ 120 | $endif$ 121 | $if(verbatim-in-note)$ 122 | \usepackage{fancyvrb} 123 | \VerbatimFootnotes % allows verbatim text in footnotes 124 | $endif$ 125 | $if(tables)$ 126 | \usepackage{longtable,booktabs} 127 | $endif$ 128 | $if(graphics)$ 129 | \usepackage{graphicx,grffile} 130 | \makeatletter 131 | \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} 132 | \def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} 133 | \makeatother 134 | % Scale images if necessary, so that they will not overflow the page 135 | % margins by default, and it is still possible to overwrite the defaults 136 | % using explicit options in \includegraphics[width, height, ...]{} 137 | \setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} 138 | $endif$ 139 | $if(links-as-notes)$ 140 | % Make links footnotes instead of hotlinks: 141 | \renewcommand{\href}[2]{#2\footnote{\url{#1}}} 142 | $endif$ 143 | $if(strikeout)$ 144 | \usepackage[normalem]{ulem} 145 | % avoid problems with \sout in headers with hyperref: 146 | \pdfstringdefDisableCommands{\renewcommand{\sout}{}} 147 | $endif$ 148 | $if(indent)$ 149 | $else$ 150 | \IfFileExists{parskip.sty}{% 151 | \usepackage{parskip} 152 | }{% else 153 | \setlength{\parindent}{0pt} 154 | \setlength{\parskip}{6pt plus 2pt minus 1pt} 155 | } 156 | $endif$ 157 | \setlength{\emergencystretch}{3em} % prevent overfull lines 158 | \providecommand{\tightlist}{% 159 | \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} 160 | $if(numbersections)$ 161 | \setcounter{secnumdepth}{5} 162 | $else$ 163 | \setcounter{secnumdepth}{0} 164 | $endif$ 165 | $if(subparagraph)$ 166 | $else$ 167 | % Redefines (sub)paragraphs to behave more like sections 168 | \ifx\paragraph\undefined\else 169 | \let\oldparagraph\paragraph 170 | \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} 171 | \fi 172 | \ifx\subparagraph\undefined\else 173 | \let\oldsubparagraph\subparagraph 174 | \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} 175 | \fi 176 | $endif$ 177 | $if(dir)$ 178 | \ifxetex 179 | % load bidi as late as possible as it modifies e.g. graphicx 180 | $if(latex-dir-rtl)$ 181 | \usepackage[RTLdocument]{bidi} 182 | $else$ 183 | \usepackage{bidi} 184 | $endif$ 185 | \fi 186 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 187 | \TeXXeTstate=1 188 | \newcommand{\RL}[1]{\beginR #1\endR} 189 | \newcommand{\LR}[1]{\beginL #1\endL} 190 | \newenvironment{RTL}{\beginR}{\endR} 191 | \newenvironment{LTR}{\beginL}{\endL} 192 | \fi 193 | $endif$ 194 | $for(header-includes)$ 195 | $header-includes$ 196 | $endfor$ 197 | 198 | $if(title)$ 199 | \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} 200 | $endif$ 201 | $if(subtitle)$ 202 | \providecommand{\subtitle}[1]{} 203 | \subtitle{$subtitle$} 204 | $endif$ 205 | $if(author)$ 206 | \author{$for(author)$$author$$sep$ \and $endfor$} 207 | $endif$ 208 | $if(institute)$ 209 | \institute{$for(institute)$$institute$$sep$ \and $endfor$} 210 | $endif$ 211 | \date{$date$} 212 | 213 | \usepackage{xcolor} 214 | 215 | % 216 | % listing colors 217 | % 218 | \definecolor{listing-background}{HTML}{F7F7F7} 219 | \definecolor{listing-rule}{HTML}{B3B2B3} 220 | \definecolor{listing-numbers}{HTML}{B3B2B3} 221 | \definecolor{listing-text-color}{HTML}{000000} 222 | \definecolor{listing-keyword}{HTML}{435489} 223 | \definecolor{listing-identifier}{HTML}{435489} 224 | \definecolor{listing-string}{HTML}{00999A} 225 | \definecolor{listing-comment}{HTML}{8E8E8E} 226 | \definecolor{listing-javadoc-comment}{HTML}{006CA9} 227 | 228 | $if(listings)$ 229 | \lstdefinestyle{nofrills_listing_style}{ 230 | language = java, 231 | numbers = left, 232 | backgroundcolor = \color{listing-background}, 233 | basicstyle = \color{listing-text-color}\small\ttfamily{}\linespread{1.15}, % print whole listing small 234 | xleftmargin = 2.7em, 235 | breaklines = true, 236 | frame = single, 237 | framesep = 0.6mm, 238 | rulecolor = \color{listing-rule}, 239 | frameround = ffff, 240 | framexleftmargin = 2.5em, 241 | tabsize = 4, 242 | numberstyle = \color{listing-numbers}, 243 | aboveskip = 1.0em, 244 | keywordstyle = \color{listing-keyword}\bfseries, 245 | classoffset = 0, 246 | sensitive = true, 247 | identifierstyle = \color{listing-identifier}, 248 | commentstyle = \color{listing-comment}, 249 | morecomment = [s][\color{listing-javadoc-comment}]{/**}{*/}, 250 | stringstyle = \color{listing-string}, 251 | showstringspaces = false, 252 | escapeinside = {/*@}{@*/}, % Allow LaTeX inside these special comments 253 | literate = 254 | {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 255 | {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 256 | {à}{{\`a}}1 {è}{{\'e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 257 | {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 258 | {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 259 | {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 260 | {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 261 | {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 262 | {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 263 | {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 264 | {€}{{\EUR}}1 {£}{{\pounds}}1 {«}{{\guillemotleft}}1 265 | {»}{{\guillemotright}}1 {ñ}{{\~n}}1 {Ñ}{{\~N}}1 {¿}{{?`}}1 266 | {…}{{\ldots}}1 {≥}{{>=}}1 {≤}{{<=}}1 {„}{{\glqq}}1 {“}{{\grqq}}1 267 | {”}{{''}}1 268 | } 269 | \lstset{style=nofrills_listing_style} 270 | 271 | \lstdefinelanguage{XML}{ 272 | morestring = [b]", 273 | moredelim = [s][\bfseries\color{listing-keyword}]{<}{\ }, 274 | moredelim = [s][\bfseries\color{listing-keyword}]{}, 275 | moredelim = [l][\bfseries\color{listing-keyword}]{/>}, 276 | moredelim = [l][\bfseries\color{listing-keyword}]{>}, 277 | morecomment = [s]{}, 278 | morecomment = [s]{}, 279 | commentstyle = \color{listing-comment}, 280 | stringstyle = \color{listing-string}, 281 | identifierstyle = \color{listing-identifier} 282 | } 283 | 284 | \begin{document} 285 | 286 | \title{No Frills Magento 2 Layout} 287 | \author{Alana Storm} 288 | \date{April 2018} 289 | 290 | \maketitle 291 | 292 | 293 | $if(title)$ 294 | \maketitle 295 | $endif$ 296 | $if(abstract)$ 297 | \begin{abstract} 298 | $abstract$ 299 | \end{abstract} 300 | $endif$ 301 | 302 | $for(include-before)$ 303 | $include-before$ 304 | 305 | $endfor$ 306 | $if(toc)$ 307 | { 308 | $if(colorlinks)$ 309 | \hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$black$endif$} 310 | $endif$ 311 | \chapter*{IMPORTANT} 312 | 313 | Copyright \copyright 2018 Pulse Storm LLC 314 | 315 | This book is a commercial product of Pulse Storm LLC, and may not be distributed without their express permission. Digital files contain purchaser metadata. If you've received a copy of this book without paying and have the means, please purchase your official copy via https://store.pulsestorm.net 316 | 317 | \setcounter{tocdepth}{$toc-depth$} 318 | \tableofcontents 319 | } 320 | $endif$ 321 | $if(lot)$ 322 | \listoftables 323 | $endif$ 324 | $if(lof)$ 325 | \listoffigures 326 | $endif$ 327 | $body$ 328 | 329 | $if(natbib)$ 330 | $if(bibliography)$ 331 | $if(biblio-title)$ 332 | $if(book-class)$ 333 | \renewcommand\bibname{$biblio-title$} 334 | $else$ 335 | \renewcommand\refname{$biblio-title$} 336 | $endif$ 337 | $endif$ 338 | \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$} 339 | 340 | $endif$ 341 | $endif$ 342 | $if(biblatex)$ 343 | \printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ 344 | 345 | $endif$ 346 | $for(include-after)$ 347 | $include-after$ 348 | 349 | $endfor$ 350 | 351 | $endif$ 352 | \end{document} 353 | -------------------------------------------------------------------------------- /magento-1/subs.php: -------------------------------------------------------------------------------- 1 | "Layout system" -------------------------------------------------------------------------------- /magento-1/test.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /magento-1/texput.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.141592-1.40.3 (Web2C 7.5.6) (format=pdflatex 2011.4.4) 29 JAN 2012 11:49 2 | entering extended mode 3 | **deliverable/nofrills_layout/No_Frills_Magento_Layout.tex 4 | 5 | ! Emergency stop. 6 | <*> ...ofrills_layout/No_Frills_Magento_Layout.tex 7 | 8 | End of file on the terminal! 9 | 10 | 11 | Here is how much of TeX's memory you used: 12 | 4 strings out of 94073 13 | 142 string characters out of 1164798 14 | 48804 words of memory out of 1500000 15 | 3390 multiletter control sequences out of 10000+50000 16 | 3640 words of font info for 14 fonts, out of 1200000 for 2000 17 | 645 hyphenation exceptions out of 8191 18 | 0i,0n,0p,1b,6s stack positions out of 5000i,500n,6000p,200000b,5000s 19 | ! ==> Fatal error occurred, no output PDF file produced! 20 | -------------------------------------------------------------------------------- /magento-1/var/guide.html: -------------------------------------------------------------------------------- 1 | #frame 2 | { 3 | float:left; 4 | position:absolute; 5 | top:0px; 6 | left:0px; 7 | width:9in; 8 | height:900in; 9 | border:1px solid #000; 10 | } 11 | 12 | 13 |
... 14 |
15 | -------------------------------------------------------------------------------- /magento-1/var/shell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Untitled 6 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /magento-1/var/shell.tex: -------------------------------------------------------------------------------- 1 | \documentclass[oneside]{book} 2 | \usepackage{verbatim} 3 | \usepackage{fancyhdr} 4 | \pagestyle{fancy} 5 | \usepackage{graphicx} 6 | \usepackage[font=small,labelsep=none]{caption} 7 | \usepackage{listings} 8 | %\usepackage{courier} 9 | \lstset{language=PHP, 10 | %frame=single, 11 | %numbers=left, 12 | basicstyle=\footnotesize\ttfamily, 13 | tabsize=4, 14 | showspaces=false, 15 | showstringspaces=false 16 | } 17 | 18 | \fancyhead[LO,LE]{} 19 | %\fancyhead[RC,RC]{} 20 | %\fancyhead[RO,RE]{} 21 | 22 | \fancyfoot[LO,LE]{Prepared for Robert Hoffner; Copyright \copyright 2011 Pulse Storm LLC} 23 | \fancyfoot[RC,RC]{} 24 | \fancyfoot[RO,RE]{\thepage} 25 | 26 | \DeclareGraphicsExtensions{.pdf,.png,.jpg,.gif} 27 | 28 | \usepackage{parskip} 29 | \setlength{\parindent}{0pt} 30 | 31 | \begin{document} 32 | 33 | \title{No Frills Magento Layout} 34 | \author{Alana Storm} 35 | \date{April 2011} 36 | 37 | \maketitle 38 | \tableofcontents 39 | \setcounter{chapter}{-1} 40 | 41 | includeshere 42 | 43 | %\chapter{Introduction} 44 | %\input{var/0_intro} 45 | % 46 | %reference 47 | %\chapter{Introduction} 48 | %Lorem \emph{ipsum dolor sit amet}, consectetur \textbf{adipisicing elit}, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 49 | %\chapter{Foo Baz Bar} 50 | %Lorem \emph{ipsum dolor sit amet}, consectetur \textbf{adipisicing elit}, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 51 | %\begin{figure}[htb] 52 | %\begin{center} 53 | %\leavevmode 54 | %\includegraphics[width=1\textwidth]{../images/chapter1/twocities} 55 | %\end{center} 56 | %%\caption{Screen Shot} 57 | %%\label{fig:awesome_image} 58 | %\end{figure} 59 | %\section{A Section Header} 60 | %Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 61 | %\subparagraph{The quick brown fox jumps over the lazy dog.} 62 | %\chapter{Building Layouts Programmatically} 63 | %Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 64 | %\appendix 65 | %\chapter{Awesome} 66 | %Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 67 | %\chapter{Foo Baz Bar} 68 | %Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 69 | 70 | 71 | \end{document} -------------------------------------------------------------------------------- /magento-2/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | output 3 | wordcount.txt 4 | *.zip -------------------------------------------------------------------------------- /magento-2/LICENSE: -------------------------------------------------------------------------------- 1 | ALL RIGHTS RESERVED Copyright © Pulse Storm LLC and Alana Storm -------------------------------------------------------------------------------- /magento-2/README.md: -------------------------------------------------------------------------------- 1 | # No Frills Magento 2 Layout 2 | 3 | Build is currently a manual process. You'll need 4 | 5 | - PHP 6 | - pandoc 7 | - A LaTeX with xelatex 8 | 9 | installed. To run the build invoke the following command 10 | 11 | % php build.php 12 | 13 | Files will be dropped into the `output` folder -------------------------------------------------------------------------------- /magento-2/build.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | $samples) 53 | { 54 | $i++; 55 | $path = $pathCode . '/chapter-' . $i; 56 | if($chapter == '# Appendix') 57 | { 58 | $path = $pathCode . '/appdendix'; 59 | } 60 | @mkdir($path); 61 | $j=0; 62 | foreach($samples as $sample) 63 | { 64 | $j++; 65 | $pathCodeFile = $path . '/' . $j . '.txt'; 66 | file_put_contents($pathCodeFile, $sample); 67 | output("Creating $pathCodeFile"); 68 | } 69 | } 70 | } 71 | 72 | function pestle_cli($argv, $options) 73 | { 74 | if(isset($options['sample-book'])) 75 | { 76 | define('SRC','src.sample'); 77 | } 78 | else 79 | { 80 | define('SRC','src'); 81 | } 82 | 83 | 84 | echo `mkdir -p output`; 85 | $files = glob(SRC . '/*.md'); 86 | if(count($files) === 0) 87 | { 88 | output("No " . SRC . "/, bailing"); 89 | exit; 90 | } 91 | 92 | $chapters = [ 93 | SRC . '/chapter-0-introduction.md', 94 | SRC . '/chapter-1-blocks-template-php.md', 95 | SRC . '/chapter-2-layout-xml.md', 96 | SRC . '/chapter-3-layouthandles.md', 97 | SRC . '/chapter-4-page-layout.md', 98 | SRC . '/chapter-5-themes.md', 99 | SRC . '/chapter-6-advanced-xml-loading.md', 100 | SRC . '/chapter-7-frontend-css.md', 101 | SRC . '/chapter-8-frontend-javascript.md', 102 | SRC . '/chapter-9-frontend-advanced-topics.md', 103 | SRC . '/chapter-10-knockout-scopes.md' 104 | ]; 105 | $appendices = [ 106 | SRC . '/appendix-areas.md', 107 | SRC . '/appendix-autoload.md', 108 | SRC . '/appendix-cache.md', 109 | SRC . '/appendix-cli.md', 110 | SRC . '/appendix-components.md', 111 | SRC . '/appendix-curl.md', 112 | SRC . '/appendix-di.md', 113 | SRC . '/appendix-frontend-build.md', 114 | SRC . '/appendix-install-module.md', 115 | SRC . '/appendix-interfaces.md', 116 | SRC . '/appendix-magento-modes.md', 117 | SRC . '/appendix-unix-find.md', 118 | SRC . '/appendix-view-source.md', 119 | ]; 120 | 121 | $raw = []; 122 | foreach($chapters as $file) 123 | { 124 | if(!in_array($file, $files)) 125 | { 126 | output($file . ' does not exist in src/, bailing'); 127 | exit; 128 | } 129 | 130 | $raw[] = file_get_contents($file); 131 | } 132 | 133 | $chapterAppendix = ["# Appendix\n\n"]; 134 | foreach($appendices as $appendix) 135 | { 136 | if(!in_array($file, $files)) 137 | { 138 | output($file . ' does not exist in src/, bailing'); 139 | exit; 140 | } 141 | $chapterAppendix[] = file_get_contents($appendix); 142 | } 143 | $raw[] = implode("\n\n", $chapterAppendix); 144 | $raw = implode("\n\n", $raw); 145 | 146 | 147 | $raw = preg_replace('/(^#[^#])/sim', ('\pagebreak' . "\n" . '$1'), $raw); 148 | file_put_contents('/tmp/working.md', $raw); 149 | 150 | $lines = file('/tmp/working.md'); 151 | buildSourceFiles($lines); 152 | 153 | echo `pandoc /tmp/working.md --toc -s -o output/No-Frills-Magento-2-Layout.tex`; 154 | // echo `pandoc /tmp/working.md -V documentclass=book -V classoption=oneside --template nofrills --toc -s --listings -o output/No-Frills-Magento-2-Layout.tex`; 155 | // echo `pandoc /tmp/working.md -o new.pdf --from markdown --template eisvogel --listings --toc -s -o output/No-Frills-Magento-2-Layout.tex`; 156 | // echo `pandoc output/No-Frills-Magento-2-Layout.tex -V documentclass=book -V classoption=oneside --template nofrills --toc -s --listings --latex-engine=xelatex -o output/No-Frills-Magento-2-Layout.pdf `; 157 | echo `pandoc --data-dir ./ output/No-Frills-Magento-2-Layout.tex -V documentclass=book -V classoption=oneside --template nofrills --toc -s --listings --pdf-engine=xelatex -o output/No-Frills-Magento-2-Layout.pdf`; 158 | echo `pandoc /tmp/working.md --toc -s -o output/No-Frills-Magento-2-Layout.html `; 159 | echo `pandoc /tmp/working.md --toc -s -o output/No-Frills-Magento-2-Layout.epub`; 160 | echo `pandoc /tmp/working.md --toc -s -o output/No-Frills-Magento-2-Layout.epub3`; 161 | 162 | //echo `tar -cvf output/Pulsestorm_Nofrillslayout.tar -C /Users/alanstorm/Sites/magento-2-1-0.dev/project-community-edition app/code/Pulsestorm/Nofrillslayout`; 163 | $date = date('Y-m-d-H-i-s',time()); 164 | $zip = $date . '.zip'; 165 | echo `zip -r $zip output`; 166 | 167 | $result = `wc -w /tmp/working.md`; 168 | $parts = preg_split('%\s{1,1000}%', trim($result)); 169 | $word_count = array_pop($parts); 170 | 171 | $word_count = preg_split('%\s{1,100}%', trim($result)); 172 | 173 | $word_count = array_shift($word_count); 174 | 175 | $cmd = "echo \"$date $word_count\" >> wordcount.txt"; 176 | `$cmd`; 177 | readfile('wordcount.txt'); 178 | // echo `cat wordcount.txt`; 179 | } 180 | pestle_cli([], []); -------------------------------------------------------------------------------- /magento-2/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astorm/magento-layout-no-frills/73ca6d82cd020929c5c0a1baae0fad5c821d56e2/magento-2/src/.DS_Store -------------------------------------------------------------------------------- /magento-2/src/_url_writing.md: -------------------------------------------------------------------------------- 1 | Let's consider a Magento front end asset URL, broken out by segment. 2 | 3 | http://magento.example.com #domain name 4 | /pub/static #base public asset path 5 | /version1514092162 #version slug 6 | /frontend/Magento/luma #magento area (frontend, adminhtml, etc.) 7 | /en_US #theme identifier 8 | /Package_Module #module identifier (optional) 9 | /path/to/file.css #asset path 10 | 11 | ### Domain Name 12 | 13 | The domain name is your website's configured domain name. It may seem obvious and redudant to mention this, but Magento does allow you to configure a domain name to use site wide at 14 | 15 | ... 16 | 17 | Subtle differences between what you think your site's URL is and what it actually is (https vs. http, www vs. non-www) can sometimes cause problems with your assets, so be sure you know what's going on with your system here. 18 | 19 | ### Base Public Path 20 | 21 | Next we have the base publiasset c path. As mentioned throughout this book, this path will vary dependingo on whether you've configured your webserver to use Magento root `index.php` file, or the `pub/index.php` file. 22 | 23 | ### Version Slug 24 | 25 | The version slug may be a little confusing, and almost certainly features a different number in your specific Magento system. This is here strictly as a "cache busting" URL. Modern browsers can be aggressive about caching CSS, Javascript, and other frontend assets. This caching is problematic if you're launching new versions of these files on a regular basis. By injecting this extra portion in an asset's URL, Magento tricks the browser into thinking its a new file, and the old cached version will be bypassed. 26 | 27 | ### Magento Area 28 | 29 | The portion of the URL is the Magento area. Different areas (the `frontend` cart, the back office `adminhtml`) may have a javascript/css file with the same name and path, but with different contents. 30 | 31 | ### Theme Identifier 32 | 33 | The portion of the URL is your theme's package name (`Magento` above) and your theme name (`luma`). This segment needs to be here since Magento's theming system allows you to replace specific frontend asset files. 34 | 35 | ### Locale 36 | 37 | The portion of the URL is the locale, or language, identifier for a site. It may seem a little excessive to allow different locales to have different CSS and Javascript files, but if you cnosider things like CSS `:after` text, or the need to localize string constants in UI libraries, it makes sense. 38 | 39 | ### Asset Path 40 | 41 | Finally, we have the path to the asset 42 | 43 | ### Module Name (optional) 44 | 45 | If your file is a part of a module (as opposed to being a part of a theme), this portion of the URL is the `Packagename_Modulename` module identifier for the module where the asset is located. 46 | 47 | ## Turning URLs into Paths 48 | 49 | Magento will take the above URL and transform it into to a file path. For example, this URL for the stock Magento `style-m.css` file 50 | 51 | http://magento.example.com 52 | /pub/static 53 | /version1514092162 54 | /frontend 55 | /Magento 56 | /luma 57 | /en_US 58 | /css 59 | /styles-m.css 60 | 61 | corresponds to the following file path 62 | 63 | $ ls -lh ./pub/static/frontend/Magento/luma/en_US/css/styles-m.css 64 | -rw-rw-r-- 1 _www staff 334K Dec 23 21:09 ./pub/static/frontend/Magento/luma/en_US/css/styles-m.css 65 | 66 | That is, Magento takes each segment (minus the version slug) and treats it as a path on your file system. 67 | 68 | Some of you may be scratching your head -- we never created a `styles-m.css` file and putting it in the `pub/static` folder. How did these files get here? 69 | 70 | Here's a quick experiment that will help clear that up. You'll need to be in developer mode for this to work. 71 | 72 | First, lets url `curl` to check Magento can download `styles-m.css`. We'll use `curl`'s `-I` modifier to look at the HTTP response headers, but you can also just load the URL directly in a browser 73 | 74 | curl -I 'http://magento-2-2-x.dev/pub/static/version1514092162/frontend/Pulsestorm/dram/en_US/css/styles-m.css' 75 | HTTP/1.1 200 OK 76 | //... 77 | 78 | So, that's a `200 OK` code -- that means the file's there. Next, let's **remove** `styles-m.css` 79 | 80 | $ rm ./pub/static/frontend/Magento/luma/en_US/css/styles-m.css 81 | 82 | With the file removed, lets try downloading it again. We'd expect to get a `404 Not Found` error -- except 83 | 84 | $ curl -I 'http://magento.example.com/pub/static/version1514092162/frontend/Pulsestorm/dram/en_US/css/styles-m.css' 85 | HTTP/1.1 200 OK 86 | //... 87 | 88 | The URL still serves the file! What's going on. 89 | 90 | You first though may be that we've told you an un-ture thing, and that the `styles-m.css` file we pointed you at isn't the file that Magento's serving. At least, that's what I thought the first time I encountered this behavior. However, if you take a look at your file system again 91 | 92 | $ ls -lh ./pub/static/frontend/Magento/luma/en_US/css/styles-m.css 93 | -rw-rw-r-- 1 _www staff 334K [today] ./pub/static/frontend/Magento/luma/en_US/css/styles-m.css 94 | 95 | You'll see that **something** has recreated the file for us! 96 | 97 | Static Asset Serving 98 | -------------------------------------------------- 99 | When you deploy a Magento system to production, you need to run the following command 100 | 101 | $ php bin/magento setup:static-content:deploy 102 | 103 | This command looks though all Magento's module's and themes for frontend assets, and creates them in the `pub/static` folder file hierarchy we discussed above. 104 | 105 | While this is an OK solution for a production system -- **developing features** under this system would be incredibly tedious and time consuming. Change a file, deploy site, wait, whoops that wan't it, repeat. To combat this problem, Magento deploys frontend assets **on demand** when you're running in developer mode. 106 | 107 | If we take a look inside the `pub/static` folder, we'll find an `.htaccess` file 108 | 109 | #File: pub/static/.htaccess 110 | # ... 111 | 112 | RewriteEngine On 113 | 114 | # Remove signature of the static files that is used to overcome the browser cache 115 | RewriteRule ^version.+?/(.+)$ $1 [L] 116 | 117 | RewriteCond %{REQUEST_FILENAME} !-f 118 | RewriteCond %{REQUEST_FILENAME} !-l 119 | 120 | RewriteRule .* ../static.php?resource=$0 [L] 121 | 122 | # ... 123 | 124 | This rewrite rule takes every request for a file in a `pub/static/version*` folder and, if the file doesn't already exist, routes the request to the program in `static.php`. In other words, a request for this URL 125 | 126 | http://magento-2-2-x.dev/pub/static/version1514092162/frontend/Pulsestorm/dram/en_US/css/styles-m.css 127 | 128 | is **actually** a request for 129 | http://magento-2-2-x.dev/pub/static.php?resource=frontend/Pulsestorm/dram/en_US/css/styles-m.css 130 | 131 | This `pub/static.php` program is Magento's static asset server. Its job is to use the `resource` parameter to find a frontend asset file in Magento's themes and modules, save that file to disk for future requests, and return the file. 132 | 133 | This `.htaccess` file is also the place where the `version...` slug is stripped out of the URL. 134 | 135 | For folks using nginx, Magento has a sample configuration with similar rules 136 | 137 | #... 138 | 139 | location ~ ^/static/version { 140 | rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last; 141 | } 142 | 143 | #... 144 | 145 | if (!-f $request_filename) { 146 | rewrite ^/static/?(.*)$ /static.php?resource=$1 last; 147 | } 148 | 149 | #... 150 | 151 | Be careful with your nginx configuration -- it's not uncommon for engineers to remember one of these rules, but forget the other. If you're not seeing frontend assets, this is the first place to look. 152 | 153 | ## The Static Asset Server 154 | 155 | If we take a look at `static.php` 156 | 157 | #File: pub/static.php 158 | require realpath(__DIR__) . '/../app/bootstrap.php'; 159 | $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER); 160 | /** @var \Magento\Framework\App\StaticResource $app */ 161 | $app = $bootstrap->createApplication(\Magento\Framework\App\StaticResource::class); 162 | $bootstrap->run($app); 163 | 164 | We see that Magneto bootstraps and runs an independent application. This is similar (but simpler) to what happens in Magento's `index.php` file. If we take a look at that application's source file, we can see the main work of the application in the `launch` method (which is eventually called after the `run` method above) 165 | 166 | #File: vendor/magento//framework/App/StaticResource.php 167 | public function launch() 168 | { 169 | // disabling profiling when retrieving static resource 170 | \Magento\Framework\Profiler::reset(); 171 | $appMode = $this->state->getMode(); 172 | if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION) { 173 | $this->response->setHttpResponseCode(404); 174 | } else { 175 | $path = $this->request->get('resource'); 176 | $params = $this->parsePath($path); 177 | $this->state->setAreaCode($params['area']); 178 | $this->objectManager->configure($this->configLoader->load($params['area'])); 179 | $file = $params['file']; 180 | unset($params['file']); 181 | $asset = $this->assetRepo->createAsset($file, $params); 182 | $this->response->setFilePath($asset->getSourceFile()); 183 | $this->publisher->publish($asset); 184 | } 185 | return $this->response; 186 | } 187 | 188 | We're not going to dive deep into this program, but here's a few lines worth paying attention to. 189 | 190 | if ($appMode == \Magento\Framework\App\State::MODE_PRODUCTION) { 191 | $this->response->setHttpResponseCode(404); 192 | } 193 | 194 | If Magento detects you're in production mode, it automatically returns a 404. Magento still needs to use the `.htaccess` rules from above to strip the `version...` string from URLs, but doesn't want to dynamically server files in production mode for performance and security reasons. 195 | 196 | These three lines 197 | 198 | $asset = $this->assetRepo->createAsset($file, $params); 199 | $this->response->setFilePath($asset->getSourceFile()); 200 | $this->publisher->publish($asset); 201 | 202 | are where the bulk of the work happen. The `createAsset` method is what does most of the work in using that `resource` path to find an actual file. The call to `setFilePath` on the response object is what tells Magento how to send the front end file to the browser **for this request only**. The call to `publish` on the `publisher` object is what saves the file to the `pub/static` folder. 203 | 204 | In an ideal world, you wouldn't need to be aware of this file. However -- if there's a bug in the static asset serving application, you may need to learn the finer points of debugging to fix it. Also, if your file permissions aren't set correctly Magento may not be able to create the file in your `pub/static` folder. Beyond being annoying, the large number of Javascript files Magento needs means there are dozens of requests to this program when you first start using a Magento system. 205 | 206 | Only using the static asset serving application is not a viable development strategy -- if your system is behaving super slow even with Magento caches on, you may want to look into the performance of this application. -------------------------------------------------------------------------------- /magento-2/src/appendix-areas.md: -------------------------------------------------------------------------------- 1 | ## Magento 2 Areas 2 | 3 | Areas were a tricky concept to understand in Magento 1, and remain so in Magento 2. To understand areas, you need to consider **how** web applications are typically built. Consider 4 | 5 | 1. A URL 6 | 2. A web application that lives at that URL 7 | 3. A web application that has several distinct features living at sub-URLs 8 | 4. And those features each require a different set of assets and resources 9 | 10 | Magento's area system uses the current URL to identify which "area" of an application a user is in, and uses that area to load different assets and resources. For example, when you're on a site's homepage, or on the cart checkout page, your URL might look like the following. 11 | 12 | http://magento.example.com/ 13 | http://magento.example.com/checkout 14 | 15 | These are URLs in the `frontend` area. However, when you're looking at the back office 16 | 17 | http://magento.example.com/admin/admin/dashboard/index 18 | 19 | you're in a different area named `adminhtml`. 20 | 21 | Areas are important to front end developers because each area loads a *different* set of layout handle XML files, and a different set of front end asset files. For example, in the catalog module you can find the `phtml` files for the `frontend` cart application in the following folder 22 | 23 | //notice the "frontend" path portion 24 | 25 | vendor/magento/module-catalog/view/frontend/templates/ 26 | 27 | while the files for the back office `adminhtml` area are in a different folder. 28 | 29 | vendor/magento/module-catalog/view/adminhtml/templates/ 30 | 31 | When Magento need to load a template URN like the following 32 | 33 | Magento_Catalog::path/to/template.phtml 34 | 35 | the base folder it uses will be determined by the application's current area. 36 | 37 | ### Base Area Folders 38 | 39 | One problem with the area system in Magento 1 was the inability to easily share assets between two areas. For example, as an extension or theme developer you might want to share a `phtml` template with both a back office `adminhtml` page **and** and `frontend` cart page. 40 | 41 | To solve this problem, Magento 2 introduced the idea of a `base` area. Assets placed in the base folder are available to **both** areas. 42 | 43 | For example, if Magento tries to expand the `Magento_Catalog::path/to/template.phtml` URN out to a full file path in the `frontend` cart application, Magento will check for a file in the following location first 44 | 45 | vendor/magento/module-catalog/view/frontend/templates/path/to/template.phtml 46 | 47 | If it doesn't find a file there, Magento will check the the `base` area folder next. 48 | 49 | vendor/magento/module-catalog/view/base/templates/path/to/template.phtml 50 | 51 | ### Programmatically Determining the Area 52 | 53 | Another way Magento 2 improves the area system is a more straightforward mechanism for programmatically checking the current area code. The `Magento\Framework\App\State` single instance object keeps track of the area code. If you use this class in an automatic constructor dependency injection constructor, you can easily check the current area 54 | 55 | public function __construct( 56 | \Magento\Framework\App\State $appState 57 | ) 58 | { 59 | $this->appState = $appState; 60 | } 61 | /* ... */ 62 | public function someMethod() 63 | { 64 | var_dump( 65 | $this->appState->getAreaCode() 66 | ); 67 | } 68 | 69 | Each sub-system in Magento handles areas a little bit differently. We'll cover the specifics as we come across them -- this appendix was meant as a gentle introduction to the topic, and as a way to cover changes to the area system in Magento 2. -------------------------------------------------------------------------------- /magento-2/src/appendix-autoload.md: -------------------------------------------------------------------------------- 1 | ## PHP Autoloading 2 | 3 | Autoloading is the PHP system that ensures when a developer attempts to instantiate an object from a class, that the correct class definition file is loaded. 4 | 5 | All programming languages have some sort of mechanism for this -- what makes PHP distinct is the autoloading system is end-user-programmer configurable. That is to say, anyone writing PHP code can register an autoloader that might run when another programmer attempts to instantiate a class. 6 | 7 | Taking the long historic view, this has led to autoloaders from early PHP frameworks not playing nice with each other when used in the same program. An autoloader from framework A might fail when a programmer attempts to load a class from framework B. 8 | 9 | In recent years, the PHP community has standardized its autoloading mechanism using the PSR-0 and PSR-4 standards. These standards were adopted by Composer, which means most modern Composer distributed frameworks (Magento 2 included) use the PSR based Composer autoloaders. 10 | 11 | However, as a working PHP programmer, it's still necessary to understand the mechanics of autoloading. Older PHP frameworks still use older, non PSR based autoloaders in their Composer packages. Additionally -- Composer's autoloader API offers an irresistible temptation for meta-programmers who want to hook into class instantiation in PHP based systems. 12 | 13 | This appendix will describe Magento's PSR-4 based autoloaders. It will also describe a few ways in which Magento uses the autoloader system to implement functionality unrelated to class autoloading. 14 | 15 | ### PSR-4 Autoloading 16 | 17 | A PSR-4 autoloader allows a user to configure a class prefix with a path name. When PHP needs to instantiate classes with this prefix, the autoloader will look for class files in the configured folder. The autoloader uses the non prefixed portion of the class to build the path's full class. 18 | 19 | Here's an example. A user might configure the class prefix `Foo\Bar` with the path `path/to/src`. Then, if someone tried to instantiate a class like this 20 | 21 | $object = new \Foo\Baz\Bar\Bap; 22 | 23 | The PSR autoloader would look for the class's definition file in 24 | 25 | path/to/class/Bar/Bap.php 26 | 27 | The autoloaders would not try to load a class named `Baz\Bar\Foo`, because this class does not start with the configured prefix `Foo\Bar`. 28 | 29 | A PSR-4 autoloader creates the path to the class file by starting with the configured path name, and transforming the non-prefix part of the class name (`Bar\Bap`). This transformation includes turning the namespace separator characters into file path separators, and appending a `.php` file extension. 30 | 31 | There's some additional subtleties and rules to PSR-4 autoloading. If you're interested in learning more you should checkout the PSR-4 specification 32 | 33 | http://www.php-fig.org/psr/psr-4/ 34 | 35 | ### PSR-4 Autoloading in Composer and Magento 36 | 37 | Here's how PSR-4 autoloading works in Magento 2 with Composer. In most cases, a Magento 2 module will configure a PSR-4 autoloader in its composer.json file. For example, consider the `Magento_Catalog` module 38 | 39 | #File: vendor/magento/module-catalog/composer.json 40 | 41 | "autoload": { 42 | /* ... */, 43 | "psr-4": { 44 | "Magento\\Catalog\\": "" 45 | } 46 | } 47 | 48 | As you can see above, Magento's configured a PSR-4 autoloader with a class prefix of `Magento\Catalog`, and an empty path. This is a standard Composer PSR-4 autoloader configuration. The empty path setting means *from this Composer package's root folder*. In other words, Magento 2 will load the `Magento\Catalog\Model\Product` class from 49 | 50 | vendor/magento/module-catalog/Model/Product.php 51 | 52 | This is the pattern Magento follows for all its core modules. Third party developers are not required to follow this pattern, but it's strongly recommended they do so. 53 | 54 | ### Autoloader Module Registration 55 | 56 | Earlier we mentioned some frameworks, Magento included, use the autoloader and autoloader related systems to implement other functionality. 57 | 58 | Magento needs a way to know which modules are available in a system. Rather than keep a list of modules somewhere in application state, or scan common module directories on every system bootstrap, Magento uses registration.php files. These files are located in the root of each Magento module folder (as well as theme, library, and language pack folders) 59 | 60 | Rather than perform a search for these files on every bootstrap, Magento taps into the power of Composer's `files` autoload feature. Consider, again, the `Magento_Catalog` module. 61 | 62 | #File: vendor/magento/module-catalog/composer.json 63 | 64 | "autoload": { 65 | "files": [ 66 | "registration.php" 67 | ], 68 | /* ... */ 69 | } 70 | 71 | The original intent of the `files` autoloader is that developers would use a file autoload to manually setup PHP autoloading for the framework with `__autoload` or `spl_autoload_register`, or that they would simply list the class files that should be automatically loaded here. 72 | 73 | However, because PHP loads a file configured in the `files` autoloader on every PHP request, this is a tempting place for framework authors to put other initializations and registration scripts. Magento could not resist this temptation themselves -- if you look inside a registration.php file 74 | 75 | #File: vendor/magento/module-catalog/registration.php 76 | getCodeGenerator()); 107 | spl_autoload_register([$autoloader, 'load']); 108 | return new Runtime(); 109 | } 110 | 111 | and you can start following the autoloader's execution here 112 | 113 | #File: vendor/magento/framework/Code/Generator/Autoloader.php 114 | public function load($className) 115 | { 116 | if (!class_exists($className)) { 117 | return Generator::GENERATION_ERROR != $this->_generator->generateClass($className); 118 | } 119 | return true; 120 | } 121 | 122 | There's a number of different file types Magento will generate for you with this autoloader 123 | 124 | #File: vendor/magento/magento2-base/app/etc/di.xml 125 | 126 | \Magento\Framework\ObjectManager\Code\Generator\Factory 127 | \Magento\Framework\ObjectManager\Code\Generator\Proxy 128 | \Magento\Framework\Interception\Code\Generator\Interceptor 129 | \Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger 130 | \Magento\Framework\Api\Code\Generator\Mapper 131 | \Magento\Framework\ObjectManager\Code\Generator\Persistor 132 | \Magento\Framework\ObjectManager\Code\Generator\Repository 133 | \Magento\Framework\ObjectManager\Code\Generator\Converter 134 | \Magento\Framework\Api\Code\Generator\SearchResults 135 | \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator 136 | \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator 137 | 138 | 139 | However, be careful. Just because Magento shipped a code generating autoloader doesn't mean that the autoloader is ready for the outside world (or even the inside world) to use. 140 | -------------------------------------------------------------------------------- /magento-2/src/appendix-cache.md: -------------------------------------------------------------------------------- 1 | ## The Magento Cache 2 | 3 | The concept of a *cache* in programming is a relatively simple one. However, as time goes on, the *practice* of caching has become more and more complicated. 4 | 5 | Caching is the process of 6 | 7 | 1. Doing something computationally intensive or time consuming. 8 | 2. Saving the result. 9 | 3. Using the saved result the next time you need that same thing. 10 | 11 | Caching is a popular solution for performance problems because it allows developers to solve their problem without worrying about performance up-front. In isolation, this may seem lazy. However, considered in the life of a working programmer who is writing new algorithms everyday, and who never knows which ones need to be performant and which ones do not, caching is often the only solution that makes sense. Deciding what to cache, when, and for how long is a fundamental part of modern systems development. 12 | 13 | Magento 1 featured an infamous number of caches. Magento 2 has kept all of these, and added a few new layers on top. 14 | 15 | You can see identifiers (also known as *tags*) for each of Magento's cache types by using the `cache:status` CLI command 16 | 17 | $ php bin/magento cache:status 18 | config: 1 19 | layout: 1 20 | block_html: 1 21 | collections: 1 22 | reflection: 1 23 | db_ddl: 1 24 | eav: 1 25 | customer_notification: 1 26 | full_page: 0 27 | config_integration: 1 28 | config_integration_api: 1 29 | translate: 1 30 | config_webservice: 1 31 | 32 | 33 | Covering what each of these cache types does is beyond the scope of this book. We will, however, briefly cover a few front end related caches. We'll also cover some things not on this list, but that are cache-like systems you'll need to be aware of when working with Magento 2. Finally we'll cover clearing these caches via formal, and informal, means. 34 | 35 | #### layout 36 | 37 | The `layout` cache stores pre-built XML configuration trees for *layout related XML files*. This means files in your module and theme's `view` folder, and **not** files in your `etc` folder. 38 | 39 | #### block_html 40 | 41 | Most `phtml` templates in Magento have a corresponding PHP Block class. A block class author can, if they wish, configure these blocks to be cached. That is, they'll render once using `phtml` code and block class methods, but the next render will simply pull the previous output from cache. 42 | 43 | Magento's category navigation block is a prominent example of this -- as querying a large category list is often a computationally complex action. 44 | 45 | #### full_page 46 | 47 | The full page cache is a new cache type introduced in Magento 2. The full page cache will cache the results of individual Magento page requests to disk. This means with full page caching enabled, the first request for a Magento page will use Magento's controllers and layout system to build the page's output and save the page to cache before serving it. The next request will skip these subsystems, opting to serve the page from the cache. 48 | 49 | This feature existed in Magento 1's enterprise versions, and Magento 1 CE had many third party full page caching extensions available. Because this feature ships in all versions of Magento 2, module and theme developers will need to test their feature both with full page caching enabled, and full page caching disabled. 50 | 51 | Although this cache type is grouped with Magento's others, and you're able to use standard cache commands to manage (i.e. clear) the full page cache, Magento **does not** store these cached pages in the standard cache storage. Instead, full page cache files are (by default) stored in the 52 | 53 | var/page_cache 54 | 55 | folder. Finally, it's worth noting that some Magento team members have stated the stock full page cache behavior is intended as a demo, and that it shouldn't be used in production. Regardless of how you decide to deploy, you'll want to be aware of full page cache while you're developing or distributing code to developers who may run with this mode enabled. 56 | 57 | ### Full Page Cache with Varnish 58 | 59 | By default, Magento's full page cache stores its cached pages on disk, in the `var/page_cache` folder. However, it's possible to configure Magento to use varnish for its full page cache. Varnish is a web server proxy whose sole job is to save pre-rendered HTTP responses (HTML pages, XML files, JSON files, etc.) 60 | 61 | You can "turn on" varnish by navigating to 62 | 63 | Stores -> Configuration -> Advanced -> Full Page Cache 64 | 65 | Magento's varnish implementation will generate a varnish VCL file for you to use with your varnish system. It will not setup or run varnish automatically for you. Magento 1 had no official varnish support, but if you've ever used the Magento 1 Nexcess Turpentine extension you'll feel right at home. Per our previous comments on Magento not recommending full page caching on disk (the default behavior) for production sites, Magento **does** recommend you run your stores behind varnish proxy servers. 66 | 67 | If you're interested in running varnish and don't know how, you'll need to check with your server infrastructure team/partners. 68 | 69 | ### LessCSS Caches 70 | 71 | Magento uses a front end tool called LessCSS to generate its cross browser CSS files. On the fly rendering of LessCSS files is another place where you can benefit from a caching system. 72 | 73 | Magento stores its LessCSS caches in 74 | 75 | var/view_preprocessed 76 | 77 | If you're making changes to LessCSS files, you may need to clear out this folder to see your changes. 78 | 79 | There's no `bin/magento` command to clear out these LessCSS caches. However, Magento does ship with grunt tasks that will clear out *some* of the LessCSS caches. See the Front End Build System appendix for more details. 80 | 81 | ### Front End Files (Static Assets) 82 | 83 | Magento's front end asset files (CSS, JavaScript, etc.) are, for the most part, generated on the fly. As previously mentioned, CSS files are generated by LessCSS. JavaScript files, while not generated, are stored with Magento's modules and moved *on demand* to the `pub/static` folder. By on demand, we mean as a user requests them, or when you deploy your Magento system (using the `setup:static-content:deploy` command). 84 | 85 | ### Other Cache Entries 86 | 87 | Keep in mind that Magento's caching objects are available for third party extension developers to use however they want. Even if you clear **all** the identifiers listed above, another developer may have tagged a cache entry with their own cache tags and not one of the 13 Magento cache types. For these cases, Magento offers a Flush Cache Storage option, available at 88 | 89 | System -> Tools -> Cache Management 90 | 91 | or 92 | 93 | $ php bin/magento cache:flush 94 | 95 | This will clear Magento's primary cache storage engine of all entries. 96 | 97 | ### Notes on Clearing Cache 98 | 99 | Throughout this book, we'll try to remind you when you'll need to clear your Magento cache to see your changes show up. Magento's main cache storage is located (by default) in the 100 | 101 | var/cache 102 | 103 | folder. You can clear your cache by removing this entire folder. However -- it's also possible (and recommended) to configure Magento to use an in-memory caching solution like redis or memcache. Because of this, it's probably best to develop the habit of clearing your cache using the built in Magento command line command 104 | 105 | $ bin/magento cache:clean 106 | 107 | This will run through each of Magento's main cache types and clear them out. 108 | 109 | Another caveat -- if your full page cache engine is varnish, or another third party full page cache implementation, the above command may not clear this cache. Also, as previously mentioned, the LessCSS files and front end assets only behave like cached entries, they're not an official part of the Magento cache. 110 | 111 | Whenever you're facing a problem where it *seems* like you've edited the right file, but your changes aren't showing up, it's always worth reviewing which cache and cache-like systems may be in play, and take the additional steps of 112 | 113 | 1. Clearing those caches using the official tools 114 | 2. Moving on to clearing the storage directly (removing cache folder/files, deleting your redis key entries, etc. ) 115 | -------------------------------------------------------------------------------- /magento-2/src/appendix-cli.md: -------------------------------------------------------------------------------- 1 | ## The Command Line 2 | 3 | The "command line" is one of the oldest ways to run programs and communicate with your computer. Despite being a relic of another time, the command line remains popular for developers and other technical professionals who need programs that take clear inputs, and produce clear outputs. 4 | 5 | If you're unfamiliar with the command line, you can access it via your Linux or MacOS/OS X based computer by running a terminal program (included with the OS). Once you launch this program, the command line will just sit there, waiting for you to run a command 6 | 7 | $ 8 | 9 | Running a command line environment on a Windows computer is a slightly more complicated affair -- the windows command line is different in many ways from a unix/linux environment. Windows also offers the ability to connect to a \*nix based computer or virtual machine and run command line programs. We're going to assume you windows folks know what you're doing, or are smart enough to figure it out. i.e. this appendix will assume a \*nix environment. 10 | 11 | ### Running a Command Line Program 12 | 13 | To run a command line program, all you need to do is type that program's name, and hit enter. For example, the `ls` program will list a directory's current contents 14 | 15 | $ ls 16 | ... 17 | 18 | Command line programs can also, like functions in programming languages, accept arguments. For example, the `cd` command (which changes directories) accepts a single argument (the folder/directory you want to change to) 19 | 20 | $ cd /path/to/magento 21 | 22 | Command line programs also often accept options -- for example you can use the `-1` option with `ls` to get a single column listing of files 23 | 24 | $ ls -1 25 | 26 | Typically, you'll use a single dash is for one letter options, and two dashes for a full-word options. i.e. 27 | 28 | $ curl --progress-bar http://example.com 29 | 30 | The single letter options are a remnant of computer past, where every byte of memory was important. 31 | 32 | ### Magento CLI 33 | 34 | Many application frameworks include their own command line framework. These frameworks allow a programmer to create command line scripts in the language of the application framework and with easy access to the functions and methods (or, in today's vague parlance, the "API") of the application framework itself. 35 | 36 | Magento 2 includes a command line framework, and ships with many useful commands. To see a list of commands in the Magento command line framework, just run the following from your project's root folder 37 | 38 | $ php bin/magento list 39 | ... 40 | 41 | This command may require some explaining. First, the `php` portion is just us running the command line version of PHP. The command line version of PHP accepts an argument that's a path to the file to execute via php -- in this case, `bin/magento`. If you look in the `bin/magento` file 42 | 43 | #File: bin/magento 44 | 45 | #!/usr/bin/env php 46 | getMessage(); 61 | exit(1); 62 | } 63 | try { 64 | $handler = new \Magento\Framework\App\ErrorHandler(); 65 | set_error_handler([$handler, 'handler']); 66 | $application = new Magento\Framework\Console\Cli('Magento CLI'); 67 | $application->run(); 68 | } catch (\Exception $e) { 69 | while ($e) { 70 | echo $e->getMessage(); 71 | echo $e->getTraceAsString(); 72 | echo "\n\n"; 73 | $e = $e->getPrevious(); 74 | } 75 | exit(Magento\Framework\Console\Cli::RETURN_FAILURE); 76 | } 77 | 78 | Here we see the PHP code that bootstraps Magento's command line framework. The second argument to `php` (above, `list`) is *also* the first argument to the `bin/magento` command line script. Many command line programs use this "sub-command" pattern. For example, the git version control system has many sub-commands 79 | 80 | $ git add ... 81 | $ git status 82 | //etc... 83 | 84 | When you run the `list` command, you're telling Magento's command line framework to list out all the commands available 85 | 86 | Describing each Magento command in full is well beyond the scope of this appendix (or this book, or possibly any single book). However, here's an example of a command that will clear Magento's cache 87 | 88 | $ php bin/magento cache:clean 89 | 90 | And here's another command that will enable a module 91 | 92 | $ php bin/magento module:enable Foo_Bar 93 | 94 | You'll notice the `module:enable` command also accepts an argument -- `Foo_Bar`. It's arguments all the way down! You can see an example of the arguments, and options, supported by each command by using the `help` command 95 | 96 | $ php bin/magento help module:enable 97 | 98 | BE CAREFUL: Command line scripts are incredibly powerful, but they often come without guard rails. In addition, Magento often ships command line scripts that aren't as well tested as more common application code paths. A bug in a command line script or a misuse of a bug-free script could damage your system in a way that might take hours, or even days, to fix. Don't use a command line script that you don't understand (or that you don't find in a tutorial you trust), and it's always a good idea to test out a command that's new to you in a backed up development environment. 99 | 100 | Finally, as mentioned, these commands are just PHP code. For example, you can find the source to the `module:enable` command here 101 | 102 | vendor/magento/magento2-base/setup/src/Magento/Setup/Console/Command/ModuleEnableCommand.php 103 | -------------------------------------------------------------------------------- /magento-2/src/appendix-components.md: -------------------------------------------------------------------------------- 1 | ## Magento 2 Components 2 | 3 | In Magento 1, the idea of modules, themes, libraries, and language packs all got a little blurry around the edges. Magento 2 attempts to make these distinctions a bit clearer. Specifically, while Magento 2 still has code modules, themes, code libraries, and language packs, there's a higher level idea of a Magento Component that sits above all of them. 4 | 5 | ### What is a Component 6 | 7 | To start, a "naming things is hard" note. Magento Components and UI Components are two different things. We're talking about Magento Components here, so if you know anything about the UI Component system, check that knowledge at the door. Don't worry, it'll be there when you get back. 8 | 9 | A Magento Component is, simply speaking, a logical collection of files in a folder hierarchy. A Magento Component is identified by a `registration.php` file in the top level folder of this hierarchy. 10 | 11 | For example, consider the following file 12 | 13 | #File: vendor/magento/theme-frontend-blank/registration.php 14 | \Magento\Framework\Component\ComponentRegistrar::register( 15 | \Magento\Framework\Component\ComponentRegistrar::THEME, 16 | 'frontend/Magento/blank', 17 | __DIR__ 18 | ); 19 | 20 | The files in `vendor/magento/theme-frontend-blank` are part of the blank theme that ships with Magento 2. This `registration.php` identifies the files in this folder as part of this theme. Each `registration.php` contains a call to the static `Magento\Framework\Component\ComponentRegistrar::register` method which 21 | 22 | 1. Identifies the Component type 23 | 2. Provides an identifier for the Component 24 | 3. Provides a path to the Component's files 25 | 26 | So, above, the Component is identified as a theme via the class constant 27 | 28 | \Magento\Framework\Component\ComponentRegistrar::THEME 29 | 30 | Its identifying string is `frontend/Magento/blank`, and the code uses the `__DIR__` magic constant to identify the current directory as the folder that contains this Component's files. Regarding `__DIR__`, while it's technically possible to point to another folder, the Magento convention is to always use this constant. Veering from this may result in unexpected behavior. 31 | 32 | ### A Module Component 33 | 34 | Let's look at another Component to make sure we understand `registration.php`. Consider the following file 35 | 36 | #File: vendor/magento/module-catalog/registration.php 37 | \Magento\Framework\Component\ComponentRegistrar::register( 38 | \Magento\Framework\Component\ComponentRegistrar::MODULE, 39 | 'Magento_Catalog', 40 | __DIR__ 41 | ); 42 | 43 | This folder contains files for the catalog code module. We know this Component is a module because of the following class constant. 44 | 45 | \Magento\Framework\Component\ComponentRegistrar::MODULE 46 | 47 | This module's identifier is `Magento_Catalog`, and (as recommended) the location of its files are the current directory, indicated via `__DIR__`. 48 | 49 | You can see an example of a code library here 50 | 51 | #File: vendor/magento/framework/registration.php 52 | \Magento\Framework\Component\ComponentRegistrar::register( 53 | \Magento\Framework\Component\ComponentRegistrar::LIBRARY, 54 | 'magento/framework', 55 | __DIR__ 56 | ); 57 | 58 | and a language/translation pack here 59 | 60 | #File: vendor/magento/language-de_de/registration.php 61 | \Magento\Framework\Component\ComponentRegistrar::register( 62 | \Magento\Framework\Component\ComponentRegistrar::LANGUAGE, 63 | 'magento_de_de', 64 | __DIR__ 65 | ); 66 | 67 | Magento treats the files in each of these folders differently -- but they're all Magento Components. 68 | 69 | ### How Magento loads Components 70 | 71 | This, of course, leads to the $64,000 question: How does Magento see, or load, these Components. In Magento 1, modules were loaded via files in 72 | 73 | app/etc/modules 74 | 75 | and themes were loaded by editing values in the `System -> Configuration -> Design` sections and added to via layout XML files configured in a module's `config.xml` file. Magento 1's single code library lived in `lib/`, and Magento scanned for language packs in a hard coded folder. Like we said -- things get blurry at the edges. 76 | 77 | One of the goals of the Magento Component system is to remove that blurriness. Another is to enable distribution of these Components via PHP Composer. If you downloaded Magento 2 as an archive, you may wonder why most of its code files are located in the `vendor/magento` folder. The `vendor` folder is where Composer installs files to by default. 78 | 79 | So, if Magento's code files are (mostly) in `vendor` -- how does Magento see them? That happens thanks to the magic of Composer's "file autoload" feature. 80 | 81 | 1. Each Composer package has a composer.json file 82 | 2. One of the things this file lets you do is run a small PHP script on every page load for a Composer based project 83 | 3. The original intent of this script was to allow packages to setup their own PHP Autoloader (via PHP's `spl_autoload_register` function) 84 | 4. Magento has hijacked this functionality to register Components 85 | 86 | If you're interested in learning more about autoloading, the autoloading appendix is a good place to start, and this online article can provide you with an in-depth exploration of Composer's autoloading mechanisms 87 | 88 | http://alanstorm.com/laravel\_composer\_autoloading/ 89 | 90 | Let's take another look at the catalog module -- but this time, we'll look at its `composer.json` file. 91 | 92 | #File: vendor/magento/module-catalog/composer.json 93 | { 94 | /* ... */ 95 | "autoload": { 96 | "files": [ 97 | "registration.php" 98 | ], 99 | /* ... */ 100 | } 101 | } 102 | 103 | We've highlighted the section we're interested in. This `autoload.files` configuration tells Composer to load the `registration.php` files located in the root folder of this module. This is the same `registration.php` we viewed earlier. 104 | 105 | By creating their `composer.json` files like this, Magento has ensured that as soon as Composer's autoloader finishes loading, that PHP will have called `Magento\Framework\Component\ComponentRegistrar::register` for all the Components that are currently installed via Composer. 106 | 107 | While clever, and powerful, this does mean that Magento 2 is tied to Composer in a way that other PHP projects with traditional architectures aren't. 108 | 109 | ### Non-Composer Components 110 | 111 | This also raises a few important questions -- is it possible to install Magento Components **without** relying on Composer? Can we work on projects without needing to redeploy code to a Composer package every time we want to see a change? 112 | 113 | Fortunately, the answer to both is yes. In addition to the above `composer.json` mechanism, Magento will scan certain folders for `registration.php` files, and load those as well. This scanning happens in the following file 114 | 115 | #File: app/etc/NonComposerComponentRegistration.php 116 | 28 | 31 |