Category Archives: Frameworks

How to use Opencart default admin over Joomla’s Component like jCart/Mijoshop or other CMS

This article is going to explain how to run a Opencart default admin with Joomla Opencart Extensions like jCart and mijoshop. This could apply to any other CMS which provide bridge between opencart and the CMS.

Some background

Opencart components are usually a opencart installation, wrapped with some code, so it will appear in Joomla or other CMS as a part of the site. Because of collisions between Joomla’s javascript libs and some opencart extensions, which heavily uses javascript they couldn’t work on the Joomla Opencart Admin. For this very reason, the following steps need to be done. The result – you will get fully functional opencart Admin, linked to the frontend of your shop. This way you can use extensions like Bulk Product Update PRO or similar.
Continue reading

Adding notification when new order arrives. Magento

It’s very common practice the administrators to get notification mail when a new order is placed on the shop. Here is how to activate this feature in Magento for free (there is paid Admin Notification Module as well):

Log in into admin area, then go to System->Configuration menu. Scroll down to Sales section and click on the Sales Emails and select the first section Orders. Enter your admin e-mail in the field “Send Order Email Copy To”.

And here comes the tricky one πŸ™‚ Select the option “Separate email” from the “Send Order Email Copy Method” field. I don’t know why, but if it’s selected “Bcc”, the e-mail to the admin wasn’t send.

It’s possible that this is fixed in the versions above 1.2.x, but I haven’t tested.

hope this helps someone.

Passing variables to all Models from the Controller – strict MVC way

It’s really easy to find inspiration when you developing on CakePHP. For the current project I need to create global (for all models) behavior which stores creator and modifier as well as deleter and deleted (for soft-delete).

What are the requirements

1. For every table (or at least the most of them) there are fields 6 fields:

  • creator (int) – user who create the the record
  • created (datetime) – date when the record was created
  • modifier (int) – user who modified the the record
  • modified (datetime) – date when the record was modified
  • deleter (int) – user who delete the the record
  • deleted (datetime) – date when the record was modified

2. Some tables doesn’t have such fields (like aros, acos, settings etc), so it should update tables which has such fields.

I’ve seen Soft Deletable Behavior as well as recently added WhoDidIt behavior, but I don’t like the approach of using _SESSION. I’ve also decided to use datetime field to determine if the record is active (field deleted is NULL) or deleted (if the field is set with date).

So the result was – I’ve write my own behavior who serves this.
Continue reading

Careful with JavaScript includes

Ok, this is not a code snippet article. It’s just an experience which you probably already met, but it was nightmare to find and it took me 1/2 a day to fix this “stupid” bug.

So what is the case?

Working on a project including some advanced JavaScript and Ajax techniques my coworker Milen noticed that the Session is not behaving as expected. In a simple function like:

 function test($id = false){
  if ($id != false) {
    echo $id;
    echo $k = $this->Session->read('some_var');
    $this->Session->write('some_var', $id);
  }
  $this->set('tests', $this->paginate());
 }

The result should be quite easy to be predicted: if you pass for example 5 on the second reload the $k should be with the same value as $id. Unfortunately instead of 5 the $k was ‘images’. Yep, quite strange, isn’t it?

if you put die() at the end of the function, the result is as expected.

What was the problem

In our current project we are using jQuery and some of it’s plugins. So the problems was in the ThickBox plugin. If you remove it from the header everything works.

Digging into unpacked version of the plugin we’ve noticed that the loading picture is not where it should be. there is an variable

 var tb_pathToImage = "images/loadingAnimation.gif"

and as you may notice the path is not compatible with Cake convention and obviously it’s not in the http://server/cakeapp/tests/test/images/.

In the example above we were writing id into the session. Yes but calling: http://server/cakeapp/tests/test/images/loadingAnimation.gif mean that $id take value of ‘images’.

It was quite tricky, because if you loading CSS or JavaScript and the file is not there, FireBug or even the html /if there is no correct CSS the styling will fail/ will warn the developer, but image loaded into the JS function is quite difficult to find.

Anyway, the conclusion is “Watch you JavaScript libs and what files they require”.

Translating plural and singular forms in CakePHP

I don’t know how good you know the *.po translation file syntax, but for me it was a text file with “msgid” and “msgstr”, where msgid is the string, which could be found in a code of the app, wrapped with __() function and msgstr is the string which is the translation.

Following this convention in all of my projects I had not problems till now. But on this one I’ve noticed that the translation is not quite accurate especially when translating time. I am speaking about usage of timeAgoInWords() function from the TimeHelper.

I noticed that when there is a translation file for the specific language singular and plural words are not translated properly, I had results like “3 hour and 34 minute” instead of “3 hours and 34 minutes”.

I thought that I’ve found a bug, and I submitted a ticket in the trac, but I was wrong, because syntax of the PO files is a little bit extended than my understanding. πŸ™‚

99% of the cases the standard approach could fit just fine, but when it’s used __n() function which is described as:

Returns correct plural form of message identified by $singular and $plural for count $count.

the translation file needed a specific syntax. Here is the example of it:

msgid "hour"
msgid_plural "hours"
msgstr[0] "hour"
msgstr[1] "hours"

As you can see instead of msgid<->msgstr pair, there is also msgid_plural and array of msgstr which holding the translations of singular and plural values. Note that in some languages plural could have 2 or more forms. In these cases the syntax will be (Czech):

msgid "%1 second"
msgid_plural "%1 seconds"
msgstr[0] "%1 sekunda"
msgstr[1] "%1 sekundy"
msgstr[2] "%1 sekund"

It’s good to set the plural forms definition in the project settings which are in the beggining of the file. This is very handy when you use PoEdit or similar translation tools, because if is your setting is correct, these tools will provide for each plural form separate tab.

The syntax of plural form definition is like:

"Plural-Forms: nplurals=1; plural=0;\n"

It hold 2 parameters the first one holding the number of plural forms in the specific language and the second one is an expression how to determine the plurals. If you don’t know how to set this correct for a specific language, check this good document of all available languages. πŸ™‚

More information about the PO syntax I founded in that article. I’ve noticed in that the article there are shortcuts, which are not useful for me so far, but you never knows, in the future they could be handy.

Regarding to that I am wondering is there a POT file for the core lib translations which could be a big helper to anyone who need to translate the whole framework.

Blast from the past

Hey guys,

last week I’ve worked on a project which I finished somewhere in spring of 2007 and I decided to share my experience with this post. I don’t know did you had such experience, but for me it was interesting, because working on old code is always challenge.

Basically, the project was really small one, which uses 80% of scaffolding, so really nothing complicated. Now the client wanted some extensions to the core functionality /like adding few more look-up tables and some basic reports/ and because I was the only one developer who worked on it, they ask me to do this and I agreed.

My first thought was to upgrade the core CakePHP lib to the last version, but after thinking I decided not to, because if something goes wrong /like some deprecated functions/, I need to do more work in debugging rather than focusing on the real tasks.

What I noticed while I coded?

The major one – Improvement of the console script. In the past it was in the /cake/scripts/. In the folder there were acl.php, bake.php and bake2.php, extract.php for label extraction and master bake which I never used. Now, the console script is more advanced and provide more functions. Still I am not big expert on it and I still using it for basic operations :).

Fully translated labels – it’s related to the previous one – when the code was generated with old bake script, some of the labels weren’t wrapped with __() function and especially for me it was biggest pain. Someone could tell me that there was ability to modify the templates, but I personally never did it.

The truth is that CakePHP in fact is improved a lot since then. Hopefully it will continue in this direction in the future as well.

Anyway, it was really interesting experience for me.

Fixing Dead Centre approach with jQuery

I was worked on a centred project design of a website. When I met such requirement I’ve always used Dead Centre approach.

Unfortunately I’ve noticed that when the content is larger than the screen the top-left corner is not visible. In that current project the logo of the site was exactly on that place, so it’s really confusing.

I had to solve this issue in order to satisfy the clients requirements. So, I’ve used jQuery to sort this out.

You can see the difference in these 2 examples:

Resize your browser window in order to see the difference.
How it’s working?

First of all there are 2 javascript includes:

<script type="text/javascript" src="jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="jquery.dimensions.min.js"></script>

After this there is a function which track the size of the screen and the content.

<script type="text/javascript">
        /*Track height and width of the window and the content*/
        function resize(){
            if($(window).height() < $('#content').height()){
                $('#horizon').css('top', '0px');
                $('#content').css('top', '0px');
            } else {
                $('#horizon').css('top', '50%');
                $('#content').css('top', '-'+($('#content').height()/2)+'px');
            }
            if($(window).width() < $('#content').width()){
                $('#content').css('left', ($('#content').width()/2)+'px');
            } else {
                $('#content').css('left', '50%');
            }
        }
       
        //Bind events on resize
        $(document).ready(function(){
            resize();
        })
        $(window).bind("resize", function(){
            resize();
        });
    </script>

The explanation of the code:
I am using jQuery plugin named jQuery Dimensions Plugin 1.1 which extract the proper dimensions of the boxes.
The function checking if the content screen is bigger than the window size, if so it change the CSS in order to fit properly. I guess that you can see the logic easily. So, no more explanations here.

Hope this will help someone.

Working with nested data and find method with breadcrumbs in CakePHP

Do you working with tree data in your projects?

Well, in CakePHP there is a Tree behavior which will help you to handle such structures. Let me show you how to use it in your projects. Hierarchical data structures are very well described here by Mike Hillyer and I would suggest you to take a look before you continue reading.

Let’s say we have following data structure:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `parent_id` INT(10) DEFAULT NULL,
  `name` VARCHAR(255) DEFAULT NULL,
  `lft` INT(10) DEFAULT NULL,
  `rght` INT(10) DEFAULT NULL,
  PRIMARY KEY  (`id`)
)

Note, that in that table there are 3 special fields: parent_id, lft and rght.

The first one is very familiar to everyone who understanding the tree structures. The other 2 are to handle the MPTT logic (see the article mentioned above). The beautiful part of using Tree behavior is that you don’t need to worry about these 2 extra columns. The behavior will fill them automatically. πŸ™‚

So, continue with the example. Attach the Tree behavior to your Model:

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');
}
?>

That’s it. Now when you save (insert or update) your data into the table, the fields lft and rght will be automatically populated with the correct values. Of course your task is to have proper value set in parent_id πŸ™‚

Why this is so important?
As you already know /if you read the article for MPTT/ using lft and rght values will give possibility to get very easy nested data in various ways.
In Model::find function there is already threaded option, but what about having breadcrumbs?

Here is a way to extend the Model::find function with this functionality. /inspired by Daniel Hofstetter’s post/

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');

    public function find($type, $options = array()) {
        switch ($type) {
            case 'breadcrumbs':
                if(!isset($options['fields']))
                    $options['fields'] = null;
                if(!isset($options['recursive']))
                    $options['recursive'] = null;
                if(is_object($this->Behaviors->Tree) && $options['id']){
                    return $this->Behaviors->Tree->getpath($this, $options['id'], $options['fields'], $options['recursive']);
                } else {
                    return null;
                }
                break;
            default:
                return parent::find($type, $options);
        }
    }
}
?>

As you can see I am using the function TreeBehavior::getpath. There are a lot of handy functions in this behavior, but for breadcrumbs example this is just enough.

How to use it?

$this->Category->find('breadcrumbs', array('id'=>1));

so if you have data like this:

1 Root
2     Cat1
3         Cat1.1
4     Cat2

and use the function mentioned above with id=3 the result will be:

Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 1
                    [parent_id] =>
                    [name] => Root
                    [lft] => 1
                    [rght] => 8
                )
        )

    [1] => Array
        (
            [Category] => Array
                (
                    [id] => 2
                    [parent_id] => 1
                    [name] => Cat1
                    [lft] => 2
                    [rght] => 5
                )
        )

    [2] => Array
        (
            [Category] => Array
                (
                    [id] => 3
                    [parent_id] => 2
                    [name] => Cat1.1
                    [lft] => 3
                    [rght] => 4
                )
         )
)

After this with

$breadcrumbs = Set::extract('/Category/name', $result);
echo ' / '.implode(' / ', $breadcrumbs);

you will have the following result

/ Root / Cat1 / Cat1.1

I am leaving to you the styling of it as well as adding the links to the parent nodes.

Building cake application (Part VI)

Saturday (Day 6)

Problem with validation messages while translating
Although my native language is Bulgarian and the requirement from the client was to have this site only in Bulgarian, I’ve preferred to have it in English and to make the translation with the i18n functions of CakePHP. There are 2 reasons to do this:

1. This will give me the possibility to show you the result of all these days of coding and
2. I can reuse some part of the codes the same as I’ve used in this project

So, up to my experience having application in English is never a bad idea. πŸ™‚

You know, that the translating process is not very exciting process, but someone need to do it and because there is no one who can help me with this I’ve start the translation. Anyway. πŸ™

While translating I noticed that the most of the validation messages are not appear of the translation file. I knew this from my past experience, but I needed to find an easy and elegant solution to translate these messages instead of putting them in all views. Putting in the view you need to do this at least 2 times.
Continue reading