Examining Magento's final XML structure - magento

Anyway to examine the final XML structure magento comes up with after parsing & combining all the different XML files?
There is nothing of that sort which turned up on searching on the internet and I think for someone like me, magento layouts were a bit too much in the beginning & I would try to do everything on the code side.
Another thing which will help in picking up the name of different nodes that we can use, right away from the final XML structure.
Never ran into this but I believe we will have a better picture of what's overriding what.

The following will get you the merged configuration from app/etc/*.xml, app/etc/modules/*.xml, as well as each (active) module's config.xml file; when retrieving the config though there is no indication of what was overwritten, as the merges happen as each config file is being parsed:
Mage::getConfig()->getNode()->asNiceXml(); // or asXML() | asArray() | etc.
However, you seem to be asking about how the application makes use of this information. This is a function of application design.
Also, you mention "all of the different XML files." It's worth noting that these are not maintained in one massive object instance. For example, layout XML is accessed using the layout update object Mage_Core_Model_Layout_Update and can be accessed meaningfully after it's been loaded and manipulated for a given rendering scope (e.g. loadLayout() in a controller action):
Mage::app()->getLayout()->getUpdate()->asString(); // or asSimplexml() or asArray()

Yes - Commercebug. As well as a whole load of other useful features, you can also view the entire XML structure that Magento has produced.
http://store.pulsestorm.net/products/commerce-bug-2

I believe the following will output the XML: echo Mage::getConfig()->getXmlString();
You can create a script with something like this:
header("Content-Type:text/xml");
require_once '../app/Mage.php';
Mage::app();
echo Mage::getConfig()->getXmlString();

based on answer from benmarks I did
echo "<pre>".htmlspecialchars(Mage::getConfig()->getNode()->asNiceXml())."</pre>";
If you want for example to see the blocks configuration in Magento 1 you can put this in a file, place the file at the root of the site and navigate to it in a browser:
<?php
include("app/Mage.php");
Mage::app();
//just see blocks...
echo "<pre>".htmlspecialchars(Mage::getConfig()->getNode()->global->blocks->asNiceXml())."</pre>";
die();

Related

Where do I find the contents of $this->getAbsoluteFooter() Magento

I'm struggling to find what this calls '$this->getAbsoluteFooter()' or where it's contents are.
Is it a template file?
The reason I ask is because my site was hacked with a js injection in the footer. Disabling $this->getAbsoluteFooter() removed the injection so I'm anxious to find the source.
I've Googled it and the only thing I can find is someone asking the same question.
Thanks.
You've been hacked which means this could be anywhere, so keep that in mind when this doesn't work for you.
The getAbsoluteFooter method is normally defined in the following file.
#File: app/code/core/Mage/Page/Block/Html.php
public function getAbsoluteFooter()
{
return Mage::getStoreConfig('design/footer/absolute_footer');
}
In a normal system, the getStoreConfig method will return the value stored in core_config_data for the passed in path (design/footer/absolute_footer).
Of course, since you're hacked, the actual class file $this refers to in your template could be anywhere on the server (depending on the severity of your hack). Give the following a try to find the real file on your specific system
//$this->getAbsoluteFooter();
$r = new ReflectionClass($this);
var_dump($r->getFilename());
That should reveal the actual filename, which may be app/code/core/Mage/Page/Block/Html.php, or may be something else.
Good luck!
I found out that a code was injected in the database on the core_config_data table with path 'design/footer/absolute_footer';
More on https://magento.stackexchange.com/a/42529/57576
Ty

How to build CodeIgniter URL with hierarchy?

I know this doesn't exactly match the form of www.example.com/class/function/ID/, but what I want to display to the user would make more sense.
This is what I would like to do:
www.example.com/project/id/item/item_id/
So, an example would be:
www.example.com/project/5/item/198237/
And this would be the behavior:
www.example.com/project/ --> This would show a list of projects (current implementation)
www.example.com/project/5/ --> This would show a list of items on project 5 (current implementation)
www.example.com/project/5/item/ --> This wouldn't really mean anything different than the line above. (Is that bad?)
www.example.com/project/5/item/198237/ --> This would show details for item 198237.
So, each item is directly associated with one and only one project.
The only way I can think how to do this is to bloat the "project" controller and parse the various parameters and control ALL views from that "project" controller. I'd prefer not to do this, because the model and view for an "item" are truly separate from the model and view of a "project."
The only other solution (that I am currently implementing and don't prefer) is to have the following:
www.example.com/project/5/
www.example.com/item/198237/
Is there any way to build a hierarchical URL as I showed at the beginning without bloating the "project" controller?
There are 3 options, sorted by how practical they can be:
Use URI Routing. Define a regular expression that will use a specific controller/method combination for each URL.
Something like that could help you, in routes.php:
$route['project/'] = 'project/viewall';
$route['project/(.+)'] = 'project/view/$1';
$route['project/(.+)/item/'] = 'project/view/$1';
$route['project/(.+)/item/(.+)'] = 'item/view/$2';
That is, considering your controllers are item and project respectively. Also note that $n in the value corresponds to the part matched in the n-th parenthesis.
Use the same controller with (or without) redirection. I guess you already considered this.
Use redirection at a lower level, such as ModRewrite on Apache servers. You could come up with a rule similar to the one in routes.php. If you are already using such a method, it wouldn't be a bad idea to use that, but only if you are already using such a thing, and preferably, in the case of Apache, in the server configuration rather than an .htaccess file.
You can control all of these options using routes.php (found in the config folder). You can alternatively catch any of your URI segments using the URI class, as in $this->uri->segment(2). That is if you have the URL helper loaded. That you can load by default in the autoload.php file (also in the config folder).

Google Analytics not tracking conversions in Magento 1.7

I'm using Magento's built in Googleanalytics module which is working fine for page views, but not for conversions. The account is set up fine on Google, but it's not adding the addTrans part in the checkout/onepage/success page.
I've done a lot of digging this morning, and found that the observer does observe the "checkout_onepage_controller_success_action" correctly, and does indeed run. It does the following:
$block = Mage::app()->getFrontController()->getAction()->getLayout()->getBlock('google_analytics');
if ($block) {
$block->setOrderIds($orderIds);
}
I've done some echoing, and it does retrieve the block, and it also sets the order ids correctly. However, in the block itself, if I echo out $this->getOrderIds(); its empty.
My next thought was that perhaps it could be using two GA blocks on the page, and maybe its passing the data to the first one but echoing the HTML of the 2nd one, but I've no clue how to start checking that! The Googleanalytics.xml file only has one block it in, and I don't use that block name anywhere else!
Anyone experienced similar? Or have any idea where I can go from here?
EDIT:
The Ga.php block includes the transaction code if $this->getOrderIds() returns an array, which it is not doing. However, the observer is doing $block->setOrderIds($order_ids); which is passing through an array containing an order id. So the observer is passing the ids to the block, and the block is receiving them (setting up a method of setBlockIds and echoing out the argument, does show the array), but when the block tries to access its own data, it's suddenly not there ($block->getData() returns an array of properties but there is no order_ids property).
I also figured maybe it could be that its echoing the blocks HTML before setting the order id, so I added some variables in to check that and it's not that - its definitely setting the order_ids before trying to get them again, but its still not working!
I'm completely stumped! My only idea now is to modify the Ga.php block to use Magento's registry instead of it's own _data property, which is really not a nice way of doing it!
I think i've been an utter tool. Magento wasn't tracking conversions on the live site because I hadn't put the account code in the configuration part, but I had on my test site.
I had previously put my own analytics code in the template, so I had tracked page views.
When I saw no conversions (despite putting the account code in my test site), I started making orders on the test site and then viewing the source of the order success page. Firefox loads its source as a new request...which automatically goes to the empty basket page. So obviously, it wasn't showing the addTrans or anything, because it had already done that.
A quick check in firebug revealled it was working as it should.
So in the end, after a day of searching, I had to change "No" to "Yes" in the admin, and type in the account code. Great.

Magento - Make a copy of history.phtml and use it in my own way

I’m looking to find a way to copy the page history that we can access from My account/My orders which is available on this directory template/sales/order/history.phtml and use its content on my own way without affecting the original one. I’ve been trying many ways, as copying the whole directory and editing the Xml files related to it in order to setup up the right path and make it work, unfortunately it was a failure. I would like to know if you could give me a solution for this.
thx.
To use the functions of a block inside another .phtml I'm quite sure you can use getBlock
$blockFunctions = $this->getLayout()->getBlock('sales/order_history');
$order = $blockFunctions->getOrderHistory();
And to add a block in your custom module you'll need to create a .xml file for your block and add it to your template, you'll also have to add the actual .phtml file. Take a look at the moduleCreator (http://www.magentocommerce.com/magento-connect/danieln/extension/1108/modulecreator) this handles most of this quite well.
This is by no means througher its just a rough guide.

Magento, translate validation error messages

I have successfully created new rules for the prototype validation, now I need to translate the error messages (Location: String in Javascript). However, I can only translate all the messages, my new custom ones don't appear to be translatable. How do I change this?
Maybe you need an jstranslator.xml file inside etc folder:
<?xml version="1.0" encoding="UTF-8"?>
<jstranslator>
<some-message-name translate="message" module="mymodule">
<message>This is the text in my own js validation</message>
</some-message-name>
</jstranslator>
With the following structure and meanings:
<jstranslator> - [one] XML root node.
<some-message-name> - [zero or more] root node child elements with a unique XML element name across all jstranslator.xml files (otherwise last in loading order based on module listing wins).
Attributes:
translate="message" - (optional) a hint that the child element(s) that is being translated is named "message", however this is hardencoded for the js translation XML files (Magento CE 1.9, search for "*/message") and this attribute does not need to be used.
module="mymodule" - (optional) name of the module, if left out the value is "core". It will be used to instantiate the data-helper later on (from that module) which then is reponsible to load the translations (e.g. from the CSV files).
<message> - [zero or one per parent] message to translate. the text value of this elements node-value is taken to be added to the javascript Translator object data.
All jstranslator.xml files of activated modules are processed.
Then put your translation line into the Something_Mymodule.csv file:
"This is the text in my own js validation", "(translated in a different language or speech)"
Then in your js scripts you can use your own translations via the Translator:
Translator.translate('This is the text in my own js validation');
Further References
Correct usage of jstranslator.xml
To translate custom javascript error messages you need also to add them to the following file:
\app\code\core\Mage\Core\Helper\Js.php
find a function _getTranslateData()
and you'll see a bunch of messages already in there.
just add your message somewhere in the array like this:
'This is my validation message' => $this->__('This is my validation message')
Don't forget a comma (,).
And then put translation in some translate file.
In the file where you use this message (I use it in opcheckout.js file) you need to wrap text in Translator.translate('This is my validation message').
I haven't figured out yet if it's important which translate file that is. You can try Mage_Core.csv .
I needed it in Mage_Checkout.csv and it works in there.
Anyway, for those who are interested in more, I noticed that these javascript messages are printed in header of every html page and some worrie that it messes with the SEO. Anyway this is printed in file
\app\design\frontend\bmled\default\template\page\html\head.phtml with the code.
<?php echo $this->helper('core/js')->getTranslatorScript() ?>
Check for more here:
I hope this helps, I just hope this works everywhere, so far I tested it on Onepage Checkout only.
You can edit app/local/ur_language/Mage_Core.csv file, adding original string in the first Column the translated one in the second. All the javascript translations are stored in this file.
What's helped me (Magento EE 1.6) -
I added new translation object:
<script>
var _data = {
'This is a required field.':
"<?php echo $this->__('This is a required field.'); ?>",
'Please make sure your passwords match.':
"<?php echo $this->__('Please make sure your passwords match');?>",
'validate telephone error':
"<?php echo $this->__('validate telephone error');?>"
};
var Translator = new Translate(_data);
</script>
if it is defined VarienForm uses it in js validation
We had exactly the same problem with one of our magento projects. We found that the function in app/design/frontend/default/default/template/page/htmlhead.phtml had been commented out:
<?php echo $this->helper('core/js')->getTranslatorScript() ?>
After putting this in, it still did not work, because translations had not been inserted into translate file. Check out those two things and it should start working.
To expand on this, you must add the translation strings to Mage/Core/Helper/Js.php.

Resources