Creation of a fully customized product catalog

Erstellt am: Montag 10 Juli 2017  |  Letzte Änderung am: Samstag 11 August 2018

The example of this article shows in brief steps how you can use SimpleCatalog to create a custom catalog output, with your own programmed logic.

Step by step

  1. Create category named Products
  2. Create some products, which are related to the new Products category
  3. Create a new theme or use an existing one
  4. Create template.php, functions.php files within the theme directory
  5. Download and Install Bootstrap (optional, but I used it in my example in order to move forward faster)
  6. Create styles.css file in your css folder
  7. Create a new GS page named Catalog, and assign the template.php file to it

Files and their contents

1. template.php

<?php if(!defined('IN_GS')){ die('you cannot load this page directly.'); } ?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Catalog Template</title>

    <!-- Bootstrap -->
    <link href="<?php get_theme_url(); ?>/css/bootstrap.min.css" rel="stylesheet">
    <link href="<?php get_theme_url(); ?>/css/styles.css" rel="stylesheet">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<div class="jumbotron">
    <div class="container">
        <h1>Product List</h1>

        <p>Product list example based on ItemManager and SimpleCatalog plugin</p>
        <p>
            <a class="btn btn-lg btn-primary" href="#" role="button">View navbar docs »</a>
        </p>
    </div>
</div>
<div class="container">
    <?php
    echo ($msg) ? $msg : '';
    // Item list view
    if($items) {
    ?>
        <div class="well well-sm breadcrumbs">
            <?php
            // Build the breadcrumb navigation
            echo '<a href="'.$catalog->processor->config->startPageUri.'">'.$category->name.'</a>';
            if($urlSegments[0] == 'tags') {
                echo '<span class="bc-separator">›</span><span class="bc-active">Tags</span>';
            }
            ?>
        </div>
        <div id="products" class="row list-group">
        <?php
        foreach($items as $item) {
        ?>
            <div class="item  col-xs-4 col-lg-4">
                <div class="thumbnail">
                    <?php echo isset($item->thumbnail) ? '<a href="'.$catalog->processor->config->startPageUri.$item->slug.'/">
                        <img class="group list-group-image" src="'.$item->thumbnail.'" alt="'.$item->image_title[0].'" /></a>' : ''; ?>
                    <div class="caption">
                        <h4 class="group inner list-group-item-heading">
                            <?php
                            // Make the product title clickable
                            echo '<a href="'.$catalog->processor->config->startPageUri.$item->slug.'/">'.$item->name.'</a>';
                            ?>
                        </h4>
                        <p class="group inner list-group-item-text">
                            <?php echo $item->summary ?></p>
                        <div class="row">
                            <div class="col-xs-12">
                                <p class="ts-1"><?php echo $item->tags ?></p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        <?php
        }
        echo $pagination;
        ?>
        </div>
    <?php
    // Item details view
    } elseif(isset($currentItem->id)) {
    ?>
        <div class="well well-sm breadcrumbs">
            <?php
            // Build the breadcrumb navigation
            echo '<a href="'.$catalog->processor->config->startPageUri.'">'.$category->name.'</a>';
            if(isset($currentItem->id)) {
                echo '<span class="bc-separator">›</span><span class="bc-active">Product details</span>';
            }
            ?>
        </div>
        <div class="container row item-wrapper">
            <h2><?php echo $currentItem->name ?></h2>
            <p><span class="text-muted">Similar articles:</span> <?php echo $currentItem->tags ?></p>
            <hr>
            <div class="col-md-1">
                <p class="item-date"><?php echo ($currentItem->updated) ?
                        date('j. M', $currentItem->updated) : date('j. M', $currentItem->created) ?></p>
            </div>
            <div class="col-md-6">
                <?php echo $currentItem->description; ?>
            </div>

            <div class="col-md-5">
                <figure>
                    <?php echo ($currentItem->thumbnail) ? '<img class="group list-group-image" src="'.
                        $currentItem->thumbnail.'" alt="'.$currentItem->image_title[0].'" />' : ''; ?>
                </figure>
            </div>
        </div>
    <?php
    // Default page content
    } else {
        get_page_content();
    }
    ?>
</div>
<footer>
    <div class="footer-bottom">
        <div class="container">
            <p class="pull-left">Based on <a href="#">SimpleCatalog</a> and <a href="#">ItemManager</a></p>
        </div>
    </div>
</footer>

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="<?php get_theme_url(); ?>/js/bootstrap.min.js"></script>
</body>
</html>

2. functions.php

Remember to adjust the $category_id below according to your real Product category!

<?php
/**
 *** Enter here the ID of the products category ***
 *
 */
$category_id = 3;
/**
 * URL segments array after catalog www.my-site.com/catalog/(segment-1/segment-2/etc...)
 */
$urlSegments = getUrlSegments();
/**
 * Shorten config
 */
$config = $catalog->processor->config;
/**
 * GS page slug
 */
$slug = get_page_slug(false);
/**
 * Declare some vars
 *
 * @route       - Current catalog route
 * @items       - Item array (List view)
 * @currentItem - Current item object (Item details view)
 * @category    - Current category object
 * @msg         - Error/Notice message
 */
$route = array();
$items = array();
$currentItem = null;
$category = null;
$msg = null;
/**
 * Get the catalog route
 */
if($catalog->router->isRouteExists($urlSegments[0])) {
    $route = $catalog->router->getRoute($urlSegments[0]);
}
/**
 * Get the current item object
 */
if(!empty($route['id'])) {
    $currentItem = $catalog->processor->getItem($route['categoryid'], $route['id']);
}
/**
 * Check if the categy exists, select it
 */
$category = $catalog->processor->getItem(
    $config->dummyCategoryId, $category_id
);
// Item details page data
if(isset($currentItem->id))
{
    // Create thumbnail if it does not exist yet
    $currentItem->thumbnail = \ImCatalog\Util::getResizedUrl($currentItem, 0, 700, 0, 'resize');
    // Build our tags output
    $tags = array_map('trim', explode(',', $currentItem->tags));
    // Override the default tags variable
    $currentItem->tags = '';
    foreach($tags as $tag) {
        $currentItem->tags .= ($tag) ?
            '<span class="tag"><a href="'.$config->startPageUri.'tags/'.strtolower($tag).'/">'.$tag.'</a></span>' : '';
    }
// Item list page data
} elseif($slug == $config->catalogStartPage)
{
    // Intercept the tags input
    $tag_selector = '';
    $pager_prefix = '';
    if($urlSegments[0] == 'tags' && isset($urlSegments[1]))
    {
        $tag_selector = '&&tags=%' . $catalog->imanager->sanitizer->text($urlSegments[1]) . '%';
        $pager_prefix = $urlSegments[0] . '/' . $urlSegments[1] . '/';
    }
    if(!empty($category->id))
    {
        $params = array(
            'section' => 'frontend',
            'selector' => 'active=1'.$tag_selector,
            'pageurl' => $config->startPageUri.$pager_prefix.'page',
            'perpage' => 3,
            'tagurl' => (isset($_GET['tags']) ? $catalog->imanager->sanitizer->text($_GET['tags']) : '')
        );
        $result = $catalog->processor->getItems($category->id, $params);
    } else
    {
        $msg = '<div class="alert alert-danger">' .
            '<strong>Warning:</strong> The category ID "'.(int)$category_id.'" does not exist yet.' .
            '</div>';
    }
    $pagination = '';
    if(!empty($result['items']))
    {
        $items = itemsPrepare($result['items']);
        $pagination = ($result['pagination']) ?
            '<div class="container bts-24 pull-left">'.$result['pagination'].'</div>' : '';
    }
}
/**
 * Prepare the SimpleItem objects for output
 *
 * @param array $items - An array with SimpleItem objects
 *
 * @return array - Prepared array with SimpleItem objects
 */
function itemsPrepare($items = array())
{
    global $catalog;
    foreach($items as $item)
    {
        // Create thumbnail if it does not exist yet
        $item->thumbnail = \ImCatalog\Util::getResizedUrl($item, 0, 0, 360, 'resize');
        // Build our tags output
        $tags = array_map('trim', explode(',', $item->tags));
        // Override the default tags variable
        $item->tags = '';
        foreach($tags as $tag) {
            $item->tags .= ($tag) ?
                '<span class="tag"><a href="'.
                    $catalog->processor->config->startPageUri.'tags/'.strtolower($tag).'/">'.$tag.'</a></span>' : '';
        }
    }
    return $items;
}
/**
 * It's an URL segmentation function
 *
 * Separates a segment part of the URL: "www.my-site.com/catalog/(segment)" by slashes, for instance:
 * "www.my-site.com/catalog/tags/clothing/" becomes "array(0 => 'tags', 1 => 'clothing')"
 *
 *
 * @return array|null - URL segments
 *
 */
function getUrlSegments()
{
    if(!isset($_GET['seg'])) return null;
    global $catalog;
    return explode('/', $catalog->imanager->sanitizer->text(trim($_GET['seg'], '/')));
}

3. styles.css

figure {
    overflow: hidden;
}
figure img {
    max-width: 100%;
}
.glyphicon { 
    margin-right:5px; 
}
.thumbnail {
    margin-bottom: 20px;
    padding: 0px;
    -webkit-border-radius: 0px;
    -moz-border-radius: 0px;
    border-radius: 0px;
}
.item.list-group-item {
    float: none;
    width: 100%;
    background-color: #fff;
    margin-bottom: 10px;
}
.item.list-group-item:nth-of-type(odd):hover,.item.list-group-item:hover {
    background: #428bca;
}
.item.list-group-item .list-group-image {
    margin-right: 10px;
}
.item.list-group-item .thumbnail {
    margin-bottom: 0px;
}
.item.list-group-item .caption {
    padding: 9px 9px 0px 9px;
}
.item.list-group-item:nth-of-type(odd) {
    background: #eeeeee;
}
.item.list-group-item:before, .item.list-group-item:after {
    display: table;
    content: " ";
}
.item.list-group-item img {
    float: left;
}
.item.list-group-item:after {
    clear: both;
}
.list-group-item-text {
    margin: 0 0 11px;
}
.tag {
    display: inline-block;
    margin-right: 3px;
}
.tag a {
    display: inline-block;
    background-color: #fff;
    padding: 2px 10px;
    margin-bottom: 3px;
    border: solid 1px #d2d7dc;
    border-radius: 2em;
    line-height: 140%;
    text-decoration: none;
}
.tag a:hover {
    text-decoration: none;
    border-color: #b9bec3;
}
/* global stuff */
.ts-1 {
    margin-top: 10px;
}
.bts-24 {
    margin-top: 20px;
    margin-bottom: 40px;
}
.item-wrapper {
    margin-bottom: 100px;
}
.item-date {
    font-size: 16px;
}
/* Breadcrumbs */
.bc-separator {
    display: inline-block;
    margin: 0 10px;
    color: #999;
}
.bc-active {
    color: #999;
}
/* Pagination */
.paginator-wrapper a {
    padding: 9px 14px;
    margin: 0;
    color: #555;
    text-decoration: none;
    font-weight: normal;
    border: solid 1px #ddd;
}
.paginator-wrapper .paginator-current {
    background-color: #eee;
}
.paginator-wrapper .paginator-disabled, .paginator-wrapper .paginator-current {
    padding: 9px 14px;
    border: solid 1px #ddd;
    background-color: #f8f8f8;
}
.paginator-wrapper span {
    margin: 0;
}
.footer-bottom {
    border-top: 1px solid #DDDDDD;
    padding-top: 10px;
    padding-bottom: 10px;
}
.footer-bottom p.pull-left {
    padding-top: 6px;
}
.payments {
    font-size: 1.5em;
}

Next three-lines is an addition to the default GetSimple .htaccess file and must be inserted above the native GS rule:

# Catalog rules
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(catalog)/?(.*)/(page[1-9]?)?$ index.php?id=$1&seg=$2&page=$3 [QSA,L]

# Native GS rules
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule /?([A-Za-z0-9-]+)/?$ index.php?id=$1 [QSA,L]

Demo catalog

Autor: Bigin  |  Tags:  FrameworkPHPGetSimpleDevelopmentItemManager