PageRenderTime 601ms CodeModel.GetById 101ms app.highlight 358ms RepoModel.GetById 35ms app.codeStats 3ms

/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 1626 lines | 873 code | 178 blank | 575 comment | 65 complexity | e6fc43f4d7bdf539096637f06f2bf579 MD5 | raw file
   1<?php
   2/**
   3 * Magento
   4 *
   5 * NOTICE OF LICENSE
   6 *
   7 * This source file is subject to the Open Software License (OSL 3.0)
   8 * that is bundled with this package in the file LICENSE.txt.
   9 * It is also available through the world-wide-web at this URL:
  10 * http://opensource.org/licenses/osl-3.0.php
  11 * If you did not receive a copy of the license and are unable to
  12 * obtain it through the world-wide-web, please send an email
  13 * to license@magentocommerce.com so we can send you a copy immediately.
  14 *
  15 * DISCLAIMER
  16 *
  17 * Do not edit or add to this file if you wish to upgrade Magento to newer
  18 * versions in the future. If you wish to customize Magento for your
  19 * needs please refer to http://www.magentocommerce.com for more information.
  20 *
  21 * @category    Mage
  22 * @package     Mage_Adminhtml
  23 * @copyright   Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
  24 * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  25 */
  26
  27/**
  28 * Adminhtml grid widget block
  29 *
  30 * @category   Mage
  31 * @package    Mage_Adminhtml
  32 * @author      Magento Core Team <core@magentocommerce.com>
  33 */
  34class Mage_Adminhtml_Block_Widget_Grid extends Mage_Adminhtml_Block_Widget
  35{
  36    /**
  37     * Columns array
  38     *
  39     * array(
  40     *      'header'    => string,
  41     *      'width'     => int,
  42     *      'sortable'  => bool,
  43     *      'index'     => string,
  44     *      //'renderer'  => Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Interface,
  45     *      'format'    => string
  46     *      'total'     => string (sum, avg)
  47     * )
  48     * @var array
  49     */
  50    protected $_columns = array();
  51
  52    protected $_lastColumnId;
  53
  54    /**
  55     * Collection object
  56     *
  57     * @var Varien_Data_Collection
  58     */
  59    protected $_collection = null;
  60
  61    /**
  62     * Page and sorting var names
  63     *
  64     * @var string
  65     */
  66    protected $_varNameLimit    = 'limit';
  67    protected $_varNamePage     = 'page';
  68    protected $_varNameSort     = 'sort';
  69    protected $_varNameDir      = 'dir';
  70    protected $_varNameFilter   = 'filter';
  71
  72    protected $_defaultLimit    = 20;
  73    protected $_defaultPage     = 1;
  74    protected $_defaultSort     = false;
  75    protected $_defaultDir      = 'desc';
  76    protected $_defaultFilter   = array();
  77
  78    /**
  79     * Export flag
  80     *
  81     * @var bool
  82     */
  83    protected $_isExport = false;
  84
  85    /**
  86     * Empty grid text
  87     *
  88     * @var sting|null
  89     */
  90    protected $_emptyText;
  91
  92     /**
  93     * Empty grid text CSS class
  94     *
  95     * @var sting|null
  96     */
  97    protected $_emptyTextCss    = 'a-center';
  98
  99    /**
 100     * Pager visibility
 101     *
 102     * @var boolean
 103     */
 104    protected $_pagerVisibility = true;
 105
 106    /**
 107     * Column headers visibility
 108     *
 109     * @var boolean
 110     */
 111    protected $_headersVisibility = true;
 112
 113    /**
 114     * Filter visibility
 115     *
 116     * @var boolean
 117     */
 118    protected $_filterVisibility = true;
 119
 120    /**
 121     * Massage block visibility
 122     *
 123     * @var boolean
 124     */
 125    protected $_messageBlockVisibility = false;
 126
 127    protected $_saveParametersInSession = false;
 128
 129    /**
 130     * Count totals
 131     *
 132     * @var boolean
 133     */
 134    protected $_countTotals = false;
 135
 136    /**
 137     * Count subtotals
 138     *
 139     * @var boolean
 140     */
 141    protected $_countSubTotals = false;
 142
 143    /**
 144     * Totals
 145     *
 146     * @var Varien_Object
 147     */
 148    protected $_varTotals;
 149
 150    /**
 151     * SubTotals
 152     *
 153     * @var array
 154     */
 155    protected $_subtotals = array();
 156
 157    /**
 158     * Grid export types
 159     *
 160     * @var array
 161     */
 162    protected $_exportTypes = array();
 163
 164    /**
 165     * Rows per page for import
 166     *
 167     * @var int
 168     */
 169    protected $_exportPageSize = 1000;
 170
 171    /**
 172     * Massaction row id field
 173     *
 174     * @var string
 175     */
 176    protected $_massactionIdField = null;
 177
 178    /**
 179     * Massaction block name
 180     *
 181     * @var string
 182     */
 183    protected $_massactionBlockName = 'adminhtml/widget_grid_massaction';
 184
 185    /**
 186    * RSS list
 187    *
 188    * @var array
 189    */
 190    protected $_rssLists = array();
 191
 192    /**
 193     * Columns view order
 194     *
 195     * @var array
 196     */
 197    protected $_columnsOrder = array();
 198
 199    /**
 200     * Columns to group by
 201     *
 202     * @var array
 203     */
 204    protected $_groupedColumn = array();
 205
 206    /**
 207     * Label for empty cell
 208     *
 209     * @var string
 210     */
 211    protected $_emptyCellLabel = '';
 212
 213    public function __construct($attributes=array())
 214    {
 215        parent::__construct($attributes);
 216        $this->setTemplate('widget/grid.phtml');
 217        $this->setRowClickCallback('openGridRow');
 218        $this->_emptyText = Mage::helper('adminhtml')->__('No records found.');
 219    }
 220
 221    protected function _prepareLayout()
 222    {
 223        $this->setChild('export_button',
 224            $this->getLayout()->createBlock('adminhtml/widget_button')
 225                ->setData(array(
 226                    'label'     => Mage::helper('adminhtml')->__('Export'),
 227                    'onclick'   => $this->getJsObjectName().'.doExport()',
 228                    'class'   => 'task'
 229                ))
 230        );
 231        $this->setChild('reset_filter_button',
 232            $this->getLayout()->createBlock('adminhtml/widget_button')
 233                ->setData(array(
 234                    'label'     => Mage::helper('adminhtml')->__('Reset Filter'),
 235                    'onclick'   => $this->getJsObjectName().'.resetFilter()',
 236                ))
 237        );
 238        $this->setChild('search_button',
 239            $this->getLayout()->createBlock('adminhtml/widget_button')
 240                ->setData(array(
 241                    'label'     => Mage::helper('adminhtml')->__('Search'),
 242                    'onclick'   => $this->getJsObjectName().'.doFilter()',
 243                    'class'   => 'task'
 244                ))
 245        );
 246        return parent::_prepareLayout();
 247    }
 248
 249    public function getExportButtonHtml()
 250    {
 251        return $this->getChildHtml('export_button');
 252    }
 253
 254    public function getResetFilterButtonHtml()
 255    {
 256        return $this->getChildHtml('reset_filter_button');
 257    }
 258
 259    public function getSearchButtonHtml()
 260    {
 261        return $this->getChildHtml('search_button');
 262    }
 263
 264    public function getMainButtonsHtml()
 265    {
 266        $html = '';
 267        if($this->getFilterVisibility()){
 268            $html.= $this->getResetFilterButtonHtml();
 269            $html.= $this->getSearchButtonHtml();
 270        }
 271        return $html;
 272    }
 273
 274    /**
 275     * set collection object
 276     *
 277     * @param Varien_Data_Collection $collection
 278     */
 279    //public function setCollection(Varien_Data_Collection $collection)
 280    public function setCollection($collection)
 281    {
 282        $this->_collection = $collection;
 283    }
 284
 285    /**
 286     * get collection object
 287     *
 288     * @return Varien_Data_Collection
 289     */
 290    public function getCollection()
 291    {
 292        return $this->_collection;
 293    }
 294
 295    /**
 296     * Add column to grid
 297     *
 298     * @param   string $columnId
 299     * @param   array || Varien_Object $column
 300     * @return  Mage_Adminhtml_Block_Widget_Grid
 301     */
 302    public function addColumn($columnId, $column)
 303    {
 304        if (is_array($column)) {
 305            $this->_columns[$columnId] = $this->getLayout()->createBlock('adminhtml/widget_grid_column')
 306                ->setData($column)
 307                ->setGrid($this);
 308        }
 309        /*elseif ($column instanceof Varien_Object) {
 310            $this->_columns[$columnId] = $column;
 311        }*/
 312        else {
 313            throw new Exception(Mage::helper('adminhtml')->__('Wrong column format.'));
 314        }
 315
 316        $this->_columns[$columnId]->setId($columnId);
 317        $this->_lastColumnId = $columnId;
 318        return $this;
 319    }
 320
 321    /**
 322     * Add column to grid after specified column.
 323     *
 324     * @param   string $columnId
 325     * @param   array|Varien_Object $column
 326     * @param   string $after
 327     * @return  Mage_Adminhtml_Block_Widget_Grid
 328     */
 329    public function addColumnAfter($columnId, $column, $after)
 330    {
 331        $this->addColumn($columnId, $column);
 332        $this->addColumnsOrder($columnId, $after);
 333        return $this;
 334    }
 335
 336    /**
 337     * Add column view order
 338     *
 339     * @param string $columnId
 340     * @param string $after
 341     * @return Mage_Adminhtml_Block_Widget_Grid
 342     */
 343    public function addColumnsOrder($columnId, $after)
 344    {
 345        $this->_columnsOrder[$columnId] = $after;
 346        return $this;
 347    }
 348
 349    /**
 350     * Retrieve columns order
 351     *
 352     * @return array
 353     */
 354    public function getColumnsOrder()
 355    {
 356        return $this->_columnsOrder;
 357    }
 358
 359    /**
 360     * Sort columns by predefined order
 361     *
 362     * @return Mage_Adminhtml_Block_Widget_Grid
 363     */
 364    public function sortColumnsByOrder()
 365    {
 366        $keys = array_keys($this->_columns);
 367        $values = array_values($this->_columns);
 368
 369        foreach ($this->getColumnsOrder() as $columnId => $after) {
 370            if (array_search($after, $keys) !== false) {
 371                // Moving grid column
 372                $positionCurrent = array_search($columnId, $keys);
 373
 374                $key = array_splice($keys, $positionCurrent, 1);
 375                $value = array_splice($values, $positionCurrent, 1);
 376
 377                $positionTarget = array_search($after, $keys) + 1;
 378
 379                array_splice($keys, $positionTarget, 0, $key);
 380                array_splice($values, $positionTarget, 0, $value);
 381
 382                $this->_columns = array_combine($keys, $values);
 383            }
 384        }
 385
 386        end($this->_columns);
 387        $this->_lastColumnId = key($this->_columns);
 388        return $this;
 389    }
 390
 391    public function getLastColumnId()
 392    {
 393        return $this->_lastColumnId;
 394    }
 395
 396    public function getColumnCount()
 397    {
 398        return count($this->getColumns());
 399    }
 400
 401    /**
 402     * Retrieve grid column by column id
 403     *
 404     * @param   string $columnId
 405     * @return  Varien_Object || false
 406     */
 407    public function getColumn($columnId)
 408    {
 409        if (!empty($this->_columns[$columnId])) {
 410            return $this->_columns[$columnId];
 411        }
 412        return false;
 413    }
 414
 415    /**
 416     * Retrieve all grid columns
 417     *
 418     * @return array
 419     */
 420    public function getColumns()
 421    {
 422        return $this->_columns;
 423    }
 424
 425    protected function _setFilterValues($data)
 426    {
 427        foreach ($this->getColumns() as $columnId => $column) {
 428            if (isset($data[$columnId]) && (!empty($data[$columnId]) || strlen($data[$columnId]) > 0) && $column->getFilter()) {
 429                $column->getFilter()->setValue($data[$columnId]);
 430                $this->_addColumnFilterToCollection($column);
 431            }
 432        }
 433        return $this;
 434    }
 435
 436    protected function _addColumnFilterToCollection($column)
 437    {
 438        if ($this->getCollection()) {
 439            $field = ( $column->getFilterIndex() ) ? $column->getFilterIndex() : $column->getIndex();
 440            if ($column->getFilterConditionCallback()) {
 441                call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);
 442            } else {
 443                $cond = $column->getFilter()->getCondition();
 444                if ($field && isset($cond)) {
 445                    $this->getCollection()->addFieldToFilter($field , $cond);
 446                }
 447            }
 448        }
 449        return $this;
 450    }
 451
 452    /**
 453     * Sets sorting order by some column
 454     *
 455     * @param Mage_Adminhtml_Block_Widget_Grid_Column $column
 456     * @return Mage_Adminhtml_Block_Widget_Grid
 457     */
 458    protected function _setCollectionOrder($column)
 459    {
 460        $collection = $this->getCollection();
 461        if ($collection) {
 462            $columnIndex = $column->getFilterIndex() ?
 463                $column->getFilterIndex() : $column->getIndex();
 464            $collection->setOrder($columnIndex, $column->getDir());
 465        }
 466        return $this;
 467    }
 468
 469    /**
 470     * Prepare grid collection object
 471     *
 472     * @return this
 473     */
 474    protected function _prepareCollection()
 475    {
 476        if ($this->getCollection()) {
 477
 478            $this->_preparePage();
 479
 480            $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
 481            $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
 482            $filter   = $this->getParam($this->getVarNameFilter(), null);
 483
 484            if (is_null($filter)) {
 485                $filter = $this->_defaultFilter;
 486            }
 487
 488            if (is_string($filter)) {
 489                $data = $this->helper('adminhtml')->prepareFilterString($filter);
 490                $this->_setFilterValues($data);
 491            }
 492            else if ($filter && is_array($filter)) {
 493                $this->_setFilterValues($filter);
 494            }
 495            else if(0 !== sizeof($this->_defaultFilter)) {
 496                $this->_setFilterValues($this->_defaultFilter);
 497            }
 498
 499            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
 500                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
 501                $this->_columns[$columnId]->setDir($dir);
 502                $this->_setCollectionOrder($this->_columns[$columnId]);
 503            }
 504
 505            if (!$this->_isExport) {
 506                $this->getCollection()->load();
 507                $this->_afterLoadCollection();
 508            }
 509        }
 510
 511        return $this;
 512    }
 513
 514    /**
 515     * Decode URL encoded filter value recursive callback method
 516     *
 517     * @var string $value
 518     */
 519    protected function _decodeFilter(&$value)
 520    {
 521        $value = $this->helper('adminhtml')->decodeFilter($value);
 522    }
 523
 524    protected function _preparePage()
 525    {
 526        $this->getCollection()->setPageSize($this->getParam($this->getVarNameLimit(), $this->_defaultLimit));
 527        $this->getCollection()->setCurPage($this->getParam($this->getVarNamePage(), $this->_defaultPage));
 528    }
 529
 530    protected function _prepareColumns()
 531    {
 532        $this->sortColumnsByOrder();
 533        return $this;
 534    }
 535
 536    /**
 537     * Prepare grid massaction block
 538     *
 539     * @return Mage_Adminhtml_Block_Widget_Grid
 540     */
 541    protected function _prepareMassactionBlock()
 542    {
 543        $this->setChild('massaction', $this->getLayout()->createBlock($this->getMassactionBlockName()));
 544        $this->_prepareMassaction();
 545        if($this->getMassactionBlock()->isAvailable()) {
 546            $this->_prepareMassactionColumn();
 547        }
 548        return $this;
 549    }
 550
 551    /**
 552     * Prepare grid massaction actions
 553     *
 554     * @return Mage_Adminhtml_Block_Widget_Grid
 555     */
 556    protected function _prepareMassaction()
 557    {
 558
 559        return $this;
 560    }
 561
 562    /**
 563     * Prepare grid massaction column
 564     *
 565     * @return unknown
 566     */
 567    protected function _prepareMassactionColumn()
 568    {
 569        $columnId = 'massaction';
 570        $massactionColumn = $this->getLayout()->createBlock('adminhtml/widget_grid_column')
 571                ->setData(array(
 572                    'index'     => $this->getMassactionIdField(),
 573                    'type'      => 'massaction',
 574                    'name'      => $this->getMassactionBlock()->getFormFieldName(),
 575                    'align'     => 'center',
 576                    'is_system' => true
 577                ));
 578
 579        if ($this->getNoFilterMassactionColumn()) {
 580            $massactionColumn->setData('filter', false);
 581        }
 582
 583        $massactionColumn->setSelected($this->getMassactionBlock()->getSelected())
 584            ->setGrid($this)
 585            ->setId($columnId);
 586
 587        $oldColumns = $this->_columns;
 588        $this->_columns = array();
 589        $this->_columns[$columnId] = $massactionColumn;
 590        $this->_columns = array_merge($this->_columns, $oldColumns);
 591        return $this;
 592    }
 593
 594    protected function _prepareGrid()
 595    {
 596        $this->_prepareColumns();
 597        $this->_prepareMassactionBlock();
 598        $this->_prepareCollection();
 599        return $this;
 600    }
 601
 602    protected function _beforeToHtml()
 603    {
 604        $this->_prepareGrid();
 605        return parent::_beforeToHtml();
 606    }
 607
 608    protected function _afterLoadCollection()
 609    {
 610        return $this;
 611    }
 612
 613    public function getVarNameLimit()
 614    {
 615        return $this->_varNameLimit;
 616    }
 617
 618    public function getVarNamePage()
 619    {
 620        return $this->_varNamePage;
 621    }
 622
 623    public function getVarNameSort()
 624    {
 625        return $this->_varNameSort;
 626    }
 627
 628    public function getVarNameDir()
 629    {
 630        return $this->_varNameDir;
 631    }
 632
 633    public function getVarNameFilter()
 634    {
 635        return $this->_varNameFilter;
 636    }
 637
 638    public function setVarNameLimit($name)
 639    {
 640        return $this->_varNameLimit = $name;
 641    }
 642
 643    public function setVarNamePage($name)
 644    {
 645        return $this->_varNamePage = $name;
 646    }
 647
 648    public function setVarNameSort($name)
 649    {
 650        return $this->_varNameSort = $name;
 651    }
 652
 653    public function setVarNameDir($name)
 654    {
 655        return $this->_varNameDir = $name;
 656    }
 657
 658    public function setVarNameFilter($name)
 659    {
 660        return $this->_varNameFilter = $name;
 661    }
 662
 663    /**
 664     * Set visibility of column headers
 665     *
 666     * @param boolean $visible
 667     */
 668    public function setHeadersVisibility($visible=true)
 669    {
 670        $this->_headersVisibility = $visible;
 671    }
 672
 673    /**
 674     * Return visibility of column headers
 675     *
 676     * @return boolean
 677     */
 678    public function getHeadersVisibility()
 679    {
 680        return $this->_headersVisibility;
 681    }
 682
 683    /**
 684     * Set visibility of pager
 685     *
 686     * @param boolean $visible
 687     */
 688    public function setPagerVisibility($visible=true)
 689    {
 690        $this->_pagerVisibility = $visible;
 691    }
 692
 693    /**
 694     * Return visibility of pager
 695     *
 696     * @return boolean
 697     */
 698    public function getPagerVisibility()
 699    {
 700        return $this->_pagerVisibility;
 701    }
 702
 703    /**
 704     * Set visibility of filter
 705     *
 706     * @param boolean $visible
 707     */
 708    public function setFilterVisibility($visible=true)
 709    {
 710        $this->_filterVisibility = $visible;
 711    }
 712
 713    /**
 714     * Return visibility of filter
 715     *
 716     * @return boolean
 717     */
 718    public function getFilterVisibility()
 719    {
 720        return $this->_filterVisibility;
 721    }
 722
 723    /**
 724     * Set visibility of filter
 725     *
 726     * @param boolean $visible
 727     */
 728    public function setMessageBlockVisibility($visible=true)
 729    {
 730        $this->_messageBlockVisibility = $visible;
 731    }
 732
 733    /**
 734     * Return visibility of filter
 735     *
 736     * @return boolean
 737     */
 738    public function getMessageBlockVisibility()
 739    {
 740        return $this->_messageBlockVisibility;
 741    }
 742
 743    public function setDefaultLimit($limit)
 744    {
 745        $this->_defaultLimit = $limit;
 746        return $this;
 747    }
 748
 749    public function setDefaultPage($page)
 750    {
 751        $this->_defaultPage = $page;
 752        return $this;
 753    }
 754
 755    public function setDefaultSort($sort)
 756    {
 757        $this->_defaultSort = $sort;
 758        return $this;
 759    }
 760
 761    public function setDefaultDir($dir)
 762    {
 763        $this->_defaultDir = $dir;
 764        return $this;
 765    }
 766
 767    public function setDefaultFilter($filter)
 768    {
 769        $this->_defaultFilter = $filter;
 770        return $this;
 771    }
 772
 773    /**
 774     * Retrieve grid export types
 775     *
 776     * @return array
 777     */
 778    public function getExportTypes()
 779    {
 780        return empty($this->_exportTypes) ? false : $this->_exportTypes;
 781    }
 782
 783    /**
 784     * Add new export type to grid
 785     *
 786     * @param   string $url
 787     * @param   string $label
 788     * @return  Mage_Adminhtml_Block_Widget_Grid
 789     */
 790    public function addExportType($url, $label)
 791    {
 792        $this->_exportTypes[] = new Varien_Object(
 793            array(
 794                'url'   => $this->getUrl($url, array('_current'=>true)),
 795                'label' => $label
 796            )
 797        );
 798        return $this;
 799    }
 800
 801     /**
 802     * Retrieve rss lists types
 803     *
 804     * @return array
 805     */
 806    public function getRssLists()
 807    {
 808        return empty($this->_rssLists) ? false : $this->_rssLists;
 809    }
 810
 811     /**
 812     * Returns url for RSS
 813     * Can be overloaded in descendant classes to perform custom changes to url passed to addRssList()
 814     *
 815     * @param string $url
 816     * @return string
 817     */
 818    protected function _getRssUrl($url)
 819    {
 820        $urlModel = Mage::getModel('core/url');
 821        if (Mage::app()->getStore()->getStoreInUrl()) {
 822            // Url in 'admin' store view won't be accessible, so form it in default store view frontend
 823            $urlModel->setStore(Mage::app()->getDefaultStoreView());
 824        }
 825        return $urlModel->getUrl($url);
 826    }
 827
 828     /**
 829     * Add new rss list to grid
 830     *
 831     * @param   string $url
 832     * @param   string $label
 833     * @return  Mage_Adminhtml_Block_Widget_Grid
 834     */
 835    public function addRssList($url, $label)
 836    {
 837        $this->_rssLists[] = new Varien_Object(
 838            array(
 839                'url'   => $this->_getRssUrl($url),
 840                'label' => $label
 841            )
 842        );
 843        return $this;
 844    }
 845
 846    /**
 847     * Retrieve grid HTML
 848     *
 849     * @return string
 850     */
 851    public function getHtml()
 852    {
 853        return $this->toHtml();
 854    }
 855
 856    /**
 857     * Retrieve file content from file container array
 858     *
 859     * @param array $fileData
 860     * @return string
 861     */
 862    protected function _getFileContainerContent(array $fileData)
 863    {
 864        $io = new Varien_Io_File();
 865        $path = $io->dirname($fileData['value']);
 866        $io->open(array('path' => $path));
 867        return $io->read($fileData['value']);
 868    }
 869
 870    /**
 871     * Retrieve Headers row array for Export
 872     *
 873     * @return array
 874     */
 875    protected function _getExportHeaders()
 876    {
 877        $row = array();
 878        foreach ($this->_columns as $column) {
 879            if (!$column->getIsSystem()) {
 880                $row[] = $column->getExportHeader();
 881            }
 882        }
 883        return $row;
 884    }
 885
 886    /**
 887     * Retrieve Totals row array for Export
 888     *
 889     * @return array
 890     */
 891    protected function _getExportTotals()
 892    {
 893        $totals = $this->getTotals();
 894        $row    = array();
 895        foreach ($this->_columns as $column) {
 896            if (!$column->getIsSystem()) {
 897                $row[] = ($column->hasTotalsLabel()) ? $column->getTotalsLabel() : $column->getRowFieldExport($totals);
 898            }
 899        }
 900        return $row;
 901    }
 902
 903    /**
 904     * Iterate collection and call callback method per item
 905     * For callback method first argument always is item object
 906     *
 907     * @param string $callback
 908     * @param array $args additional arguments for callback method
 909     * @return Mage_Adminhtml_Block_Widget_Grid
 910     */
 911    public function _exportIterateCollection($callback, array $args)
 912    {
 913        $originalCollection = $this->getCollection();
 914        $count = null;
 915        $page  = 1;
 916        $lPage = null;
 917        $break = false;
 918
 919        while ($break !== true) {
 920            $collection = clone $originalCollection;
 921            $collection->setPageSize($this->_exportPageSize);
 922            $collection->setCurPage($page);
 923            $collection->load();
 924            if (is_null($count)) {
 925                $count = $collection->getSize();
 926                $lPage = $collection->getLastPageNumber();
 927            }
 928            if ($lPage == $page) {
 929                $break = true;
 930            }
 931            $page ++;
 932
 933            foreach ($collection as $item) {
 934                call_user_func_array(array($this, $callback), array_merge(array($item), $args));
 935            }
 936        }
 937    }
 938
 939    /**
 940     * Write item data to csv export file
 941     *
 942     * @param Varien_Object $item
 943     * @param Varien_Io_File $adapter
 944     */
 945    protected function _exportCsvItem(Varien_Object $item, Varien_Io_File $adapter)
 946    {
 947        $row = array();
 948        foreach ($this->_columns as $column) {
 949            if (!$column->getIsSystem()) {
 950                $row[] = $column->getRowFieldExport($item);
 951            }
 952        }
 953        $adapter->streamWriteCsv($row);
 954    }
 955
 956    /**
 957     * Retrieve a file container array by grid data as CSV
 958     *
 959     * Return array with keys type and value
 960     *
 961     * @return array
 962     */
 963    public function getCsvFile()
 964    {
 965        $this->_isExport = true;
 966        $this->_prepareGrid();
 967
 968        $io = new Varien_Io_File();
 969
 970        $path = Mage::getBaseDir('var') . DS . 'export' . DS;
 971        $name = md5(microtime());
 972        $file = $path . DS . $name . '.csv';
 973
 974        $io->setAllowCreateFolders(true);
 975        $io->open(array('path' => $path));
 976        $io->streamOpen($file, 'w+');
 977        $io->streamLock(true);
 978        $io->streamWriteCsv($this->_getExportHeaders());
 979
 980        $this->_exportIterateCollection('_exportCsvItem', array($io));
 981
 982        if ($this->getCountTotals()) {
 983            $io->streamWriteCsv($this->_getExportTotals());
 984        }
 985
 986        $io->streamUnlock();
 987        $io->streamClose();
 988
 989        return array(
 990            'type'  => 'filename',
 991            'value' => $file,
 992            'rm'    => true // can delete file after use
 993        );
 994    }
 995
 996     /**
 997     * Retrieve Grid data as CSV
 998     *
 999     * @return string
1000     */
1001    public function getCsv()
1002    {
1003        $csv = '';
1004        $this->_isExport = true;
1005        $this->_prepareGrid();
1006        $this->getCollection()->getSelect()->limit();
1007        $this->getCollection()->setPageSize(0);
1008        $this->getCollection()->load();
1009        $this->_afterLoadCollection();
1010
1011        $data = array();
1012        foreach ($this->_columns as $column) {
1013            if (!$column->getIsSystem()) {
1014                $data[] = '"'.$column->getExportHeader().'"';
1015            }
1016        }
1017        $csv.= implode(',', $data)."\n";
1018
1019        foreach ($this->getCollection() as $item) {
1020            $data = array();
1021            foreach ($this->_columns as $column) {
1022                if (!$column->getIsSystem()) {
1023                    $data[] = '"'.str_replace(array('"', '\\'), array('""', '\\\\'), $column->getRowFieldExport($item)).'"';
1024                }
1025            }
1026            $csv.= implode(',', $data)."\n";
1027        }
1028
1029        if ($this->getCountTotals())
1030        {
1031            $data = array();
1032            foreach ($this->_columns as $column) {
1033                if (!$column->getIsSystem()) {
1034                    $data[] = '"'.str_replace(array('"', '\\'), array('""', '\\\\'), $column->getRowFieldExport($this->getTotals())).'"';
1035                }
1036            }
1037            $csv.= implode(',', $data)."\n";
1038        }
1039
1040        return $csv;
1041    }
1042
1043    public function getXml()
1044    {
1045        $this->_isExport = true;
1046        $this->_prepareGrid();
1047        $this->getCollection()->getSelect()->limit();
1048        $this->getCollection()->setPageSize(0);
1049        $this->getCollection()->load();
1050        $this->_afterLoadCollection();
1051        $indexes = array();
1052        foreach ($this->_columns as $column) {
1053            if (!$column->getIsSystem()) {
1054                $indexes[] = $column->getIndex();
1055            }
1056        }
1057        $xml = '<?xml version="1.0" encoding="UTF-8"?>';
1058        $xml.= '<items>';
1059        foreach ($this->getCollection() as $item) {
1060            $xml.= $item->toXml($indexes);
1061        }
1062        if ($this->getCountTotals())
1063        {
1064            $xml.= $this->getTotals()->toXml($indexes);
1065        }
1066        $xml.= '</items>';
1067        return $xml;
1068    }
1069
1070    /**
1071     * Write item data to Excel 2003 XML export file
1072     *
1073     * @param Varien_Object $item
1074     * @param Varien_Io_File $adapter
1075     * @param Varien_Convert_Parser_Xml_Excel $parser
1076     */
1077    protected function _exportExcelItem(Varien_Object $item, Varien_Io_File $adapter, $parser = null)
1078    {
1079        if (is_null($parser)) {
1080            $parser = new Varien_Convert_Parser_Xml_Excel();
1081        }
1082
1083        $row = array();
1084        foreach ($this->_columns as $column) {
1085            if (!$column->getIsSystem()) {
1086                $row[] = $column->getRowFieldExport($item);
1087            }
1088        }
1089        $data = $parser->getRowXml($row);
1090        $adapter->streamWrite($data);
1091    }
1092
1093    /**
1094     * Retrieve a file container array by grid data as MS Excel 2003 XML Document
1095     *
1096     * Return array with keys type and value
1097     *
1098     * @return string
1099     */
1100    public function getExcelFile($sheetName = '')
1101    {
1102        $this->_isExport = true;
1103        $this->_prepareGrid();
1104
1105        $parser = new Varien_Convert_Parser_Xml_Excel();
1106        $io     = new Varien_Io_File();
1107
1108        $path = Mage::getBaseDir('var') . DS . 'export' . DS;
1109        $name = md5(microtime());
1110        $file = $path . DS . $name . '.xml';
1111
1112        $io->setAllowCreateFolders(true);
1113        $io->open(array('path' => $path));
1114        $io->streamOpen($file, 'w+');
1115        $io->streamLock(true);
1116        $io->streamWrite($parser->getHeaderXml($sheetName));
1117        $io->streamWrite($parser->getRowXml($this->_getExportHeaders()));
1118
1119        $this->_exportIterateCollection('_exportExcelItem', array($io, $parser));
1120
1121        if ($this->getCountTotals()) {
1122            $io->streamWrite($parser->getRowXml($this->_getExportTotals()));
1123        }
1124
1125        $io->streamWrite($parser->getFooterXml());
1126        $io->streamUnlock();
1127        $io->streamClose();
1128
1129        return array(
1130            'type'  => 'filename',
1131            'value' => $file,
1132            'rm'    => true // can delete file after use
1133        );
1134    }
1135
1136    /**
1137     * Retrieve grid data as MS Excel 2003 XML Document
1138     *
1139     * @param string $filename the Workbook sheet name
1140     * @return string
1141     */
1142    public function getExcel($filename = '')
1143    {
1144        $this->_isExport = true;
1145        $this->_prepareGrid();
1146        $this->getCollection()->getSelect()->limit();
1147        $this->getCollection()->setPageSize(0);
1148        $this->getCollection()->load();
1149        $this->_afterLoadCollection();
1150        $headers = array();
1151        $data = array();
1152        foreach ($this->_columns as $column) {
1153            if (!$column->getIsSystem()) {
1154                $headers[] = $column->getHeader();
1155            }
1156        }
1157        $data[] = $headers;
1158
1159        foreach ($this->getCollection() as $item) {
1160            $row = array();
1161            foreach ($this->_columns as $column) {
1162                if (!$column->getIsSystem()) {
1163                    $row[] = $column->getRowField($item);
1164                }
1165            }
1166            $data[] = $row;
1167        }
1168
1169        if ($this->getCountTotals())
1170        {
1171            $row = array();
1172            foreach ($this->_columns as $column) {
1173                if (!$column->getIsSystem()) {
1174                    $row[] = $column->getRowField($this->getTotals());
1175                }
1176            }
1177            $data[] = $row;
1178        }
1179
1180        $xmlObj = new Varien_Convert_Parser_Xml_Excel();
1181        $xmlObj->setVar('single_sheet', $filename);
1182        $xmlObj->setData($data);
1183        $xmlObj->unparse();
1184
1185        return $xmlObj->getData();
1186    }
1187
1188    public function canDisplayContainer()
1189    {
1190        if ($this->getRequest()->getQuery('ajax')) {
1191            return false;
1192        }
1193        return true;
1194    }
1195
1196    /**
1197     * Grid url getter
1198     *
1199     * @deprecated after 1.3.2.3 Use getAbsoluteGridUrl() method instead
1200     *
1201     * @return string current grid url
1202     */
1203    public function getGridUrl()
1204    {
1205        return $this->getCurrentUrl();
1206    }
1207
1208    /**
1209     * Grid url getter
1210     * Version of getGridUrl() but with parameters
1211     *
1212     * @param array $params url parameters
1213     * @return string current grid url
1214     */
1215    public function getAbsoluteGridUrl($params = array())
1216    {
1217        return $this->getCurrentUrl($params);
1218    }
1219
1220    /**
1221     * Retrieve grid
1222     *
1223     * @param   string $paramName
1224     * @param   mixed $default
1225     * @return  mixed
1226     */
1227    public function getParam($paramName, $default=null)
1228    {
1229        $session = Mage::getSingleton('adminhtml/session');
1230        $sessionParamName = $this->getId().$paramName;
1231        if ($this->getRequest()->has($paramName)) {
1232            $param = $this->getRequest()->getParam($paramName);
1233            if ($this->_saveParametersInSession) {
1234                $session->setData($sessionParamName, $param);
1235            }
1236            return $param;
1237        }
1238        elseif ($this->_saveParametersInSession && ($param = $session->getData($sessionParamName)))
1239        {
1240            return $param;
1241        }
1242
1243        return $default;
1244    }
1245
1246    public function setSaveParametersInSession($flag)
1247    {
1248        $this->_saveParametersInSession = $flag;
1249        return $this;
1250    }
1251
1252    public function getJsObjectName()
1253    {
1254        return $this->getId().'JsObject';
1255    }
1256
1257    /**
1258     * Deprecated since 1.1.7
1259     *
1260     * @return string
1261     */
1262    public function getRowId($row)
1263    {
1264        return $this->getRowUrl($row);
1265    }
1266
1267    /**
1268     * Retrive massaction row identifier field
1269     *
1270     * @return string
1271     */
1272    public function getMassactionIdField()
1273    {
1274        return $this->_massactionIdField;
1275    }
1276
1277    /**
1278     * Set massaction row identifier field
1279     *
1280     * @param  string    $idField
1281     * @return Mage_Adminhtml_Block_Widget_Grid
1282     */
1283    public function setMassactionIdField($idField)
1284    {
1285        $this->_massactionIdField = $idField;
1286        return $this;
1287    }
1288
1289    /**
1290     * Retrive massaction block name
1291     *
1292     * @return string
1293     */
1294    public function getMassactionBlockName()
1295    {
1296        return $this->_massactionBlockName;
1297    }
1298
1299    /**
1300     * Set massaction block name
1301     *
1302     * @param  string    $blockName
1303     * @return Mage_Adminhtml_Block_Widget_Grid
1304     */
1305    public function setMassactionBlockName($blockName)
1306    {
1307        $this->_massactionBlockName = $blockName;
1308        return $this;
1309    }
1310
1311    /**
1312     * Retrive massaction block
1313     *
1314     * @return Mage_Adminhtml_Block_Widget_Grid_Massaction_Abstract
1315     */
1316    public function getMassactionBlock()
1317    {
1318        return $this->getChild('massaction');
1319    }
1320
1321    public function getMassactionBlockHtml()
1322    {
1323        return $this->getChildHtml('massaction');
1324    }
1325
1326    /**
1327     * Set empty text for grid
1328     *
1329     * @param string $text
1330     * @return Mage_Adminhtml_Block_Widget_Grid
1331     */
1332    public function setEmptyText($text)
1333    {
1334        $this->_emptyText = $text;
1335        return $this;
1336    }
1337
1338    /**
1339     * Return empty text for grid
1340     *
1341     * @return string
1342     */
1343    public function getEmptyText()
1344    {
1345        return $this->_emptyText;
1346    }
1347
1348    /**
1349     * Set empty text CSS class
1350     *
1351     * @param string $cssClass
1352     * @return Mage_Adminhtml_Block_Widget_Grid
1353     */
1354    public function setEmptyTextClass($cssClass)
1355    {
1356        $this->_emptyTextCss = $cssClass;
1357        return $this;
1358    }
1359
1360    /**
1361     * Return empty text CSS class
1362     *
1363     * @return string
1364     */
1365    public function getEmptyTextClass()
1366    {
1367        return $this->_emptyTextCss;
1368    }
1369
1370    /**
1371     * Set count totals
1372     *
1373     * @param boolean $visible
1374     */
1375    public function setCountTotals($count=true)
1376    {
1377        $this->_countTotals = $count;
1378    }
1379
1380    /**
1381     * Return count totals
1382     *
1383     * @return boolean
1384     */
1385    public function getCountTotals()
1386    {
1387        return $this->_countTotals;
1388    }
1389
1390    /**
1391     * Set totals
1392     *
1393     * @param boolean $visible
1394     */
1395    public function setTotals(Varien_Object $totals)
1396    {
1397        $this->_varTotals = $totals;
1398    }
1399
1400    /**
1401     * Retrieve totals
1402     *
1403     * @return Varien_Object
1404     */
1405    public function getTotals()
1406    {
1407        return $this->_varTotals;
1408    }
1409
1410    /**
1411     * Set subtotals
1412     *
1413     * @param boolean $flag
1414     * @return Mage_Adminhtml_Block_Widget_Grid
1415     */
1416    public function setCountSubTotals($flag = true)
1417    {
1418        $this->_countSubTotals = $flag;
1419        return $this;
1420    }
1421
1422    /**
1423     * Return count subtotals
1424     *
1425     * @return boolean
1426     */
1427    public function getCountSubTotals()
1428    {
1429        return $this->_countSubTotals;
1430    }
1431
1432    /**
1433     * Set subtotal items
1434     *
1435     * @param array $items
1436     * @return Mage_Adminhtml_Block_Widget_Grid
1437     */
1438    public function setSubTotals(array $items)
1439    {
1440        $this->_subtotals = $items;
1441        return $this;
1442    }
1443
1444    /**
1445     * Retrieve subtotal item
1446     *
1447     * @param Varien_Object $item
1448     * @return Varien_Object
1449     */
1450    public function getSubTotalItem($item)
1451    {
1452        foreach ($this->_subtotals as $subtotalItem) {
1453            foreach ($this->_groupedColumn as $groupedColumn) {
1454                if ($subtotalItem->getData($groupedColumn) == $item->getData($groupedColumn)) {
1455                    return $subtotalItem;
1456                }
1457            }
1458        }
1459        return '';
1460    }
1461
1462    /**
1463     * Retrieve subtotal items
1464     *
1465     * @return array
1466     */
1467    public function getSubTotals()
1468    {
1469        return $this->_subtotals;
1470    }
1471
1472    /**
1473     * Check whether subtotal should be rendered
1474     *
1475     * @param Varien_Object $item
1476     * @return boolean
1477     */
1478    public function shouldRenderSubTotal($item) {
1479        return ($this->_countSubTotals && count($this->_subtotals) > 0 && count($this->getMultipleRows($item)) > 0);
1480    }
1481
1482    /**
1483     * Retrieve columns to render
1484     *
1485     * @return unknown
1486     */
1487    public function getSubTotalColumns() {
1488        return $this->getColumns();
1489    }
1490
1491    /**
1492     * Retrieve rowspan number
1493     *
1494     * @param Varien_Object $item
1495     * @param Mage_Adminhtml_Block_Widget_Grid_Column $column
1496     * @return integer|boolean
1497     */
1498    public function getRowspan($item, $column)
1499    {
1500        if ($this->isColumnGrouped($column)) {
1501            return count($this->getMultipleRows($item)) + count($this->_groupedColumn);
1502        }
1503        return false;
1504    }
1505
1506    /**
1507     * Enter description here...
1508     *
1509     * @param string|object $column
1510     * @param string $value
1511     * @return boolean|Mage_Adminhtml_Block_Widget_Grid
1512     */
1513    public function isColumnGrouped($column, $value = null)
1514    {
1515        if (null === $value) {
1516            if (is_object($column)) {
1517                return in_array($column->getIndex(), $this->_groupedColumn);
1518            }
1519            return in_array($column, $this->_groupedColumn);
1520        }
1521        $this->_groupedColumn[] = $column;
1522        return $this;
1523    }
1524
1525    /**
1526     * Get children of specified item
1527     *
1528     * @param Varien_Object $item
1529     * @return array
1530     */
1531    public function getMultipleRows($item)
1532    {
1533        return $item->getChildren();
1534    }
1535
1536    /**
1537     * Retrieve columns for multiple rows
1538     *
1539     * @param Varien_Object $item
1540     * @return array
1541     */
1542    public function getMultipleRowColumns()
1543    {
1544        $columns = $this->getColumns();
1545        foreach ($this->_groupedColumn as $column) {
1546            unset($columns[$column]);
1547        }
1548        return $columns;
1549    }
1550
1551    /**
1552     * Check whether should render cell
1553     *
1554     * @param Varien_Object $item
1555     * @param Mage_Adminhtml_Block_Widget_Grid_Column $column
1556     * @return boolean
1557     */
1558    public function shouldRenderCell($item, $column)
1559    {
1560        if ($this->isColumnGrouped($column) && $item->getIsEmpty()) {
1561            return true;
1562        }
1563        if (!$item->getIsEmpty()) {
1564            return true;
1565        }
1566        return false;
1567    }
1568
1569    /**
1570     * Check whether should render empty cell
1571     *
1572     * @param Varien_Object $item
1573     * @param Mage_Adminhtml_Block_Widget_Grid_Column $column
1574     * @return boolean
1575     */
1576    public function shouldRenderEmptyCell($item, $column)
1577    {
1578        return ($item->getIsEmpty() && in_array($column['index'], $this->_groupedColumn));
1579    }
1580
1581    /**
1582     * Retrieve colspan for empty cell
1583     *
1584     * @param Varien_Object $item
1585     * @return integer
1586     */
1587    public function getEmptyCellColspan()
1588    {
1589        return $this->getColumnCount() - count($this->_groupedColumn);
1590    }
1591
1592    /**
1593     * Retrieve label for empty cell
1594     *
1595     * @return string
1596     */
1597    public function getEmptyCellLabel()
1598    {
1599        return $this->_emptyCellLabel;
1600    }
1601
1602    /**
1603     * Set label for empty cell
1604     *
1605     * @param string $label
1606     * @return Mage_Adminhtml_Block_Widget_Grid
1607     */
1608    public function setEmptyCellLabel($label)
1609    {
1610        $this->_emptyCellLabel = $label;
1611        return $this;
1612    }
1613
1614    /**
1615     * Return row url for js event handlers
1616     *
1617     * @param Mage_Catalog_Model_Product|Varien_Object
1618     * @return string
1619     */
1620    public function getRowUrl($item)
1621    {
1622        $res = parent::getRowUrl($item);
1623        return ($res ? $res : '#');
1624    }
1625
1626}