Seditio Source
Root |
./othercms/ips_4.3.4/applications/nexus/modules/front/store/store.php
<?php
/**
 * @brief        Browse Store
 * @author        <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright    (c) Invision Power Services, Inc.
 * @license        https://www.invisioncommunity.com/legal/standards/
 * @package        Invision Community
 * @subpackage    Nexus
 * @since        29 Apr 2014
 */

namespace IPS\nexus\modules\front\store;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
   
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
    exit;
}

/**
 * Browse Store
 */
class _store extends \IPS\Dispatcher\Controller
{
   
/**
     * @brief    Products per page
     */
   
protected static $productsPerPage = 50;
   
   
/**
     * Execute
     *
     * @return    void
     */
   
public function execute()
    {
        \
IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store.css', 'nexus' ) );

        if ( \
IPS\Theme::i()->settings['responsive'] )
        {
            \
IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'store_responsive.css', 'nexus', 'front' ) );
        }
       
       
parent::execute();
    }

   
/**
     * Browse Store
     *
     * @return    void
     */
   
protected function manage()
    {
       
/* Work out currency */
       
if ( isset( \IPS\Request::i()->currency ) and in_array( \IPS\Request::i()->currency, \IPS\nexus\Money::currencies() ) )
        {
            if ( isset( \
IPS\Request::i()->csrfKey ) and \IPS\Request::i()->csrfKey === \IPS\Session\Front::i()->csrfKey )
            {
               
$_SESSION['cart'] = array();
               
$_SESSION['currency'] = \IPS\Request::i()->currency;
            }
           
$currency = \IPS\Request::i()->currency;
        }
        else
        {
           
$currency = \IPS\nexus\Customer::loggedIn()->defaultCurrency();
        }
       
       
/* If we have a category, display it */
       
if ( isset( \IPS\Request::i()->cat ) )
        {
            try
            {
               
$category = \IPS\nexus\Package\Group::loadAndCheckPerms( \IPS\Request::i()->cat );
               
                if ( \
IPS\Request::i()->view )
                {
                    \
IPS\Request::i()->setCookie( 'storeView', ( \IPS\Request::i()->view == 'list' ) ? 'list' : 'grid', \IPS\DateTime::ts( time() )->add( new \DateInterval( 'P1Y' ) ) );
                    \
IPS\Request::i()->cookie['storeView'] = ( \IPS\Request::i()->view == 'list' ) ? 'list' : 'grid';
                }

               
$subcategories = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_package_groups', array( 'pg_parent=?', $category->id ), 'pg_position ASC' ), 'IPS\nexus\Package\Group' );
               
               
$joins = array();
                switch ( \
IPS\Request::i()->sortby )
                {
                    case
'name':
                       
$joins['core_sys_lang_words'] = array( "word_app='nexus' AND word_key=CONCAT( 'nexus_package_', p_id ) AND lang_id=?", \IPS\Member::loggedIn()->language()->id );
                       
$sortBy = 'word_custom';
                        break;
                       
                    case
'price_low':
                    case
'price_high':
                       
$joins['nexus_package_base_prices'] = array( 'id=p_id' );
                       
$sortBy = \IPS\Request::i()->sortby == 'price_low' ? $currency : ( $currency . ' DESC' );
                        break;
                       
                    case
'rating':
                       
$sortBy = 'p_rating DESC';
                        break;
                       
                    default:
                       
$sortBy = 'p_position';
                        break;
                }
               
               
$currentPage = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;

                if(
$currentPage < 1 )
                {
                   
$currentPage = 1;
                }

               
$select = \IPS\Db::i()->select( '*', 'nexus_packages', array(
                    array(
'p_group=?', $category->id ),
                    array(
'p_store=1' ),
                    array(
"( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )' )
                ),
$sortBy, array( ( $currentPage - 1 ) * static::$productsPerPage, static::$productsPerPage ), NULL, NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS );
                foreach (
$joins as $table => $clause )
                {
                   
$select->join( $table, $clause );
                }
               
               
$packages = new \IPS\Patterns\ActiveRecordIterator( $select, 'IPS\nexus\Package' );
               
$totalCount = \IPS\Db::i()->select( 'count(*)', 'nexus_packages', array(
                    array(
'p_group=?', $category->id ),
                    array(
'p_store=1' ),
                    array(
"( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )' )
                ) )->
first();
               
               
$totalPages = ceil( $packages->count( TRUE ) / static::$productsPerPage );
                if (
$totalPages and $currentPage > $totalPages )
                {
                    \
IPS\Output::i()->redirect( $category->url()->setQueryString( 'page', $totalPages ), NULL, 303 );
                }
               
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $category->url(), $totalPages, $currentPage, static::$productsPerPage );
               
               
$packagesWithCustomFields = array();
                foreach (
iterator_to_array( \IPS\Db::i()->select( 'cf_packages', 'nexus_package_fields', 'cf_purchase=1' ) ) as $ids )
                {
                   
$packagesWithCustomFields = array_merge( $packagesWithCustomFields, array_filter( explode( ',', $ids ) ) );
                }
               
                \
IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('store')->categorySidebar( $category, $subcategories );                
                \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->category( $category, $subcategories, $packages, $pagination, $packagesWithCustomFields, $totalCount );
               
                foreach (
$category->parents() as $parent )
                {
                    \
IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
                }
                \
IPS\Output::i()->breadcrumb[] = array( NULL, $category->_title );
                \
IPS\Output::i()->title = $category->_title;

               
/* Add JSON-LD
                    @note Google does not like categories marked up and instead recommends marking up each product separately.
                    @link https://developers.google.com/search/docs/guides/intro-structured-data#multiple-entities-on-the-same-page */
               
foreach( $packages as $package )
                {
                   
$item    = \IPS\nexus\Package\Item::load( $package->id );

                    try
                    {
                       
$price = $package->price();
                    }
                    catch( \
OutOfBoundsException $e )
                    {
                       
$price = NULL;
                    }

                   
/* A product MUST have an offer, so if there's no price (i.e. due to currency configuration) don't even output */
                   
if( $price !== NULL )
                    {
                        \
IPS\Output::i()->jsonLd['package' . $package->id ]    = array(
                           
'@context'        => "http://schema.org",
                           
'@type'            => "Product",
                           
'name'            => $package->_title,
                           
'description'    => strip_tags( $item->truncated() ),
                           
'category'        => $category->_title,
                           
'url'            => (string) $package->url(),
                           
'sku'            => $package->id,
                           
'offers'        => array(
                                               
'@type'            => 'Offer',
                                               
'availability'    => ( $package->stock > 0 OR $package->stock == -1 ) ? 'http://schema.org/InStock' : 'http://schema.org/OutOfStock',
                                               
'price'            => $price->amountAsString(),
                                               
'priceCurrency'    => $price->currency,
                                               
'seller'        => array(
                                                                   
'@type'        => 'Organization',
                                                                   
'name'        => \IPS\Settings::i()->board_name
                                                               
),
                                            ),
                        );

                        if(
$package->image )
                        {
                            \
IPS\Output::i()->jsonLd['package' . $package->id ]['image'] = (string) $package->image;
                        }

                        if(
$package->reviewable )
                        {
                            \
IPS\Output::i()->jsonLd['package' . $package->id ]['aggregateRating'] = array(
                               
'@type'            => 'AggregateRating',
                               
'ratingValue'    => $item->averageReviewRating(),
                               
'ratingCount'    => $item->reviews
                           
);
                        }
                    }
                }

                return;
            }
            catch ( \
OutofRangeException $e )
            {
                \
IPS\Output::i()->error( 'node_error', '1X241/1', 404, '' );
            }
        }
       
       
/* Otherwise, display the index */
       
else
        {
           
/* New Products */
           
$newProducts = array();
           
$nexus_store_new = explode( ',', \IPS\Settings::i()->nexus_store_new );
            if (
$nexus_store_new[0] )
            {
               
$newProducts = \IPS\nexus\Package\Item::getItemsWithPermission( array( array( 'p_date_added>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $nexus_store_new[1] . 'D' ) )->getTimestamp() ) ), 'p_date_added DESC', $nexus_store_new[0] );
            }
           
           
/* Popular Products */
           
$popularProducts = array();
           
$nexus_store_popular = explode( ',', \IPS\Settings::i()->nexus_store_popular );
            if (
$nexus_store_popular[0] )
            {
               
$where = array();
               
$where[] = array( 'ps_app=? AND ps_type=? AND ps_start>?', 'nexus', 'package', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . $nexus_store_popular[1] . 'D' ) )->getTimestamp() );
               
$where[] = "( p_member_groups='*' OR " . \IPS\Db::i()->findInSet( 'p_member_groups', \IPS\Member::loggedIn()->groups ) . ' )';
               
$where[] = array( 'p_store=?', 1 );

               
$popularIds = \IPS\Db::i()->select( 'nexus_purchases.ps_item_id', 'nexus_purchases', $where, 'COUNT(ps_item_id) DESC', $nexus_store_popular[0], 'ps_item_id' )->join( 'nexus_packages', 'ps_item_id=p_id' );
                if(
count( $popularIds ) )
                {
                   
$popularProducts = new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( 'nexus_packages.*', 'nexus_packages', array( \IPS\Db::i()->in( 'p_id', iterator_to_array( $popularIds ) ) ), 'FIELD(p_id, ' . implode( ',', iterator_to_array($popularIds) ) . ')' ), 'IPS\nexus\Package' );
                }
            }
                       
           
/* Display */
           
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('store')->categorySidebar( );
            \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->index( \IPS\nexus\Customer::loggedIn()->cm_credits[ $currency ], $newProducts, $popularProducts );
            \
IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__nexus_store');
        }
    }
   
   
/**
     * Registration Packages
     *
     * @return    void
     */
   
public function register()
    {
        \
IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
        \
IPS\Output::i()->sidebar['enabled'] = FALSE;
        \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->register( \IPS\nexus\Package\Item::getItemsWithPermission( array( array( 'p_reg=1' ) ), 'pg_position, p_position', 10, 'read', \IPS\Content\Hideable::FILTER_AUTOMATIC, 0, NULL, TRUE ) );
        \
IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('sign_up');
    }
   
   
/**
     * View Cart
     *
     * @return    void
     */
   
protected function cart()
    {
        \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('store')->cart();
    }
}