Monday, December 30, 2013

Installing Subversion And Configuring Access Through Different Protocols On Ubuntu

Subversion is an open source version control system. Using Subversion, you can record the history of source files and documents. It manages files and directories over time. A tree of files is placed into a central repository. The repository is much like an ordinary file server, except that it remembers every change ever made to files and directories.

Installation

To access Subversion repository using the HTTP protocol, you must install and configure a web server. Apache2 is proven to work with Subversion. Please refer to the HTTP subsection in the Apache2 section to install and configure Apache2. To access the Subversion repository using the HTTPS protocol, you must install and configure a digital certificate in your Apache 2 web server. Please refer to the HTTPS subsection in the Apache2 section to install and configure the digital certificate.
To install Subversion, run the following command from a terminal prompt:

sudo apt-get install subversion libapache2-svn

Server Configuration

This step assumes you have installed above mentioned packages on your system. This section explains how to create a Subversion repository and access the project.

Create Subversion Repository

The Subversion repository can be created using the following command from a terminal prompt:

svnadmin create /path/to/repos/project

Importing Files

Once you create the repository you can import files into the repository. To import a directory, enter the following from a terminal prompt:
svn import /path/to/import/directory file:///path/to/repos/project

Access Methods

Subversion repositories can be accessed (checked out) through many different methods --on local disk, or through various network protocols. A repository location, however, is always a URL. The table describes how different URL schemes map to the available access methods.
Table 16.1. Access Methods
SchemaAccess Method
file://direct repository access (on local disk)
http://Access via WebDAV protocol to Subversion-aware Apache2 web server
https://Same as http://, but with SSL encryption
svn://Access via custom protocol to an svnserve server
svn+ssh://Same as svn://, but through an SSH tunnel

In this section, we will see how to configure Subversion for all these access methods. Here, we cover the basics. For more advanced usage details, refer to the svn book.

Direct repository access (file://)

This is the simplest of all access methods. It does not require any Subversion server process to be running. This access method is used to access Subversion from the same machine. The syntax of the command, entered at a terminal prompt, is as follows:

svn co file:///path/to/repos/project

or

svn co file://localhost/path/to/repos/project

[Note]
If you do not specify the hostname, there are three forward slashes (///) -- two for the protocol (file, in this case) plus the leading slash in the path. If you specify the hostname, you must use two forward slashes (//).
The repository permissions depend on filesystem permissions. If the user has read/write permission, he can checkout from and commit to the repository.

Access via WebDAV protocol (http://)

To access the Subversion repository via WebDAV protocol, you must configure your Apache 2 web server. Add the following snippet between the <VirtualHost> and </VirtualHost> elements in /etc/apache2/sites-available/default, or another VirtualHost file:
 <Location /svn>
  DAV svn
  SVNPath /home/svn
  AuthType Basic
  AuthName "Your repository name"
  AuthUserFile /etc/subversion/passwd
  Require valid-user
 </Location> 
[Note]
The above configuration snippet assumes that Subversion repositories are created under /home/svn/directory using svnadmin command. They can be accessible usinghttp://hostname/svn/repos_name url.
To import or commit files to your Subversion repository over HTTP, the repository should be owned by the HTTP user. In Ubuntu systems, normally the HTTP user is www-data. To change the ownership of the repository files enter the following command from terminal prompt:
sudo chown -R www-data:www-data /path/to/repos
[Note]
By changing the ownership of repository as www-data you will not be able to import or commit files into the repository by running svn import file:/// command as any user other than www-data.
Next, you must create the /etc/subversion/passwd file that will contain user authentication details. To create a file issue the following command at a command prompt (which will create the file and add the first user):
sudo htpasswd -c /etc/subversion/passwd user_name
To add additional users omit the "-c" option as this option replaces the old file. Instead use this form:
sudo htpasswd /etc/subversion/password user_name
This command will prompt you to enter the password. Once you enter the password, the user is added. Now, to access the repository you can run the following command:
                    
                      svn co http://servername/svn
                    
                  
[Warning]
The password is transmitted as plain text. If you are worried about password snooping, you are advised to use SSL encryption. For details, please refer next section.

Access via WebDAV protocol with SSL encryption (https://)

Accessing Subversion repository via WebDAV protocol with SSL encryption (https://) is similar to http:// except that you must install and configure the digital certificate in your Apache2 web server. To use SSL with Subversion add the above Apache2 configuration to /etc/apache2/sites-available/default-ssl. For more information on setting up Apache2 with SSL see the section called “HTTPS Configuration”.
You can install a digital certificate issued by a signing authority. Alternatively, you can install your own self-signed certificate.
This step assumes you have installed and configured a digital certificate in your Apache 2 web server. Now, to access the Subversion repository, please refer to the above section! The access methods are exactly the same, except the protocol. You must use https:// to access the Subversion repository.

Access via custom protocol (svn://)

Once the Subversion repository is created, you can configure the access control. You can edit the/path/to/repos/project/conf/svnserve.conf file to configure the access control. For example, to set up authentication, you can uncomment the following lines in the configuration file:
# [general]
# password-db = passwd
After uncommenting the above lines, you can maintain the user list in the passwd file. So, edit the file passwd in the same directory and add the new user. The syntax is as follows:
username = password
For more details, please refer to the file.
Now, to access Subversion via the svn:// custom protocol, either from the same machine or a different machine, you can run svnserver using svnserve command. The syntax is as follows:
$ svnserve -d --foreground -r /path/to/repos
# -d -- daemon mode
# --foreground -- run in foreground (useful for debugging)
# -r -- root of directory to serve

For more usage details, please refer to:
$ svnserve --help
Once you run this command, Subversion starts listening on default port (3690). To access the project repository, you must run the following command from a terminal prompt:

svn co svn://hostname/project project --username user_name

Based on server configuration, it prompts for password. Once you are authenticated, it checks out the code from Subversion repository. To synchronize the project repository with the local copy, you can run the update sub-command. The syntax of the command, entered at a terminal prompt, is as follows:

cd project_dir ; svn update

For more details about using each Subversion sub-command, you can refer to the manual. For example, to learn more about the co (checkout) command, please run the following command from a terminal prompt:
                    
                      svn co help
                    
                  

Access via custom protocol with SSL encryption (svn+ssh://)

The configuration and server process is same as in the svn:// method. For details, please refer to the above section. This step assumes you have followed the above step and started the Subversion server using svnserve command.
It is also assumed that the ssh server is running on that machine and that it is allowing incoming connections. To confirm, please try to login to that machine using ssh. If you can login, everything is perfect. If you cannot login, please address it before continuing further.
The svn+ssh:// protocol is used to access the Subversion repository using SSL encryption. The data transfer is encrypted using this method. To access the project repository (for example with a checkout), you must use the following command syntax:

svn co svn+ssh://hostname/var/svn/repos/project

[Note]
You must use the full path (/path/to/repos/project) to access the Subversion repository using this access method.
Based on server configuration, it prompts for password. You must enter the password you use to login via ssh. Once you are authenticated, it checks out the code from the Subversion repository.

Thursday, December 5, 2013

Magento : Display product count in Subcategory menu

Magento is the most popular use for ecommerce solutions in the web, because there have already useful built in functions and modules such a newsletter sending, credit card payments, strong securities and more and make life easy as a magento developer. In some our work projects, we need to add extra functionally in Magento Store, such a creating custom magento modules, creating custom widgets, add custom pages. In this tutorial, I would like to share on how get the count of products in Subcategories in navigation and append the count in sub category name. In the screenshot below, we appended the count of products in corresponding subcategories, this is very easy to add. This works in Magento Community Edition 1.7.0.2. However if Magento Community release the new version 1.8.x and up, I will update this post and test the compatibility of the module.

What will you do is go to the core directory '\app\code\core\Mage\Page\Block\Html\Topmenu.php' and copy the Topmenu.php, and create a override copy in local folder like '\app\code\local\Mage\Page\Block\Html\Topmenu.php' and modify it. The Modify code shown below.

<?php

class Mage_Page_Block_Html_Topmenu extends Mage_Core_Block_Template {
    /**
     * Top menu data tree
     *
     * @var Varien_Data_Tree_Node
     */
    protected $_menu;

    /**
     * Init top menu tree structure
     */
    public function _construct()
    {
        $this->_menu = new Varien_Data_Tree_Node(array(), 'root', new Varien_Data_Tree());
    }

    /**
     * Get top menu html
     *
     * @param string $outermostClass
     * @param string $childrenWrapClass
     * @return string
     */
    public function getHtml($outermostClass = '', $childrenWrapClass = '')
    {
        Mage::dispatchEvent('page_block_html_topmenu_gethtml_before', array(
            'menu' => $this->_menu
        ));

        $this->_menu->setOutermostClass($outermostClass);
        $this->_menu->setChildrenWrapClass($childrenWrapClass);

        $html = $this->_getHtml($this->_menu, $childrenWrapClass);

        Mage::dispatchEvent('page_block_html_topmenu_gethtml_after', array(
            'menu' => $this->_menu,
            'html' => $html
        ));

        return $html;
    }

    /**
     * Recursively generates top menu html from data that is specified in $menuTree
     *
     * @param Varien_Data_Tree_Node $menuTree
     * @param string $childrenWrapClass
     * @return string
     */
    protected function _getHtml(Varien_Data_Tree_Node $menuTree, $childrenWrapClass)
    {
        $html = '';

        $children = $menuTree->getChildren();
        $parentLevel = $menuTree->getLevel();
        $childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;

        $counter = 1;
        $childrenCount = $children->count();

        $parentPositionClass = $menuTree->getPositionClass();
        $itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';

        foreach ($children as $child) {

            $child->setLevel($childLevel);
            $child->setIsFirst($counter == 1);
            $child->setIsLast($counter == $childrenCount);
            $child->setPositionClass($itemPositionClassPrefix . $counter);

            $outermostClassCode = '';
            $outermostClass = $menuTree->getOutermostClass();

            if ($childLevel == 0 && $outermostClass) {
                $outermostClassCode = ' class="' . $outermostClass . '" ';
                $child->setClass($outermostClass);
            }

   /* custom code */
   $category = Mage::getModel('catalog/category')->load(str_replace('category-node-', '', $child->getId()));
   $prodCollection = Mage::getResourceModel('catalog/product_collection')->addCategoryFilter($category);
            /* cuatom code end */

   $html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';

   /* original */
   // $html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml($child->getName()) . '</span></a>';

   /* custom count products */
   $html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml($child->getName()) . (is_null($parentLevel) ? '' : ' ('.$prodCollection->count().')') . '</span>' . '</a>';

            if ($child->hasChildren()) {
                if (!empty($childrenWrapClass)) {
                    $html .= '<div class="' . $childrenWrapClass . '">';
                }
                $html .= '<ul class="level' . $childLevel . '">';
                $html .=  $this->_getHtml($child , $childrenWrapClass);
                $html .= '</ul>';

                if (!empty($childrenWrapClass)) {
                    $html .= '</div>';
                }
            }
            $html .= '</li>';

            $counter++;
        }

        return $html;
    }

    /**
     * Generates string with all attributes that should be present in menu item element
     *
     * @param Varien_Data_Tree_Node $item
     * @return string
     */
    protected function _getRenderedMenuItemAttributes(Varien_Data_Tree_Node $item)
    {
        $html = '';
        $attributes = $this->_getMenuItemAttributes($item);

        foreach ($attributes as $attributeName => $attributeValue) {
            $html .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"';
        }

        return $html;
    }

    /**
     * Returns array of menu item's attributes
     *
     * @param Varien_Data_Tree_Node $item
     * @return array
     */
    protected function _getMenuItemAttributes(Varien_Data_Tree_Node $item)
    {
        $menuItemClasses = $this->_getMenuItemClasses($item);
        $attributes = array(
            'class' => implode(' ', $menuItemClasses)
        );

        return $attributes;
    }

    /**
     * Returns array of menu item's classes
     *
     * @param Varien_Data_Tree_Node $item
     * @return array
     */
    protected function _getMenuItemClasses(Varien_Data_Tree_Node $item)
    {
        $classes = array();

        $classes[] = 'level' . $item->getLevel();
        $classes[] = $item->getPositionClass();

        if ($item->getIsFirst()) {
            $classes[] = 'first';
        }

        if ($item->getIsActive()) {
            $classes[] = 'active';
        }

        if ($item->getIsLast()) {
            $classes[] = 'last';
        }

        if ($item->getClass()) {
            $classes[] = $item->getClass();
        }

        if ($item->hasChildren()) {
            $classes[] = 'parent';
        }

        return $classes;
    }
}