How do you customize the log directory? - magento

I'm trying to customize my Magento's log directory, by setting log_dir in the Mage::app() $options, but it's still logging to var/log/file.log.
Note: I couldn't find this information very readily on SO or the web in general, so I felt it needed to be SO'd.

So it turns out that (as of 1.6.2.0 at least), Magento doesn't actually use the Mage::getBaseDir('log') within it's log() method - weak sauce, right?
It uses Mage::getBaseDir('var') and appends log and then the file name that you pass in.
If you want to customize the directory more than that, you have to get your hands a little dirty. For example, in our case, we wanted the log directory to be:
var/username/log/file.log
So here's how you bust it. Drop this in your config.xml to tell Magento about your new logging class:
<log>
<core>
<writer_model>Name_Module_Model_Zend_Log_Writer_Stream</writer_model>
</core>
</log>
Then, create a model:
class Name_Module_Model_Zend_Log_Writer_Stream extends Zend_Log_Writer_Stream
Then, proceed to do what you needs to do. In my case, it went something like this:
public function __construct($streamOrUrl, $mode = NULL)
{
$newLogPath = $this->_workMyMagicOnLogFilePath($streamOrUrl, $mode);
return parent::__construct($newLogPath, $mode);
}

Related

CodeIgniter pagintation - appending the page number to "page" string

What I am trying to achieve is urls outputting via pagination like this:
http://www.mysite.com/users/page5
or
http://www.mysite.com/users/page-5
At present, it will be using the URI segments like this:
http://www.mysite.com/users/page/5
I can modify the routes.php config file to route the path if the first two URLs are used. So, that's not the issue.
What I am having trouble with is, how do I initialize the settings for the pagination, so that the $this->pagination->create_links() will create a pagination with items having links like in the first or the second format?
Let me know if you need more explanation or examples regarding this. I'm not much good in explaining things. :)
Thank you
This functionality already exists in the in-development version of CodeIgniter 3.0. You can view the Pagination class as it sits here.
To use this library, you can either A) use all of CI 3.0 (it's pretty stable), or B) extend (or, more realistically, replace) the Pagination library by creating application/libraries/MY_Pagination.php and filling it with the contents of the link above. (Full disclosure: it's been a while since I tinkered with CI, so I don't know if anything has changed since that may result in errors with any of this answer.)
To use the feature you want, specify your base URL minus the page-X segment, set that you want to use page numbers instead of offset in your URI segment, and then specify a prefix.
$config['base_url'] = site_url('users');
$config['use_page_numbers'] = true;
$config['prefix'] = 'page-';
Make sure to include your other obvious items as well, such as per_page, etc.
To change the functionality of the Pagination library, you can extend the library and override the create_links() function.
Create a file named MY_Pagination.php in application/libraries/
The file should have the following structure, so you can change or add additional functionality to CI's native Pagination library. (It is bad practice to directly change the Pagination library in the system directory.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Pagination extends CI_Pagination {
public function __construct()
{
parent::__construct();
}
}
You'll then need to add the create_links() function to your MY_Pagination class, allowing you to override its default functionality. Below is an explanation of what you could change to achieve your desired output (you may want to add flexibility, by adding a parameter to the function, but this is the simplest change that I could think of.)
function create_links()
{
// You can copy the exact functionality of this function from:
// system/libraries/Pagination.php
// The line you want to change is:
// $this->base_url = rtrim($this->base_url, '/') .'/';
// Changing to this: $this->base_url = rtrim($this->base_url, '/') .'';
// Will create links in this format: ../page5
// Or changing to this: $this->base_url = rtrim($this->base_url, '/') .'-';
// Will create links in this format: ../page-5
}

Magento email template: Block template inheritance broken

Problem
When I try to add a block into my transactional email template in the following manner:
{{block type='core/template' area='frontend' template='invent/baskettimer/email_items.phtml' record=$record}}
I get the following error, and nothing is rendered.
CRIT (2): Not valid template file:frontend/base/default/template/invent/baskettimer/email_items.phtml
Troubleshooting
Normally this warning points to a typo which is breaking the inheritance but I have quadruple checked and this should work.
I then copied the file into the base and did a test, it rendered correctly.
Create a custom block and set the template, same error is displayed.
Theory
To me it seems template inheritance is broken / not implemented for emails, so it is always looking in base, I cannot put my templates there so I am not sure how to call them.
Possible workarounds
Render the block to html then send it to as a variable to render, problem with this is I am sending the emails from Model level and am having a hard time pre rendering the block, even with a helper.
Render the data using a method, don't really want to do this as it is message / against MVC.
Any help is much appreciated.
Bounty update
So I have traced down the problem, it is probably an easy solution now.
The problem is that I am calling it from a cronjob does not have the correct store view, it is fairly easy to replicate similar situation by using a shell script, then changing the _appCode to null.
<?php
require_once 'abstract.php';
class Mage_Shell_Shell extends Mage_Shell_Abstract
{
protected $_appCode = ''; // works - remove to not work
/**
* Run script
*
*/
public function run()
{
Mage::getModel('invent_baskettimer/email')->sendJob();
}
}
$shell = new Mage_Shell_Shell();
$shell->run();
So basically the question has become:
How do I call a block->toHtml() regardless of store view?
There is not way of setting a cronjob to be like that. Lucky magento lets you emulate your store views, see the following to emulate the default store.
public function cronjob()
{
$iDefaultStoreId = Mage::app()
->getWebsite()
->getDefaultGroup()
->getDefaultStoreId();
$appEmulation = Mage::getSingleton('core/app_emulation');
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($iDefaultStoreId);
.. do your stuff here ..
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
}
For more info see: http://inchoo.net/ecommerce/magento/emulate-store-in-magento/

Error extends AccountController.php in magento

I'm trying to extend the core AccountController.php -> app/code/core/Mage/Customer copied it to app/code/local/Mage/ and add a log to see which extends properly.
In the file AccountController.php (app/code/local/Mage/Customer/controllers)
...
...
public function createPostAction() {
Mage::log('In app/code/local/Mage/', null, 'test.log', true);
...
...
AND CORE (only test)
In the file AccountController.php (app/code/core/Mage/Customer/controllers)
...
...
public function createPostAction() {
Mage::log('In app/code/core/Mage/', null, 'test.log', true);
...
...
And does not go through code/local/ Mage but by CORE.
I need to configure something or it fails?
The logic through which controller class definitions are loaded builds the path to the file above the explicit include paths on which the autoloader relies. This means no local vs. core precedence.
You need to creat a controller rewrite by specifying a directory under the xpath frontend/routers/customer/args/modules/your_module
The latter node needs the before attribute set to Mage_Customer and you will need to create an AccountController.php with a createPostAction() method. Depending on your needs you may or may not need to extend from and require the core account controller class.
I guess you need to require the original controller:
require_once Mage::getModuleDir('controllers', 'Mage_Customer').DS.'AccountController.php';
Normally you need to do this with rewriting a controller the xml way...i havent checked in code, but maybe this is the problem.
I would recommend to do it the regular way via config.xml
http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/how_to_overload_a_controller

How to deal with the messages block in Magento hole punching

I am getting interested in how hole punching might work in magento inside a full page cache situation. This is not directly related to the enterprise edition and how its full page cache and hole punching mechanism might work, just in general.
Due to the way that the messages block is generated by magento i am really very curious as to how to deal with the messages block in a hole punching situation?
Have any magento devs out there tackled this before and can maybe explain to me how this particular block can be hole punched?
You will need to link a cache container to the core/messages block to be able to prevent the block from caching. To reach your goal you will need a basic module, or add this to one of your existing module, whichever is the best (read: more logical) place for you.
Within your_module/etc/ you will need to create cache.xml file:
<config>
<placeholders>
<your_module_messages>
<block>core/messages</block>
<placeholder>SYSTEM_MESSAGES</placeholder>
<container>Your_Module_Model_PageCache_NoCache</container>
</your_module_messages>
</placeholders>
</config>
The Your_Module_Model_PageCache_NoCache needs to be an extend of Enterprise_PageCache_Model_Container_Abstract and in that extend you need to overwrite the saveCache() method and directly return $this instead triggering the underlying $this->_saveCache(). Perhaps with more logic you can make this punch hole a bit smarter, but for now assume that you never know when there is a new messages, thus leaving the hole open at all times.
public function saveCache($blockContent)
{
return $this;
}
The only thing left is to trigger Magento to load the core/messages block from within the whole. This you can accomplish by adding the following method to your class.
protected function _renderBlock()
{
$block = $this->_placeholder->getAttribute('block');
//$template = $this->_placeholder->getAttribute('template');
$block = new $block;
//$block->setTemplate($template);
$block->setLayout(Mage::app()->getLayout());
return $block->toHtml();
}
It will fetch the block information from the cache.xml file and return the output of the block. Since core/messages actually generated it's own HTML you don't need to provide a template. So might as well remove those commented lines from the code.
Hopefully this helps you with your task at hand!

Magento - module with system config, how do I do something on save?

I have a simple module created with the Magento Module Creator with a couple of settings in admin->system->config.
When I go to these settings and choose the enable/disable option, the settings get saved - which is great - however, I want to run my own code after that, i.e. on the save action, once the data has been saved.
In your etc/system.xml add a backend model descended from Mage_Core_Model_Config_Data and use it's _afterSave() method to run your code.
although it isnt a good idea but you can achieve it by observers:
<controller_action_postdispatch_adminhtml_mymodule_mycontroller_myaction>
replace the my-s with module_controller_action, and most likely you want to put it in this event:
<controller_action_postdispatch_adminhtml_system_config_save>
in your config xml as follows:
<controller_action_postdispatch_adminhtml_system_config_save>
<observers><myobserver>
<type>singleton</type>
<class>mymodule/observer</class>
<method>mymethod</method>
</myobserver></observers>
</controller_action_postdispatch_adminhtml_system_config_save>
and in mymodule, as in your module have a class observer in mymodule/Model/Observer.php
and declare the observer as
class modules_mymodule_observer {
public function myfunction(Varien_Event_Observer $observer){
//do your stuffs
}
}

Resources