code:
<?php
namespace {
/**
 * Enfold Child Theme - Starter
 *
 * @since Enfold Starter 1.0
 *
 * Add your own functions here. You can also copy some of the theme functions into this file.
 * Wordpress will use those functions instead of the original functions then.
 *
 * @link http://www.kriesi.at/documentation/enfold/using-a-child-theme/
 */

/**
 *	Add filter to add or replace Enfold ALB shortcodes with new folder contents
 *
 *	Note that the shortcodes must be in the same format as those in
 *	enfold/config-templatebuilder/avia-shortcodes
 *
 *	@link http://www.kriesi.at/documentation/enfold/add-new-or-replace-advanced-layout-builder-elements-from-child-theme/
 */

add_filter('avia_load_shortcodes', 'avia_include_shortcode_template', 15, 1);
function avia_include_shortcode_template($paths)
{
	$template_url = get_stylesheet_directory();
    	array_unshift($paths, $template_url.'/shortcodes/');

	return $paths;
}

/**
 *	Turn on Custom CSS Class field for all Avia Layout Builder elements
 *	@link http://www.kriesi.at/documentation/enfold/turn-on-custom-css-field-for-all-alb-elements/
 */
add_theme_support('avia_template_builder_custom_css');
}

namespace ITSociaal\Themes\Houtgrutter
{
	const LIBDIR = __DIR__ . "/lib";
	const SRCDIR = __DIR__ . "/src";

	require_once LIBDIR . '/Autoloader.php';
	class_alias("Paulyg\\Autoloader", __NAMESPACE__ . "\\Autoloader");

	function do_autoloader($namespaces)
	{
		return array_map(
			'call_user_func_array',
			array_fill(
				0,
				count($namespaces),
				[new Autoloader, "addPsr4"]
			),
			$namespaces
		);
	}

	function theme_root_path()
	{
		$ret = __DIR__;

		if (defined("STYLESHEETPATH")) {
			assert(constant("STYLESHEETPATH") === $ret);
		}

		return $ret;
	}

	do_autoloader([
		[__NAMESPACE__, SRCDIR],
		["ErrorDumper", LIBDIR . "/error-dumper/src"],
		//["Cypress\\Curry", LIBDIR . "/php-curry"],
	]);

	if (defined("WP_DEBUG") && constant("WP_DEBUG")) {
		if (!is_admin() && (PHP_SAPI != "cli")) {
			\ErrorDumper\Magic::registerErrorDumper();
		}

		error_reporting(~0);
	}

	if (!isset($_REQUEST["page"])) {
		$_REQUEST["page"] = "";
	}

	\add_filter("posts_results", function($posts) {
		// Fix for wp_query with virtual pages
		if (isset($posts[0])
		&& isset($posts[0]->ID)
		&& (0 == $posts[0]->ID)
		) {
			// Set to some unregistered type to prevent errors
			$posts[0]->post_type =
				strtolower(array_reverse(explode("\\", __NAMESPACE__))[0]);
		}

		return $posts;
	}, 32767);

	\add_filter("kriesi_backlink", F::always(""));
	\add_filter("avf_google_fontlist", F::always(
		"Titillium+Web:600,600italic|Ubuntu:400,400italic"
	));

	\add_action("wp_enqueue_scripts", function() {
		wp_deregister_script("avia-compat");
		wp_deregister_script("avia-default");
		wp_deregister_script("avia-shortcodes");
		wp_deregister_script("avia-popup");

		$base_uri = \get_stylesheet_directory_uri();
		wp_enqueue_script("avia-compat", "$base_uri/assets/avia-compat.js", ["jquery"], 2, false );
		wp_enqueue_script("avia-default", "$base_uri/assets/avia.js", ["jquery"], 3, false);
		wp_enqueue_script("avia-shortcodes", "$base_uri/assets/shortcodes.js", ["jquery"], 3, false);
	}, 1024);

	\add_action("ava_after_main_title", function() {
		if (is_shopp_catalog_frontpage ())
			TemplateController::main("laura/advertentie");
	}, 1024);

	\add_action("wp_head", function() {
		$uri = \get_stylesheet_directory_uri() . "/assets/ie9.css";
		?>

<!--[if IE lte 9]>
	<link rel="stylesheet" href="<?=$uri?>" type="text/css"/>
<![endif]-->

		<?php
	});
}

/* vi:set ts=4 sw=4 noet: */

repo_name: ITSociaal/hg

license: mit


code:
<?php
/**
 * Paulyg/Autoloader - A slightly different PSR-0 and PSR-4 compatable class autoloader.
 *
 * Copyright 2012-2013 Paul Garvin <paul@paulgarvin.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
namespace Paulyg;

/**
 * This autoloader class supports PSR-0 rules, PEAR type class mappings, and
 * the newly adopted PSR-4 class mapping rules.
 *
 * The inner workings of the autoloader are different from most of the other
 * implementations out there as well. Each time you add a namespace or class
 * prefix with the addPsr0() or addPsr4() methods it creates a Closure and
 * registers that with the PHP's SPL autoloader stack.
 *
 * The addPsr0() or addPsr4() functions only accept a string as the $path
 * argument whereas other implementations allow an array of paths here.
 * But you can call addPsr0() and addPsr4() multiple times with the same
 * $prefix. Each call will register a different Closure with PHP. You can
 * affect the order directories are looked in by prepending to the stack
 * instead of the deault of appending.
 *
 * The PHP engine will be responsible for looping through all the Closures
 * registered on the stack vs. the way most implementations work, foreaching
 * through an array of paths in userland code. Allowing the PHP engine to do
 * iteration should be faster. Also since each add* call registers with the
 * SPL autoload stack automatically there is no need to call a separate
 * register() function as is the case with most other framework autoloaders.
 *
 * @author Paul Garvin <paul@paulgarvin.net>
 * @copyright Copyright 2012-2013 Paul Garvin.
 * @license MIT License
 */
class Autoloader
{
    protected static $autoloaders = array();

    public static function addPsr0($prefix, $path, $prepend = false)
    {
        $key = self::getHashKey($prefix, $path);
        $prefix = ltrim($prefix, '\\');
        $path = rtrim($path, DIRECTORY_SEPARATOR);

        $autoloader = function($fqcn) use ($prefix, $path) {
            if (strpos($fqcn, $prefix) !== 0) {
                return;
            }

            $relpath = Autoloader::class2Path($fqcn);
            $file = $path . DIRECTORY_SEPARATOR . $relpath;

            if (is_file($file)) {
                require $file;
            }
        };

        self::$autoloaders[$key] = $autoloader;
        spl_autoload_register($autoloader, true, $prepend);
    }

    public static function addPsr4($prefix, $path, $prepend = false)
    {
        $key = self::getHashKey($prefix, $path);
        $prefix = ltrim($prefix, '\\');
        $path = rtrim($path, DIRECTORY_SEPARATOR);

        $autoloader = function($fqcn) use ($prefix, $path) {
            if (strpos($fqcn, $prefix) !== 0) {
                return;
            }

            $trimmed = substr($fqcn, strlen($prefix));
            $relpath = Autoloader::class2Path($trimmed);
            $file = $path . DIRECTORY_SEPARATOR . $relpath;
            if (is_file($file)) {
                require $file;
            }
        };

        self::$autoloaders[$key] = $autoloader;
        spl_autoload_register($autoloader, true, $prepend);
    }

    public static function remove($prefix, $path)
    {
        $key = self::getHashKey($prefix, $path);
        if (!isset(self::$autoloaders[$key])) {
            return;
        }
        $autoloader = self::$autoloaders[$key];
        spl_autoload_unregister($autoloader);
        unset(self::$autoloaders[$key]);
    }

    public static function class2Path($fqcn)
    {
        $lastNsPos = strrpos($fqcn, '\\');

        if ($lastNsPos !== false) {
            $ns = substr($fqcn, 0, $lastNsPos);
            $ns = str_replace('\\', DIRECTORY_SEPARATOR, $ns);
            $cls = substr($fqcn, $lastNsPos + 1);
            $cls = str_replace('_', DIRECTORY_SEPARATOR, $cls);
            $normalized = $ns . DIRECTORY_SEPARATOR . $cls;
        } else {
            $normalized = str_replace('_', DIRECTORY_SEPARATOR, $fqcn);
        }

        return $normalized . '.php';
    }

    protected static function getHashKey($prefix, $path)
    {
        return crc32($prefix . '-' . $path);
    }
}


code:
<?php

namespace ErrorDumper\Console;

class Printer implements PrinterInterface
{
    const COLOR_BLACK	= '0';
    const COLOR_RED		= '1';
    const COLOR_GREEN	= '2';
    const COLOR_YELLOW	= '3';
    const COLOR_BLUE	= '4';
    const COLOR_MAGENTA	= '5';
    const COLOR_CYAN	= '6';
    const COLOR_WHITE	= '7';

    const STYLE_NORMAL		= '0';
    const STYLE_BOLD		= '1';
    const STYLE_UNDERLINED	= '4';
    const STYLE_BLINKING	= '5';
    const STYLE_REVERSE		= '7';

    private $stream;

    public function __construct($outputStream)
    {
        $this->setOutputStream($outputStream);
    }

    public function errorBox($text)
    {
        $this->colorizeAndPrint(static::COLOR_RED, null, static::STYLE_BOLD, $text . PHP_EOL);

        return $this;
    }

    public function infoBox($text)
    {
        $this->colorizeAndPrint(static::COLOR_BLUE, null, null, $text . PHP_EOL);

        return $this;
    }

    public function defaultBox($line)
    {
        $this->printRaw($line . PHP_EOL);

        return $this;
    }

    public function setOutputStream($stream)
    {
        $this->stream = $stream;

        return $this;
    }

    public function warningBox($text)
    {
        $this->colorizeAndPrint(static::COLOR_GREEN, null, null, $text . PHP_EOL);

        return $this;
    }

    /**
     * @codeCoverageIgnore
     * @param $textColor
     * @param $backgroundColor
     * @param $style
     * @param $text
     */
    private function colorizeAndPrint($textColor, $backgroundColor, $style, $text)
    {
        $colored = '';

        if (!is_null($textColor))
        {
            $colored .= "\033[3" . $textColor . 'm';
        }

        if (!is_null($style))
        {
            $colored .= "\033[" . $style . 'm';
        }

        if (!is_null($backgroundColor))
        {
            $colored .= "\033[4" . $backgroundColor . 'm';
        }

        $this->printRaw($colored . $text . "\033[0m");
    }

    private function printRaw($text)
    {
        fputs($this->stream, $text);
    }
}


code:
<?php

namespace ErrorDumper\Console;

interface PrinterInterface
{
    /**
     * @param $stream
     * @return PrinterInterface
     */
    public function setOutputStream($stream);

    /**
     * @param $line
     * @return PrinterInterface
     */
    public function defaultBox($line);

    /**
     * @param $text
     * @return PrinterInterface
     */
    public function errorBox($text);

    /**
     * @param $text
     * @return PrinterInterface
     */
    public function infoBox($text);

    /**
     * @param $text
     * @return PrinterInterface
     */
    public function warningBox($text);
}


code:
<?php

namespace ErrorDumper\DumpFunctions;

class Detector
{
    const SYMFONY_COMPONENT_CLASS = 'Symfony\Component\VarDumper\Dumper\HtmlDumper';

    /**
     * @codeCoverageIgnore
     * @return DumpFunctionInterface
     */
    public static function createDetectedVarDumper()
    {
        if (class_exists(static::SYMFONY_COMPONENT_CLASS, true))
        {
            return new SymfonyVarDumper();
        }

        return new InternalVarDumper();
    }
}


code:
<?php

namespace ErrorDumper\DumpFunctions;

interface DumpFunctionInterface
{
    /**
     * @param $var
     * @return string
     */
    public function __invoke($var);
}


code:
<?php

namespace ErrorDumper\DumpFunctions;

class InternalVarDumper implements DumpFunctionInterface
{
    public function __invoke($var)
    {
        ob_start();
        var_dump($var);
        $result = ob_get_contents();
        ob_end_clean();
        $xdebugIsLoaded = extension_loaded('xdebug');

        return ($xdebugIsLoaded ? '' : '<pre>' ) . $result . ($xdebugIsLoaded ? '' : '</pre>');
    }
}


code:
<?php

namespace ErrorDumper\DumpFunctions;

class LightVarDumper implements DumpFunctionInterface
{
    const XDEBUG_CONFIG_KEY = 'xdebug.overload_var_dump';

    public function __invoke($var)
    {
        ob_start();
        $previous = ini_get(static::XDEBUG_CONFIG_KEY);
        ini_set(static::XDEBUG_CONFIG_KEY, false);
        var_dump($var);
        ini_set(static::XDEBUG_CONFIG_KEY, $previous);
        $contents = ob_get_contents();
        ob_end_clean();

        return '<pre>' . substr($contents, 0, 300) . '</pre>';
    }
}


code:
<?php

namespace ErrorDumper\DumpFunctions;

use Symfony\Component;

/**
 * @codeCoverageIgnore
 */
class SymfonyVarDumper implements DumpFunctionInterface
{
    /**
     * @var Component\VarDumper\Dumper\HtmlDumper
     */
    private $dumper;

    /**
     * @var Component\VarDumper\Cloner\VarCloner
     */
    private $cloner;

    public function __construct()
    {
        $this->dumper = new Component\VarDumper\Dumper\HtmlDumper();
        $this->cloner = new Component\VarDumper\Cloner\VarCloner();
    }

    public function __invoke($var)
    {
        ob_start();
        $this->dumper->dump($this->cloner->cloneVar($var));
        $result = ob_get_contents();
        ob_end_clean();

        return $result;
    }
}


code:
<?php

namespace ErrorDumper\Dumpers;

abstract class Base implements DumperInterface
{
    protected $outputStream;

    public function setOutputStream($output)
    {
        $this->outputStream = $output;

        return $this;
    }
}


code:
<?php

namespace ErrorDumper\Dumpers;

use ErrorDumper\Console\Printer;
use ErrorDumper\Console\PrinterInterface;
use ErrorDumper\Helpers\Exceptions;

class Cli extends Base
{
    const EMPHASIS_LENGTH = 50;

    /**
     * @var PrinterInterface
     */
    private $printer;

    /**
     * @var callable
     */
    private $windowWidthGetter;

    public function __construct($stream)
    {
        $this->printer = new Printer($stream);
        $this->setOutputStream($stream);
    }

    public function displayException($e)
    {
        Exceptions::throwIfIsNotThrowable($e);
        $width = $this->getWindowWidth();
        $this->printer->defaultBox('');
        $this->printer->defaultBox('');
        $this->printer->errorBox(str_pad('', $width, '#'));
        $this->printer->errorBox(get_class($e) . ': ' . $e->getMessage());
        $this->printer->errorBox(str_pad('', $width, '#'));
        $this->printer->defaultBox('');
        $this->printer->defaultBox('');
        $this->printer->defaultBox($e->getTraceAsString());
    }

    public function setOutputStream($output)
    {
        parent::setOutputStream($output);
        $this->printer->setOutputStream($output);

        return $this;
    }

    /**
     * @param callable $getter
     * @return Cli
     */
    public function setWindowWidthGetter($getter)
    {
        Exceptions::throwIfIsNotCallable($getter);
        $this->windowWidthGetter = $getter;

        return $this;
    }

    private function getWindowWidth()
    {
        return $this->windowWidthGetter
            ? call_user_func($this->windowWidthGetter)
            : static::EMPHASIS_LENGTH;
    }
}


code:
<?php

namespace ErrorDumper\Dumpers;

interface DumperInterface
{
    /**
     * @param \Exception|\Throwable $e
     */
    public function displayException($e);

    /**
     * @param $output resource
     * @return DumperInterface
     */
    public function setOutputStream($output);
}


code:
<?php

namespace ErrorDumper\Dumpers;

use ErrorDumper\DumpFunctions\Detector;
use ErrorDumper\DumpFunctions\DumpFunctionInterface;
use ErrorDumper\Editors\EditorInterface;
use ErrorDumper\Helpers\Exceptions;
use ErrorDumper\Views\Template;

class Html extends Base
{
    const TAG_HTML = '<!-- @ErrorDumper -->';

    const BOOTSTRAP_CSS = '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css';
    const BOOTSTRAP_JS = '//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js';
    const JQUERY_JS = '//code.jquery.com/jquery-2.1.4.min.js';

    private $bootstrapCss = '';
    private $bootstrapJs = '';
    private $jqueryJs = '';

    /**
     * @var EditorInterface
     */
    private $editor;

    /**
     * @var callable
     */
    private $varDumpFn;

    public function __construct(EditorInterface $editor, $stream)
    {
        $this
            ->setEditor($editor)
            ->setOutputStream($stream)
            ->setBootstrapJs(static::BOOTSTRAP_JS)
            ->setBootstrapCss(static::BOOTSTRAP_CSS)
            ->setJqueryJs(static::JQUERY_JS)
            ->setVarDumpFn(Detector::createDetectedVarDumper());
    }

    public function displayException($e)
    {
        Exceptions::throwIfIsNotThrowable($e);
        $vars = array(
            'exception' => $e,
            'exceptionClass' => get_class($e),
            'message' => $e->getMessage(),
            'trace' => array(),
            '__static' => array(
                'css' => array(
                    \get_stylesheet_directory_uri() . "/assets/bootstrap.min.css",
                ),
                'js' => array(
                ),
            ),
        );
        $helper = new HtmlHelper($this->varDumpFn, $this->editor);
        $vars['trace'][] = $helper->prepareStep(array(
            'file' => $e->getFile(),
            'line' => $e->getLine(),
        ));
        foreach ($e->getTrace() as $rawStep)
        {
            $vars['trace'][] = $helper->prepareStep($rawStep);
        }
        $template = new Template();
        fputs($this->outputStream, $template->render('exceptions/html', $vars));
    }

    /**
     * @param EditorInterface $editor
     * @return Html
     */
    public function setEditor(EditorInterface $editor)
    {
        $this->editor = $editor;

        return $this;
    }

    /**
     * @param DumpFunctionInterface $fn
     * @return Html
     * @throws \ErrorDumper\Helpers\NotCallableException
     */
    public function setVarDumpFn(DumpFunctionInterface $fn)
    {
        Exceptions::throwIfIsNotCallable($fn);
        $this->varDumpFn = $fn;

        return $this;
    }

    /**
     * @param $path
     * @return Html
     */
    public function setBootstrapCss($path)
    {
        $this->bootstrapCss = $path;

        return $this;
    }

    /**
     * @param $path
     * @return Html
     */
    public function setBootstrapJs($path)
    {
        $this->bootstrapJs = $path;

        return $this;
    }

    /**
     * @param $path
     * @return Html
     */
    public function setJqueryJs($path)
    {
        $this->jqueryJs = $path;

        return $this;
    }
}


code:
<?php

namespace ErrorDumper\Dumpers;

use ErrorDumper\DumpFunctions\DumpFunctionInterface;
use ErrorDumper\Editors\CannotGenerateLinkException;
use ErrorDumper\Editors\EditorInterface;
use ErrorDumper\Helpers\PHPVersion;

class HtmlHelper
{
    const MAX_VARIADIC_ARGS = 5;
    const CLOSURE_NAME = '{closure}';

    private $key = 0;

    /**
     * @var callable
     */
    private $varDump;

    /**
     * @var EditorInterface
     */
    private $editor;

    /**
     * @codeCoverageIgnore
     * @param DumpFunctionInterface $varDump
     * @param EditorInterface $editor
     */
    public function __construct(DumpFunctionInterface $varDump, EditorInterface $editor)
    {
        $this->varDump = $varDump;
        $this->editor = $editor;
    }

    private function dump($var)
    {
        return call_user_func($this->varDump, $var);
    }

    private function prepareColorizedParameters($step)
    {
        $params = isset($step['args']) ? $step['args'] : array();
        if (!$params)
        {
            return array();
        }
        if (!isset( $step['function'] ) || strpos($step['function'], static::CLOSURE_NAME) !== false)
        {
            $result = array();
            foreach ($params as $key => $param)
            {
                $dump = $this->dump($param);
                $result[] = array(
                    'name' => $this->getType($param) . ': unknown[' . $key . ']',
                    'dump' => $dump,
                    'full' => $this->showFull($param, $dump),
                );
            }
            return $result;
        }
        if (!isset( $step['class'] ))
        {
            if (!function_exists($step['function'])) # for example include
            {
                $result = array();
                foreach ($params as $key => $param)
                {
                    $dump = $this->dump($param);
                    $result[] = array(
                        'name' => $this->getType($param) . ': unknown[' . $key . ']',
                        'dump' => $dump,
                        'full' => $this->showFull($param, $dump),
                    );
                }
                return $result;
            }

            $function = new \ReflectionFunction($step['function']);
        }
        else
        {
            $class = new \ReflectionClass($step['class']);
            if (!$class->hasMethod($step['function']))
            {
                $result = array();
                foreach ($params as $key => $param)
                {
                    $dump = $this->dump($param);
                    $result[] = array(
                        'name' => $this->getType($param) . ': unknown[' . $key . ']',
                        'dump' => $dump,
                        'full' => $this->showFull($param, $dump),
                    );
                }
                return $result;
            }
            $function = $class->getMethod($step['function']);
        }
        $result = array();
        $index = 0;
        foreach ($function->getParameters() as $reflectionParam)
        {
            /**
             * isVariadic requires at least php 5.6.0
             */
            if (PHPVersion::atLeast('5.6.0') && $reflectionParam->isVariadic())
            {
                if (empty($params) || count($params) > static::MAX_VARIADIC_ARGS)
                {
                    $dump = $this->dump($params);
                    $result[] = array(
                        'name' => '...$' . $reflectionParam->getName(),
                        'dump' => $dump,
                        'full' => $this->showFull($params, $dump),
                    );
                }
                else
                {
                    foreach ($params as $i => $param)
                    {
                        $dump = $this->dump($param);
                        $result[] = array(
                            'name' => $this->getType($param) . ': ...$' . $reflectionParam->getName() . '[' . $i . ']',
                            'dump' => $dump,
                            'full' => $this->showFull($param, $dump),
                        );
                    }
                }
                $params = array();
                break;
            }
            $isset = in_array(0, array_keys($params), true);
            $param = array_shift($params);
            $dump = $this->dump($param);
            $result[] = array(
                'full' => $this->showFull($param, $dump),
                'dump' => $isset ? $dump : '
undefined
',
                'name' => $this->getType($param) . ': ' . ($reflectionParam->isPassedByReference() ? '&' : '') . '$' . $reflectionParam->getName(),
            );
            $index++;
        }
        foreach ($params as $param)
        {
            $dump = $this->dump($param);
            $result[] = array(
                'dump' => $dump,
                'name' => $this->getType($param) . ': unknown' . $index++,
                'full' => $this->showFull($param, $dump),
            );
        }
        return $result;
    }

    public function prepareStep(array $rawStep)
    {
        if (!isset($rawStep['file']))
        {
            $rawStep['file'] = 'empty';
        }
        if (!isset($rawStep['line']))
        {
            $rawStep['line'] = 0;
        }
        $title = "{$rawStep['file']}:{$rawStep['line']} ";
        if (!empty($rawStep['class']))
        {
            $title .= $rawStep['class'];
        }
        if (!empty($rawStep['type']))
        {
            $title .= $rawStep['type'];
        }
        if (!empty($rawStep['function']))
        {
            $title .= $rawStep['function'] . '()';
        }
        $title .= "";

/*
        try
        {
            $link = $this->editor->createLinkToFile($rawStep['file'], $rawStep['line']);
            $link = htmlspecialchars($link);
            $title = "{$title}";
        }
        catch(CannotGenerateLinkException $e)
        {
        }
*/

        return array(
            'title' => $title,
            'source' => $this->getClassShortContents($rawStep['file'], $rawStep['line']),
            'key' => $this->key++,
            'arguments' => $this->prepareColorizedParameters($rawStep),
        );
    }

    private function getClassShortContents($filename, $line)
    {
        if ("empty" == $filename) return "";
        if (!$line || !is_file($filename))
        {
            return "File does not exist {$filename}:{$line}.";
        }
        $lines = explode("\n", file_get_contents($filename));
        $countLines = count($lines);
        $maxDiff = 7;
        $from = $line - $maxDiff - 1;
        if ($from < 0)
        {
            $from = 0;
        }
        $to = $line + $maxDiff;
        if ($to > $countLines)
        {
            $to = $countLines;
        }
        $maxStrLen = strlen($to) + 4;
        $outputLines = array_slice($lines, $from, $maxDiff*2+1, true);
        foreach ($outputLines as $key => &$currentLine)
        {
            $currentLine = str_replace("\t", '    ', $currentLine);
            $currentLineNumber = $key + 1;

/*
            try
            {
                $lineLink = $this->editor->createLinkToFile($filename, $currentLineNumber);
                $lineLink = htmlspecialchars($lineLink);
                $lineTag = "#{$currentLineNumber}";
            }
            catch (CannotGenerateLinkException $e)
            {
*/
                $lineTag = '#' . $currentLineNumber;
/*
            }
*/

            $currentLine = $lineTag
                . str_pad('',  $maxStrLen - strlen($currentLineNumber), ' ')
                . htmlspecialchars($currentLine);
        }
        $outputLines[$line-1] = '' . $outputLines[$line-1] . '';
        return implode("\n", $outputLines);
    }

    private function showFull($var, $dump)
    {
        if (is_scalar($var) || is_null($var))
        {
            if (!is_string($var) || strlen($var) <= 30)
            {
                return true;
            }
        }

        if (is_array($var) && count($var) <= 10)
        {
            return true;
        }

        return false;
    }

    private function getType($var)
    {
        if (is_object($var))
        {
            return '' . get_class($var) . '';
        }

        if (is_array($var))
        {
            return 'array(' . count($var) . ')';
        }

        return \gettype($var);
    }
}


code:
<?php

namespace ErrorDumper\Editors;

abstract class Base implements EditorInterface
{
    private $mapping = array();

    public function createLinkToFile($file, $line)
    {
        if (!$line)
        {
            return '';
        }

        return $this->getProtocol() . '://open?' . http_build_query(array(
            'file' => $this->convertPath($file),
            'line' => $line
        ));
    }

    public function registerDirectoryMap($serverPath, $projectPath)
    {
        $this->mapping[$serverPath] = $projectPath;
    }

    abstract protected function getProtocol();

    private function convertPath($path)
    {
        $result = $path;
        foreach ($this->mapping as $from => $to)
        {
            $pattern = '#^' . preg_quote($from, '#') . '#';
            $result = preg_replace($pattern, $to, $result);
        }

        return $result;
    }
}


code:
<?php

namespace ErrorDumper\Editors;

class CannotGenerateLinkException extends \Exception
{
}


code:
<?php

namespace ErrorDumper\Editors;

interface EditorInterface
{
    /**
     * @param $file
     * @param $line
     * @return string
     * @throws CannotGenerateLinkException
     */
    public function createLinkToFile($file, $line);

    /**
     * @param $serverPath
     * @param $projectPath
     * @return EditorInterface
     */
    public function registerDirectoryMap($serverPath, $projectPath);
}


code:
<?php

namespace ErrorDumper\Editors;

class MacVim extends Base
{
    /**
     * @codeCoverageIgnore
     */
    public function getProtocol()
    {
        return 'mvim';
    }
}


code:
<?php

namespace ErrorDumper\Editors;

class Nothing implements EditorInterface
{
    public function createLinkToFile($file, $line)
    {
        throw new CannotGenerateLinkException();
    }

    public function registerDirectoryMap($serverPath, $projectPath)
    {
        return $this;
    }
}


code:
<?php

namespace ErrorDumper\Editors;

class PhpStorm extends Base
{
    /**
     * @codeCoverageIgnore
     */
    public function getProtocol()
    {
        return 'idea';
    }
}


code:
<?php

namespace ErrorDumper\Editors;

class TextMate extends Base
{
    /**
     * @codeCoverageIgnore
     */
    public function getProtocol()
    {
        return 'txmt';
    }
}


code:
<?php

namespace ErrorDumper\Handlers;

interface CallbackEventInterface
{
    /**
     * @param \Exception|\Throwable $e
     */
    public function __invoke($e);
}


code:
<?php

namespace ErrorDumper\Handlers;

use ErrorDumper\Dumpers\DumperInterface;
use ErrorDumper\Helpers\Exceptions;

class Handler implements HandlerInterface
{
    /**
     * @var DumperInterface
     */
    private $dumper;

    /**
     * @var callable
     */
    private $postCallback;

    /**
     * @var callable
     */
    private $preCallback;

    public function __construct(DumperInterface $dumper)
    {
        $this->setDumper($dumper);
    }

    public function setDumper(DumperInterface $dumper)
    {
        $this->dumper = $dumper;

        return $this;
    }

    public function getDumper()
    {
        return $this->dumper;
    }

    public function setPostCallback($callback)
    {
        Exceptions::throwIfIsNotCallable($callback);
        $this->postCallback = $callback;

        return $this;
    }

    public function setPreCallback($callback)
    {
        Exceptions::throwIfIsNotCallable($callback);
        $this->preCallback = $callback;

        return $this;
    }

    /**
     * @param \Exception|\Throwable $e
     */
    public function __invoke($e)
    {
        Exceptions::throwIfIsNotThrowable($e);
        $pre = $this->preCallback;
        if (!empty($pre))
        {
            try
            {
                call_user_func($pre, $e);
            }
            catch (StopDisplayException $stopE)
            {
                return;
            }
        }
        $this->dumper->displayException($e);
        $post = $this->postCallback;
        if (!empty($post))
        {
            call_user_func($post, $e);
        }
    }
}


code:
<?php

namespace ErrorDumper\Handlers;

use ErrorDumper\Dumpers\DumperInterface;

interface HandlerInterface
{
    /**
     * @param DumperInterface $dumper
     * @return HandlerInterface
     */
    public function setDumper(DumperInterface $dumper);

    /**
     * @return DumperInterface
     */
    public function getDumper();

    /**
     * @param \Exception|\Throwable $e
     */
    public function __invoke($e);

    /**
     * @param callable $callback
     * @return HandlerInterface
     */
    public function setPreCallback($callback);

    /**
     * @param callable $callback
     * @return HandlerInterface
     */
    public function setPostCallback($callback);
}


code:
<?php

namespace ErrorDumper\Handlers;

abstract class PreCallbackEvent implements CallbackEventInterface
{
    public function stopDisplay()
    {
        throw new StopDisplayException();
    }
}


code:
<?php

namespace ErrorDumper\Handlers;

use ErrorDumper\Helpers\Exceptions;
use ErrorDumper\StandardExceptions\FatalErrorException;
use ErrorDumper\StandardExceptions\ShutdownErrorException;

/**
 * @codeCoverageIgnore
 */
class RegisterErrorHandler implements RegisterErrorHandlerInterface
{
    /**
     * @var callable
     */
    private $callable;

    private $mode;

    /**
     * @param callable $callable
     * @param int $mode
     */
    public function __construct($callable, $mode = null)
    {
        if (is_null($mode))
        {
            $mode = E_STRICT | E_ALL;
        }
        $this->setCallable($callable);
        $this->mode = $mode;
    }

    /**
     * @codeCoverageIgnore
     */
    public function register()
    {
        $this->registerExceptionHandler();
        $this->registerErrorHandler();
        $this->registerShutdownHandler();

        return $this;
    }

    public function setCallable($callable)
    {
        Exceptions::throwIfIsNotCallable($callable);
        $this->callable = $callable;

        return $this;
    }

    /**
     * This method is public because of supporting php 5.3.
     * @param $e
     */
    public function onError($e)
    {
        Exceptions::throwIfIsNotThrowable($e);
        call_user_func($this->callable, $e);
    }

    private function registerExceptionHandler()
    {
        $self = $this;
        set_exception_handler(function ($e) use ($self) {
            $self->onError($e);
        });
    }

    private function registerErrorHandler()
    {
        $self = $this;
        set_error_handler(function ($no, $str, $file, $line) use ($self) {
            $exception = new FatalErrorException();
            $exception
                ->setFile($file)
                ->setMessage($str)
                ->setCode($no)
                ->setLine($line);
            $self->onError($exception);
        }, $this->mode);
    }

    private function registerShutdownHandler()
    {
        $self = $this;
        register_shutdown_function(function () use ($self) {
            if ($error = error_get_last())
            {
                $exception = new ShutdownErrorException();
                $exception
                    ->setFile($error['file'])
                    ->setMessage($error['message'])
                    ->setCode($error['type'])
                    ->setLine($error['line']);
                $self->onError($exception);
            }
        });
    }
}


code:
<?php

namespace ErrorDumper\Handlers;

interface RegisterErrorHandlerInterface
{
    /**
     * @param callable $callable
     * @return RegisterErrorHandlerInterface
     */
    public function setCallable($callable);

    /**
     * @return RegisterErrorHandlerInterface
     */
    public function register();
}


code:
<?php

namespace ErrorDumper\Handlers;

class StopDisplayException extends \Exception
{
}


code:
<?php

namespace ErrorDumper\Helpers;

class Exceptions
{
    /**
     * @param \Exception|\Throwable $var
     * @throws NotThrowableException
     */
    public static function throwIfIsNotThrowable($var)
    {
        if (!is_object($var))
        {
            throw new NotThrowableException('Variable has to be throwable, but is not even object!');
        }
        if (PHPVersion::atLeast('7.0'))
        {
            // @codeCoverageIgnoreStart
            if (!$var instanceof \Throwable)
            {
                throw new NotThrowableException('Variable is not instance of \Throwable!');
            }
            // @codeCoverageIgnoreStop
        }
        else if (!$var instanceof \Exception)
        {
            // @codeCoverageIgnoreStart
            throw new NotThrowableException('Variable is not instance of \Exception!');
            // @codeCoverageIgnoreStop
        }
    }

    /**
     * @param callable $var
     * @throws NotCallableException
     */
    public static function throwIfIsNotCallable($var)
    {
        if (!is_callable($var))
        {
            throw new NotCallableException('Variable has to be callable!');
        }
    }
}


code:
<?php

namespace ErrorDumper\Helpers;

class NotCallableException extends \Exception
{
}


code:
<?php

namespace ErrorDumper\Helpers;

class NotThrowableException extends \Exception
{
}


code:
<?php

namespace ErrorDumper\Helpers;

/**
 * @codeCoverageIgnore
 */
class PHPVersion
{
    public static function atLeast($compareTo)
    {
        return version_compare(PHP_VERSION, $compareTo) >= 0;
    }
}


code:
<?php

namespace ErrorDumper\Helpers;

class Stream
{
    public static function getContentsFromStream($stream)
    {
        rewind($stream);
        $result = '';
        while (!feof($stream))
        {
            $result .= fread($stream, 1024);
        }

        return $result;
    }
}


code:
<?php

namespace ErrorDumper;

use ErrorDumper\DumpFunctions\LightVarDumper;
use ErrorDumper\Editors;
use ErrorDumper\Handlers\Handler;
use ErrorDumper\Handlers\HandlerInterface;
use ErrorDumper\Handlers\RegisterErrorHandler;
use ErrorDumper\Helpers\Exceptions;
use ErrorDumper\Dumpers;
use ErrorDumper\Helpers\Stream;

/**
 * @codeCoverageIgnore
 *
 * registerErrorCallback() and registerErrorDumper() are mutually exclusive
 */
class Magic
{
    /**
     * If you want skip some errors, call:
     * Magic::registerErrorDumper()->setPreCallback(callable $preCallback);
     *
     * If you want save information about error, call:
     * Magic::registerErrorDumper()->setPostCallback(callable $postCallback);
     *
     * Chain syntax is supported, for example:
     * Magic::registerErrorDumper()
     *  ->setPreCallback(callable $preCallback)
     *  ->setPostCallback(callable $postCallback);
     *
     * @see Handler::__invoke()
     * @param Editors\EditorInterface|null $editor
     * @return HandlerInterface
     */
    public static function registerErrorDumper(Editors\EditorInterface $editor = null)
    {
        $preCallback = null;
        $postCallback = function () {
            exit(1);
        };
        if (php_sapi_name() === 'cli')
        {
            $dumper = new Dumpers\Cli(fopen('php://output', 'w'));
            $dumper->setWindowWidthGetter(function () {
                return (int) exec('tput cols') ? : Dumpers\Cli::EMPHASIS_LENGTH;
            });
        }
        else
        {
            is_null($editor) && $editor = new Editors\PhpStorm();
            $dumper = (new Dumpers\Html($editor, fopen('php://output', 'w')));
            $preCallback = function () {
/*
                if (!headers_sent())
                {
                    header('HTTP/1.1 503 Service Temporarily Unavailable');
                    header('Status: 503 Service Temporarily Unavailable');
                    header('Retry-After: 300');
                }
*/
            };
        }
        $handler = new Handler($dumper);
        $handler->setPostCallback($postCallback);
        if ($preCallback)
        {
            $handler->setPreCallback($preCallback);
        }
        $registerErrorHandler = new RegisterErrorHandler($handler);
        $registerErrorHandler->register();

        return $handler;
    }

    /**
     * Method only for catching errors, without friendly output.
     *
     * @param $callable
     * @param int $mode
     * @throws Helpers\NotCallableException
     */
    public static function registerErrorCallback($callable, $mode = null)
    {
        Exceptions::throwIfIsNotCallable($callable);
        $registerErrorHandler = new RegisterErrorHandler($callable, $mode);
        $registerErrorHandler->register();
    }

    /**
     * @param $exception
     * @param Editors\EditorInterface|null $editor
     * @return string
     * @throws Helpers\NotThrowableException
     */
    public static function exportExceptionToLightHtml($exception, Editors\EditorInterface $editor = null)
    {
        Exceptions::throwIfIsNotThrowable($exception);
        is_null($editor) && $editor = new Editors\Nothing();
        $tmp = tmpfile();
        $dumper = new Dumpers\Html($editor, $tmp);
        $dumper->setVarDumpFn(new LightVarDumper());
        $dumper->displayException($exception);
        $result = Stream::getContentsFromStream($tmp);
        fclose($tmp);

        return $result;
    }
}


code:
<?php

namespace ErrorDumper\StandardExceptions;

class FakeException extends \Exception
{
    public function setLine($line)
    {
        $this->line = $line;

        return $this;
    }

    public function setFile($file)
    {
        $this->file = $file;

        return $this;
    }

    public function setMessage($message)
    {
        $this->message = $message;

        return $this;
    }

    public function setCode($code)
    {
        $this->code = $code;

        return $this;
    }
}


code:
<?php

namespace ErrorDumper\StandardExceptions;

class FatalErrorException extends FakeException
{
}


code:
<?php

namespace ErrorDumper\StandardExceptions;

class ShutdownErrorException extends FakeException
{
}


code:
<?php

namespace ErrorDumper\Views;

class Template implements TemplateInterface
{
    private $rootDirectory;

    public function __construct()
    {
        $this->setRootDirectory(implode(DIRECTORY_SEPARATOR, array(__DIR__, '..', '..', 'templates')));
    }

    public function render($path, array $data = array())
    {
        // @codeCoverageIgnoreStart
        if (DIRECTORY_SEPARATOR !== '/')
        {
            $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
        }
        // @codeCoverageIgnoreStop
        $realPath = implode(DIRECTORY_SEPARATOR, array($this->rootDirectory, $path . '.php'));
        ob_start();
        require $realPath;
        $contents = ob_get_contents();
        ob_end_clean();

        return $contents;
    }

    public function setRootDirectory($dir)
    {
        $this->rootDirectory = $dir;
    }
}


code:
<?php

namespace ErrorDumper\Views;

interface TemplateInterface
{
    /**
     * @param string $path
     * @param array $data
     * @return string
     */
    public function render($path, array $data);

    public function setRootDirectory($dir);
}


code:
<!doctype html>

    <meta charset="UTF-8" />
    <title>Error dumper</title>
    <link href="data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAVFFOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAABEAAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAABEAAAAAEQABEAAAAAABEAEQAAAAAAEQABEAAAAAEQAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAAEQAAEQAAAAAAAAAAAAD//wAA888AAOfnAADn5wAA5+cAAOfnAADP8wAAn/kAAJ/5AADP8wAA5+cAAOfnAADn5wAA5+cAAPPPAAD//wAA" rel="icon" type="image/x-icon" />
    <?php foreach ($data['__static']['css'] as $file) { ?>
        <link rel="stylesheet" type="text/css" href="<?php echo $file ?>" />
    <?php } ?>

Error!

Message

<?php echo $data['exceptionClass']; ?><?php echo isset($data['message']) ? ' ' . $data['message'] : '' ?>

Backtrace

    <?php foreach ($data['trace'] as $step) { ?>

<?php echo $step['title'] ?>

            <?php if (!empty($step['arguments'])) { ?>

                <ul class="nav nav-tabs" data-tabs="tabs-<?php echo $step['key'] ?>">

                        <a href="#source-<?php echo $step['key'] ?>" data-toggle="tab">Source

                        <a href="#colorized-key-<?php echo $step['key'] ?>" data-toggle="tab">Arguments

            <?php } ?>

                    <div class="tab-pane active in fade" id="<?php if (!empty($step['key'])) { ?>source-<?php echo $step['key']; } ?>">
                        <pre class="<?php echo !empty($step['key']) ? 'code-box' : '' ?> max-height"><?php echo $step['source'] ?>

                    <?php if (!empty($step['arguments'])) { ?>
                    <div class="tab-pane fade" id="colorized-key-<?php echo $step['key'] ?>">

                            <?php foreach ($step['arguments'] as $keyParam => $param) { ?>

                                    <a data-toggle="collapse" data-target="#parameters-<?php echo $step['key'] ?>-<?php echo $keyParam ?>" class="<?php echo $param['full'] ?: 'collapsed' ?>"><?php echo $param['name'] ?>

                                <div id="parameters-<?php echo $step['key'] ?>-<?php echo $keyParam ?>" class="panel-collapse <?php echo $param['full'] ? 'collapse in' : 'collapse' ?>">

                                        <?php echo $param['dump']; ?>

                            <?php } ?>

                    <?php } ?>

    <?php } ?>

<?php foreach ($data['__static']['js'] as $file) { ?>

<?php } ?>
<?php echo \ErrorDumper\Dumpers\Html::TAG_HTML ?>


code:
html { font: 13px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; padding: 20px; position: relative; text-align: center; background: #efefef; }

#header, #body { width: 600px; margin: 0 auto; text-align: left; }
#header { width: 680px; padding: 0; }
#body { background: white; padding: 40px; }

h1 { font-size: 30px; margin-bottom: 4px; }
h2 { margin-top: 0; color: #999; font-weight: normal; }

address { font-style: normal; }
fieldset { border: none; border-top: 1px solid #dadada; margin: 20px 40px 20px 0; }
fieldset legend { display: block; font-weight: bold; color: #999; }
table { clear: both; }
table.transaction th { text-align: left; }
.labels { width: 100%; }
table.labels td { vertical-align: top; }
h1 { margin-bottom: 0; }
p { margin-bottom: 24px; }

.order { width: 100%; overflow: hidden; border: none; }
.order td { border: none; }
.order th { font-weight: bold; text-align: left; }
.order .item { width: 50%; }
.order td.qty { text-align: center; }

.order .money,
.order .total,
.order .buttons td { text-align: right; }
.order .remove { font-size: 12px; }

.order tr.totals th,
.order tr.totals td { padding: 10px 0 0 0; }


code:
/**
 * shopp.css
 * Generic layout & styles for Shopp pages
 *
 * @author Jonathan Davis
 * @package shopp
 **/

/** Generic Shopp Styles **/

#shopp .submit { text-align: right; }
#shopp form { text-align: left; }
#shopp form.product ul.options { list-style: none; }
#shopp form ul { line-height: 1; }
#shopp form li > label { font-weight: bold; padding: 20px 0 10px; }
#shopp form ul li span label,
#shopp form div label { font-size: 0.8125em; font-weight: normal; padding-top: 0.6em; }
#shopp .right { float: right; }

/** Catalog/Category **/

.categories ul li a.current { font-weight: bold; }
#shopp .category { position: relative; }
#shopp .category-description { padding-bottom: 14px; }
#shopp .views,
#shopp .views li { display: inline; }
#shopp .orderby { float: right; }

#shopp .category .subcategories { padding: 10px 0; margin-bottom: 10px; }
#shopp .category .subcategories ul { padding: 10px 0 0 20px; margin-bottom: 10px; }
#shopp .category .subcategories li { display: inline-block; margin-right: 20px; vertical-align: top; }
#shopp form.category-list-menu .subcategories { padding: auto; }
#shopp .slideshow,
#shopp .carousel { margin: 20px 0; overflow: hidden; }

/* Each product in a category has a containing frame */
#shopp ul.products li.product div.frame { padding: 10px; }

#shopp ul.products li .name,
#shopp ul.products li .summary,
#shopp ul.products li .savings,
#shopp ul.products li .price { margin-top: 0; margin-bottom: 0; }
#shopp ul.products li .details { float: none; }

/* Hide the product summary in the grid view */
#shopp ul.products li .summary { display: none; }
#shopp ul.products li .listview { display: none; }

#shopp .price { font-weight: bold; line-height: 1.5; margin: 0; }
#shopp .original { text-decoration: line-through; }
#shopp .sale { font-size: 150%; }

/* Faceted menu cancel filter link styles */
.filters a.cancel:before { content: "["; }
.filters a.cancel { font-weight: bold; }
.filters a.cancel:after { content: "]"; }
.filters a.cancel:hover { text-decoration: none; }

/** Product List View **/
#shopp.list ul.products li { float: none; width: 100%; overflow: hidden; padding-bottom: 10px;}
#shopp.list ul.products li.product {  border-bottom: 1px solid #ddd; }
#shopp.list ul.products li div.frame { width: 100%; text-align: left; }
#shopp.list ul.products li img { float: left; margin-right: 10px; }
#shopp.list ul.products li .details { float: left; width: 65%; }
#shopp.list ul.products li .listview { display: block; }

#shopp ul.breadcrumb { margin: 10px 0; display: inline; }
#shopp ul.breadcrumb li { background: none; padding: 0; display: inline; margin-left: 0; text-indent: 0; }
#shopp ul.breadcrumb li span { font-weight: bold; }
#shopp .category-list-menu { display: inline; }

#shopp ul.categories { float: left; margin-right: 20px; }

/** Category Pagination **/
#shopp ul.paging { /* placeholder for your styles - inherited defaults: clear: none; display: inline-block; */ }
#shopp ul.paging li { /* placeholder for your styles - inherited defaults: display: inline-block; margin-left: 5px; */ }
#shopp ul.paging li a { /* page links default styling */ }
#shopp ul.paging li a:hover { /* page links hover styling */ }
#shopp ul.paging li.active { /* currrent page style */ }
#shopp ul.paging li.disabled { /* style for disabled previous/next links */ }
#shopp ul.paging li.previous a,
#shopp ul.paging li.next a { /* previous/next link style */ }

/** Product Pages **/
#shopp .column { float: left; }
#shopp .column.first { width: 65%; }
#shopp .column.second { float: right; width: 35%; }

#shopp .original { text-decoration: line-through; }
#shopp form.product ul,
#shopp form.product ul li,
#shopp form.product ul li label { clear: none; }
#shopp form.product ul { width: auto; }
#shopp ul.variations label { display: block; }
#shopp dl { overflow: hidden; }
#shopp dt { clear:left; float:left; text-align: right; width:50%; margin-right: 1em; }
#shopp dd { clear:right; width:50%; padding-left: 50%; }

#shopp .gallery { margin: 5px 10px 5px 0; }
#shopp .gallery ul.thumbnails { margin: 10px 0 10px 0; }
#shopp .gallery ul.thumbnails li { margin: 0 5px 0 0; }

/** Category List Widget **/
ul.shopp_categories { /* category list container */ }
ul.shopp_categories li { /* category listing containers */ }
ul.shopp_categories li a { /* category link default styles */ }
ul.shopp_categories li a:hover { /* category link hover styles */ }
ul.shopp_categories li span { /* categpry product count styles */ }
ul.shopp_categories li.current { /* currently viewed category container */ }
ul.shopp_categories li.current a { /* currently viewed category link style */ }
ul.shopp_categories li.current a:hover { /* currently viewed category link hover style */ }
ul.shopp_categories li ul.children { /* sub-category list container */ }
ul.shopp_categories li ul.children li { /* sub-category listing container */ }
ul.shopp_categories li ul.active { /* active sub-category container */ }

/* Collapsed sub-category menus example
ul.shopp_categories li ul.children { display: none; }
ul.shopp_categories li ul.active { display: block; }
*/

/** Side Products Widget **/
.sideproduct { margin-top: 20px; }
.sideproduct h3 { margin-top: 0; }
.sideproduct .original.price { text-decoration: line-through; }

/** Shopping Cart **/
#shopp #cart { width: 100%; }
#shopp #cart table { padding: 10px 0; width: 100%; }
#shopp #cart th { text-align: left; font-weight: bold; }
#shopp #cart th, #shopp #cart td { padding: 3px; }
#shopp #cart .item { width: 50%; }
#shopp #cart .money,
#shopp #cart .totals th,
#shopp #cart .buttons td { text-align: right; white-space: nowrap; }
#shopp #cart .totals.total th,
#shopp #cart .totals.total td { font-size: 130%; }
#shopp #cart .remove { font-size: 9px; }

#shopp #cart address { font-style: normal; }
#shopp #cart big { display: block; margin: 10px 0; }
#shopp #cart big a.right { float: right; }

/** Shopping Cart Widget **/
#shopp-cart.widget p.status { margin-bottom: 10px; }

#shopp ul.account li { display: inline-block; width: 200px; padding-top: 18px; }

/** Checkout **/
#shopp #shipping-methods { padding-left: 30px; }
#shopp #shipping-methods li { margin-top: 5px; }
#shopp #shipping-methods li label { padding: 0 0 10px; }
#shopp #shipping-methods input { margin-left: -16px; }

#shopp .shopp-errors { color: #990000; }
#shopp input.error { background: #ffdddd; }
#shopp label.error { color: #990000; font-weight: bold; }

.clickwrap-terms { overflow: auto; height: 200px; border: 1px solid #333; padding: 0.5em; margin-bottom: 1em; }

/** Order Receipt **/
#shopp #receipt { position: relative; margin: 20px 0; }
#shopp #receipt address { font-style: normal; }
#shopp #receipt fieldset { padding: 10px; border: 1px solid #dadada; margin: 20px 0 30px; }
#shopp #receipt fieldset legend { display: block; }
#shopp #receipt table { overflow: hidden; }
#shopp #receipt table.transaction th { text-align: left; }
#shopp #receipt .labels { width: 100%; }
#shopp #receipt table.labels td { vertical-align: top; }

#shopp #receipt .order { width: 100%; overflow: hidden; border: none; }
#shopp #receipt td { border: none; }
#shopp #receipt th { font-weight: bold; text-align: left; border: none; }
#shopp #receipt th,
#shopp #receipt td { padding: 3px 0; }
#shopp #receipt .order .item { width: 50%; }
#shopp #receipt .order td.qty { text-align: center; }
#shopp #receipt .order .money,
#shopp #receipt .order .total,
#shopp #receipt .order .buttons td { text-align: right; }
#shopp #receipt .order .totals.total th,
#shopp #receipt .order .totals.total td { font-size: 130%; }


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

     class BadMethodCallException
   extends \BadMethodCallException
implements ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

interface ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

     class InvalidArgumentException
   extends \InvalidArgumentException
implements ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

     class InvalidPostProcessorException
   extends RuntimeException
implements ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

     class InvalidRendererException
   extends RuntimeException
implements ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Exception;

     class RuntimeException
   extends \RuntimeException
implements ExceptionInterface
{
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

/**
 * @version 0.0.1
 *
 * Contains all kinds of clever uses for call_user_func_array
 * Of course it could not be called apply() because strlen is
 * just the perfect hash function...
 *
 * None of this actually requires a class, or keeps any state
 * at all (i.e. no $this or static vars, all methods declared
 * static). Future versions may simply use a namespace and no
 * class, depending on what works well wrt unit tests.
 */
class F
{
	/**
	 * Create a function which always returns $val
	 *
	 * @param mixed $val
	 *
	 * @return \Closure that returns $val
	 */
	public static function always($val)
	{
		return function() use ($val) {
			return $val;
		};
	}

	/**
	 * In case you're tired of writing call_user_func_array
	 * May be removed in the future, because it's quite meh
	 */
	public static function apply(callable $func, $args=[])
	{
		return call_user_func_array($func, $args);
	}

	/**
	 * @param callable $func
	 *
	 * @return \Closure with the first two parameters swapped
	 *
	 * If a single argument is passed to resulting closure,
	 * the second argument will be substituted with a NULL.
	 */
	public static function flip(callable $func)
	{
		return function() use ($func) {
			return call_user_func_array(
				$func,

				/* Use the fact that arrays are actually
				 * ordered maps to swap just the first 2
				 */
				array_values(array_replace(
					array_reverse(
						array_fill(0, 2, null),
						true
					), // [1] => null, [0] => null
					func_get_args()
				))
			);
		};
	}

	/**
	 * @param callable $func
	 *
	 * @return \Closure with all parameters reversed
	 *
	 * Might not work properly with variable argument lists
	 */
	public static function flipAll(callable $func)
	{
		return function() use ($func) {
			return call_user_func_array(
				$func,
				array_reverse(func_get_args())
			);
		};
	}

	/**
	 * Does nothing but return the given argument
	 *
	 * @param mixed $param
	 *
	 * @return mixed $param
	 */
	public static function identity($param)
	{
		return $param;
	}

	/**
	 * Creates a function that returns the given $property of an object
	 *
	 * @param string $property Name
	 *
	 * @return \Closure Function that returns $property from argument
	 */
	public static function pick($property)
	{
		return function($obj) use ($property) {
			return is_object($obj)
				? $obj->{$property}
				: $obj[$property];
		};
	}

	/**
	 * Creates a function that calls a function depending on a condition
	 *
	 * When called, passes its argument to $test and calls either $onTrue or
	 * $onFalse depending on the return value of $test. $onFalse can be null
	 * and the function will by default simply return the argument.
	 *
	 * @param callable $test    Evaluates its argument and returns bool
	 * @param callable $onTrue  Called with argument in the true case
	 * @param callable $onFalse Called with argument in the false case
	 *
	 * @return \Closure takes one argument
	 */
	public static function conditional($test, $onTrue, $onFalse = null)
	{
		return function($subject) use ($test, $onTrue, $onFalse)
		{
			return call_user_func($test, $subject)
				? call_user_func($onTrue, $subject)
				: (!is_null($onFalse)
					? call_user_func($onFalse, $subject)
					: $subject);
		};
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

abstract class GenericRendererFactory implements RendererFactoryInterface
{
	/**
	 * Produces RendererInterface for the given template name
	 *
	 * Based on PSR4-style class name
	 *
	 * @param string                             $name
	 * @param \ITSociaal\Themes\Houtgrutter\Util $util
	 *
	 * @return \ITSociaal\Themes\Houtgrutter\RendererInterface|null
	 */
	public static function create($name, Util $util)
	{
		$class = $util->deriveClassNameFromTemplateName(
			$name
		);

		return class_exists($class)
			? $util->createObject($class)
			: null;
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

class GlobalWordPress implements WordPressInterface
{
	public function avia_append_search_nav(...$args)
	{
		return \avia_append_search_nav(...$args);
	}

	public function avia_get_option(...$args)
	{
		return \avia_get_option(...$args);
	}

	public function get_bloginfo(...$args)
	{
		return \get_bloginfo(...$args);
	}

	public function get_the_post_thumbnail(...$args)
	{
		return \get_the_post_thumbnail(...$args);
	}

	public function has_post_thumbnail(...$args)
	{
		return \has_post_thumbnail(...$args);
	}

	public function load_template(...$args)
	{
		return \load_template(...$args);
	}

	public function shopp(...$args)
	{
		return \shopp(...$args);
	}

	public function wp_nav_menu(...$args)
	{
		return \wp_nav_menu(...$args);
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Includes;

use ITSociaal\Themes\Houtgrutter\PostProcessorInterface;
use ITSociaal\Themes\Houtgrutter\TemplateProcessor;
use ITSociaal\Themes\Houtgrutter\WordPressBase;

class HelperMainMenu extends WordPressBase implements PostProcessorInterface
{
	const MAIN_MENU = 3;  // Hoofdmenu ID
	const SHOP_MENU = 17; // Webshopmenu ID

	/**
	 * Removes substring if it occurs at the end of $string
	 *
	 * @param string $string Original string
	 * @param string $remove Substring to remove
	 *
	 * @return string without $remove if found at end
	 */
	protected function removeStringFromEnd($string, $remove)
	{
		$pos = strrpos($string, $remove);

		if ($pos === false) {
			return $string;
		}

		return ($pos + strlen($remove) === strlen($string))
			? substr($string, 0, $pos)
			: $string;
	}

	/**
	 * Removes
 and
 from end of $html
	 *
	 * @param string $html
	 *
	 * @return string
	 */
	protected function reopenNavMenu($html)
	{
		return
			$this->removeStringFromEnd(
				trim($this->removeStringFromEnd(trim($html), "
")),
				"
"
			);
	}

	/**
	 * Get HTML for site logo
	 *
	 * @return string
	 */
	public function getLogo()
	{
		$wp = $this->getWP();

		return '
avia_get_option("logo")
			. '" alt="'
			. $wp->get_bloginfo("name")
			. '" />
';
	}

	/**
	 * Get HTML for the main menu
	 *
	 * @return string
	 */
	public function getMainMenu()
	{
		return trim($this->reopenNavMenu($this->getWP()->wp_nav_menu([
			"container"		=> "div",
			"container_class" => "mainmenu container",
			"depth"			=> 1,
			"echo"			=> false,
			"fallback_cb"	=> false,
			"menu"			=> static::MAIN_MENU,
			"menu_id"		=> "MainMenu",
		])));
	}

	/**
	 * Get HTML for the webshop menubar
	 *
	 * @return string
	 */
	public function getShopMenu()
	{
		return trim($this->reopenNavMenu($this->getWP()->wp_nav_menu([
			"container"		=> "div",
			"container_class" => "shopmenu hidez",
			"depth"			=> 1,
			"echo"			=> false,
			"fallback_cb"	=> false,
			"menu"			=> static::SHOP_MENU,
			"menu_id"		=> "ShopMenu",
			"menu_class"	=> "container",
		])));
	}

	/**
	 * Get HTML for the search form
	 *
	 * @return string
	 */
	public function getSearch()
	{
		return $this->getWP()->avia_append_search_nav(
			"",
			(object)["theme_location" => "avia"]
		);
	}

	/**
	 * Get HTML for the subtotal
	 *
	 * @return string
	 */
	public function getCartSubtotal()
	{
		return $this->getWP()->shopp(
			"cart",
			"subtotal",
			["echo" => false, "return" => true]
		);
	}

	/** {@inheritDoc} */
	public function post($content, TemplateProcessor $tp=null)
	{
		$tp = $tp ?: new TemplateProcessor;

		return $tp->setContext($this)->process($content);
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
%%LOGO%%

      %%MAINMENU%%
        %%SEARCH%%

      %%SHOPMENU%%

              %%CARTSUBTOTAL%%

              <img src="<?php echo get_stylesheet_directory_uri(), "/assets/winkelwagen_icon.svg"; ?>" width="32" height="32" alt="Winkelwagen:"/>


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Laura;

use ITSociaal\Themes\Houtgrutter\WordPressBase;
use WP_Query;

class Advertentie extends WordPressBase
{
	/** @var \ITSociaal\Themes\Houtgrutter\Laura\Util */
	protected $util;

	/** @var \ITSociaal\Themes\Houtgrutter\WordPressInterface */
	protected $wpi;

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractContent($post)
	{
		return [
			/* Cannot use `apply_filters("the_content")` here,
			 * because that's where shopp injects its content.
			 * Any shortcodes in the post will be shown as is.
			 */
			"content" => $post->post_content,
		];
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractHave($post)
	{
		return [
			"have_ad" => boolval($post->ID),
		];
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractImage($post)
	{
		$wp = $this->getWP();
		$attr = [
			"class" => "advertentie-featured",
		];
		$have_image = $wp->has_post_thumbnail($post);
		$image = $have_image
			? $wp->get_the_post_thumbnail($post, "full", $attr) : "";

		return compact("have_image", "image");
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractTitle($post)
	{
		return [
			"title" => $post->post_title,
		];
	}

	/**
	 * Search the latest post in the "Advertenties" category
	 *
	 * @see /wp-admin/term.php?taxonomy=category&tag_ID=19&post_type=post
	 *
	 * @return \WP_Query
	 */
	protected function createQuery()
	{
		return $this->getUtil()->createObject(
			WP_Query::class,
			[
				'cat' => 19,
				'post_status' => 'publish',
				'posts_per_page' => 1,
				'order' => 'DESC',
				'orderby' => 'ID',
			]);
	}

	/**
	 * @return object
	 */
	protected function getPost()
	{
		// array -> generator -> array. I'm weird
		return iterator_to_array(
			$this->getUtil()->generatePostsFromWpQuery(
				$this->createQuery()
			),
			false //use_keys
		)[0] ?: $this->getUtil()->createEmptyPost();
	}

	/**
	 * @return \ITSociaal\Themes\Houtgrutter\Laura\Util
	 */
	protected function getUtil()
	{
		return $this->util;
	}

	/**
	 * Wraps callables into automatically bound anonymous functions
	 *
	 * Should probably be moved elsewhere but it's not an issue yet.
	 * If you move this method, remember to manually bind it to the
	 * right context so protected and private methods can be called.
	 *
	 * @param array $callables
	 *
	 * @return \Closure[]
	 */
	protected function wrapCallables(array $callables)
	{
		return array_map(
			function($callable) {
				return function(...$args) use ($callable) {
					return $callable(...$args);
				};
			},
			$callables
		);
	}

	/**
	 * Retrieve data to use in a template
	 *
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Advertentie $self
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Util        $util
	 *
	 * @return object
	 */
	public static function createContext(Advertentie $self=null, Util $util=null)
	{
		$util = $util ?: new Util();
		$self = $self ?: new static($util);

		return $self
			->getData();
	}

	/**
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Util $util
	 */
	public function __construct(Util $util)
	{
		$this->util = $util;
	}

	/**
	 * Retrieve data to use in a template
	 *
	 * @return object
	 */
	public function getData()
	{
		$util = $this->getUtil();

		return (object)array_merge(...iterator_to_array(
			$util->generateResultPerMethod(
				$this->wrapCallables(
					$util->getCallablesFromPrefixedMethods(
						$this, "extract", true
					)
				),
				$this->getPost()
			)
		));
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Laura;

use ITSociaal\Themes\Houtgrutter\Util as UtilBase;
use ReflectionClass;
use ReflectionMethod;
use WP_Query;

class Util extends UtilBase
{
	/**
	 * Iterate over posts in a WP_Query object.
	 *
	 * Does not execute any actions!
	 *
	 * @param WP_Query $wpq WP_Query object to iterate
	 *
	 * @return \Iterator yields posts (if any)
	 */
	public function generatePostsFromWpQuery(WP_Query $wpq)
	{
		$posts = $wpq->posts;
		reset($posts);
		foreach ($posts as $post) {
			yield $post;
		}
	}

	/**
	 * Create dummy post object compatible with get_post
	 *
	 * @return \stdClass Only minimal properties present
	 */
	public function createEmptyPost()
	{
		return (object)[
			"ID" => 0,
			"filter" => "raw",
			"post_content" => "",
			"post_title" => "",
		];
	}

	/**
	 * List methods in $class
	 *
	 * @param string|object $class
	 * @param boolean       $protected whether to include protected methods
	 *
	 * @return string[]
	 */
	public function getMethodsFromClass($class, $protected=false)
	{
		return array_map(
			function($method) {
				return $method->name;
			},
			(new ReflectionClass($class))
				->getMethods(
					ReflectionMethod::IS_PUBLIC | (
						intval(boolval($protected)) *
						ReflectionMethod::IS_PROTECTED
					)
				)
		);
	}

	/**
	 * Return subset of string array with matching prefix
	 *
	 * @param string[] $strings
	 * @param string   $prefix
	 *
	 * @return string[] only strings that begin with $prefix
	 */
	public function filterPrefix(array $strings, $prefix)
	{
		return array_values(array_filter(
			$strings,
			function($value) use ($prefix) {
				return strpos($value, $prefix) === 0;
			}
		));
	}

	/**
	 * Return array callables from list of methods on object
	 *
	 * @param object   $object
	 * @param string[] $methods
	 *
	 * @return array[] callables
	 */
	public function makeCallables($object, $methods)
	{
		return array_map(
			function($method) use ($object) {
				// This can somehow crash PHP with xdebug enabled
				return [$object, $method];
			},
			$methods
		);
	}

	/**
	 * Return list of callables for methods with a given prefix in $object
	 *
	 * @param object  $object
	 * @param string  $prefix
	 * @param boolean $protected
	 *
	 * @return array[] callables
	 */
	public function getCallablesFromPrefixedMethods(
		$object, $prefix, $protected=false
	) {
		return $this->makeCallables(
			$object,
			$this->filterPrefix(
				$this->getMethodsFromClass($object, $protected),
				$prefix
			)
		);
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Laura;

$ctx = Advertentie::createContext();

if ($ctx->have_ad):
?>

			<?=$ctx->image ?>

<?=$ctx->title ?>

						<?=$ctx->content ?>

<?php
endif;


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

interface PostProcessorInterface
{
	/**
	 * Performs post-processing on $content
	 *
	 * @param string $content raw content
	 *
	 * @return string processed content
	 */
	public function post($content);
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

class RenderController
{
	/** @var \ITSociaal\Themes\Houtgrutter\Util */
	protected $util;

	/** @var string */
	protected $result;

	/** @var \ITSociaal\Themes\Houtgrutter\RendererInterface[] */
	protected $renderers = [];

	/** @var \ITSociaal\Themes\Houtgrutter\PostProcessorInterface[] */
	protected $postprocessors = [];

	/**
	 * Calls the given renderers
	 *
	 * @return \Generator
	 */
	protected function generateRendererResult()
	{
		$renderers = $this->getRenderers();

		return $this->getUtil()->generateResultPerArgument(
			$renderers,
			[$this, "renderObject"]
		);
	}

	/**
	 * Call the given post-processors
	 *
	 * @return \Generator
	 */
	protected function generatePostProcessorResult()
	{
		return $this->getUtil()->generateResultPerArgument(
			$this->getPostProcessors(),
			[$this, "postprocessObject"]
		);
	}

	/**
	 * @return \ITSociaal\Themes\Houtgrutter\Util
	 */
	protected function getUtil()
	{
		return $this->util;
	}

	/**
	 * Calls a RendererInterface object
	 *
	 * @param \ITSociaal\Themes\Houtgrutter\RendererInterface $obj
	 *
	 * @return string
	 * @throws \ITSociaal\Themes\Houtgrutter\Exception\InvalidRendererException
	 */
	public function renderObject($obj)
	{
		if (!is_a($obj, RendererInterface::class)) {
			throw new Exception\InvalidRendererException;
		}

		return $obj->render();
	}

	/**
	 * Calls a PostProcessorInterface object
	 *
	 * @param \ITSociaal\Themes\Houtgrutter\PostProcessorInterface $obj
	 * @param string                                               $input
	 *
	 * @return string
	 * @throws \ITSociaal\Themes\Houtgrutter\Exception\InvalidPostProcessorException
	 */
	public function postprocessObject($obj, $input = null)
	{
		if (!is_a($obj, PostProcessorInterface::class))
			throw new Exception\InvalidPostProcessorException;

		$input = $input ?: $this->getResult();

		return $obj->post($input);
	}

	/**
	 * Calls the available RendererInterfaces and validates their result
	 *
	 * Stops on the first available valid result
	 *
	 * @return self
	 */
	public function performRendering()
	{
		foreach($this->generateRendererResult() as $result) {
			if (is_null($result))
				continue;
			else {
				assert(is_string($result));
				$this->setResult($result);
				break;
			}
		}

		return $this;
	}

	/**
	 * Calls the available PostProcessors and uses their result consecutively
	 *
	 * @return self
	 */
	public function performPostProcessing()
	{
		foreach($this->generatePostProcessorResult() as $result) {
			assert(is_string($result));
			$this->setResult($result);
		}

		return $this;
	}

	/**
	 * @return string
	 * @throws \ITSociaal\Themes\Houtgrutter\Exception\RuntimeException
	 */
	public function getResult()
	{
		$ret = $this->result;

		if (is_null($ret)) {
			throw new Exception\RuntimeException("No result defined yet");
		}

		return $ret;
	}

	/**
	 * @param string
	 *
	 * @return self
	 */
	protected function setResult($result)
	{
		$this->result = strval($result);

		return $this;
	}

	/**
	 * @param \ITSociaal\Themes\Houtgrutter\RendererInterface $renderer
	 *
	 * @return self
	 */
	public function addRenderer(RendererInterface $renderer)
	{
		$this->renderers[] = $renderer;

		return $this;
	}

	/**
	 * @return \ITSociaal\Themes\Houtgrutter\RendererInterface[]
	 * @throws \ITSociaal\Themes\Houtgrutter\Exception\RuntimeException
	 */
	public function getRenderers()
	{
		$ret = $this->renderers;

		if (empty($ret)) {
			throw new Exception\RuntimeException(
				"No renderers defined"
			);
		}

		return $ret;
	}

	/**
	 * @param \ITSociaal\Themes\Houtgrutter\PostProcessorInterface $postprocessor
	 *
	 * @return self
	 */
	public function addPostProcessor(PostProcessorInterface $postprocessor)
	{
		$this->postprocessors[] = $postprocessor;

		return $this;
	}

	/**
	 * @return \ITSociaal\Themes\Houtgrutter\PostProcessorInterface[]
	 */
	public function getPostProcessors()
	{
		return $this->postprocessors;
	}

	/**
	 * @param \ITSociaal\Themes\Houtgrutter\Util $util
	 */
	public function __construct(Util $util)
	{
		$this->util = $util;
	}
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

interface RendererFactoryInterface
{
	/**
	 * Create a RendererInterface, if possible
	 *
	 * @param string                             $name Canonicalized name
	 * @param \ITSociaal\Themes\Houtgrutter\Util $util Valid instance
	 *
	 * @return \ITSociaal\Themes\Houtgrutter\RendererInterface|null
	 */
	public static function create($name, Util $util);
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php
namespace ITSociaal\Themes\Houtgrutter;

interface RendererInterface
{
	/**
	 * Render the object
	 *
	 * @return string
	 */
	public function render();
}

/* vi:set ts=4 sw=4 noet: */


code:
<?php _e( 'Downloads', 'Shopp' ); ?>

	<a href="<?php shopp('customer.url'); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>

<?php if ( shopp( 'customer.has-downloads' ) ) : ?>

				<?php _e( 'Product', 'Shopp' ); ?>
				<?php _e( 'Order', 'Shopp' ); ?>
				<?php _e( 'Amount', 'Shopp' ); ?>

		<?php while( shopp( 'customer.downloads' ) ) : ?>

					<?php shopp( 'customer.download', 'name' ); ?> <?php shopp( 'customer.download', 'variation' ); ?>

						<a href="<?php shopp( 'customer.download', 'url' ); ?>"><?php _e( 'Download File', 'Shopp' ); ?> (<?php shopp( 'customer.download', 'size' ); ?>)

					<?php shopp( 'customer.download', 'purchase' ); ?>

					<?php shopp( 'customer.download', 'date' ); ?>

					<?php shopp( 'customer.download', 'total' ); ?>

					<?php shopp( 'customer.download', 'downloads' ); ?> <?php _e( 'Downloads', 'Shopp' ); ?>

		<?php endwhile; ?>

<?php else : ?>

		<?php _e( 'You have no digital product downloads available.', 'Shopp' ); ?>

<?php endif; // end 'has-downloads' ?>

	<a href="<?php shopp( 'customer.url' ); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>


code:
	<a href="<?php shopp( 'customer.url' ); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>

<?php if ( shopp( 'purchase.get-id' ) ) : ?>
	<?php shopp( 'purchase.receipt' ); ?>
	<?php return; ?>
<?php endif; ?>

<form action="<?php shopp( 'customer.action' ); ?>" method="post" class="shopp validate" autocomplete="off">
	<?php if ( shopp( 'customer.has-purchases' ) ) : ?>

					<?php _e( 'Date', 'Shopp' ); ?>
					<?php _e( 'Order', 'Shopp' ); ?>
					<?php _e( 'Status', 'Shopp' ); ?>
					<?php _e( 'Total', 'Shopp' ); ?>

			<?php while( shopp( 'customer.purchases' ) ) : ?>

					<?php shopp( 'purchase.date' ); ?>
					<?php shopp( 'purchase.id' ); ?>
					<?php shopp( 'purchase.status' ); ?>
					<?php shopp( 'purchase.total' ); ?>
					<a href="<?php shopp( 'customer.order' ); ?>"><?php _e( 'View Order', 'Shopp' ); ?>

			<?php endwhile; ?>

	<?php else: ?>

<?php _e( 'You have no orders, yet.', 'Shopp' ); ?>

	<?php endif; // end 'has-purchases' ?>
</form>

	<a href="<?php shopp( 'customer.url' ); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>


code:
<form action="<?php shopp( 'customer.action' ); ?>" method="post" class="shopp validate" autocomplete="off">

	<?php if ( shopp( 'customer.password-changed' ) ) : ?>

<?php _e( 'Your password has been changed successfully.', 'Shopp' ); ?>

	<?php endif; ?>

	<?php if ( shopp( 'customer.profile-saved' ) && shopp( 'customer.password-change-fail' ) ) : ?>

<?php _e( 'Your account has been updated.', 'Shopp' ); ?>

	<?php endif; ?>

		<a href="<?php shopp( 'customer.url' ); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>

			<?php _e( 'Your Account', 'Shopp' ); ?>

				<?php shopp( 'customer.firstname', 'required=true&minlength=2&size=8&title=' . __( 'First Name', 'Shopp' ) ); ?>
				<?php _e( 'First', 'Shopp' ); ?>

				<?php shopp( 'customer.lastname', 'required=true&minlength=3&size=14&title=' . __( 'Last Name', 'Shopp' ) ); ?>
				<?php _e('Last','Shopp'); ?>

				<?php shopp( 'customer.company', 'size=20&title=' . __( 'Company', 'Shopp' ) ); ?>
				<?php _e( 'Company', 'Shopp' ); ?>

				<?php shopp( 'customer.phone', 'format=phone&size=15&title=' . __( 'Phone', 'Shopp' ) ); ?>
				<?php _e( 'Phone', 'Shopp' ); ?>

				<?php shopp( 'customer.email', 'required=true&format=email&size=30&title=' . __( 'Email', 'Shopp' ) ); ?>
				<?php _e( 'Email', 'Shopp' ); ?>

				<?php shopp( 'customer.marketing', 'title=' . __( 'I would like to continue receiving e-mail updates and special offers!', 'Shopp' ) ); ?> <?php _e('I would like to continue receiving e-mail updates and special offers!','Shopp'); ?>

		<?php while ( shopp( 'customer.hasinfo' ) ) : ?>

					<?php shopp( 'customer.info' ); ?>
					<?php shopp( 'customer.info', 'mode=name' ); ?>

		<?php endwhile; ?>

			<?php _e( 'Change Your Password', 'Shopp' ); ?>

				<?php shopp( 'customer.password', 'size=14&title=' . __( 'New Password', 'Shopp' ) ); ?>
				<?php _e( 'New Password', 'Shopp' ); ?>

				<?php shopp( 'customer.confirm-password', '&size=14&title=' . __( 'Confirm Password', 'Shopp' ) ); ?>
				<?php _e('Confirm Password','Shopp'); ?>

			<?php _e( 'Billing Address', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-address', 'title=' . __( 'Billing street address', 'Shopp' ) ); ?>
				<?php _e( 'Street Address', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-xaddress', 'title=' . __( 'Billing address line 2', 'Shopp' ) ); ?>
				<?php _e( 'Address Line 2', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-city', 'title=' . __( 'City billing address', 'Shopp' ) ); ?>
				<?php _e( 'City', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-state', 'title=' . __( 'State/Province/Region billing address', 'Shopp' ) ); ?>
				<?php _e( 'State / Province', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-postcode', 'title=' . __( 'Postal/Zip Code billing address', 'Shopp' ) ); ?>
				<?php _e( 'Postal / Zip Code', 'Shopp' ); ?>

				<?php shopp( 'customer.billing-country', 'title=' . __( 'Country billing address', 'Shopp' ) ); ?>
				<?php _e( 'Country', 'Shopp' ); ?>

			<?php _e( 'Shipping Address', 'Shopp' ); ?>

				<?php shopp( 'customer.shipping-address', 'title=' . __( 'Shipping street address', 'Shopp' ) ); ?>
				<?php _e( 'Street Address', 'Shopp' ); ?>

				<?php shopp( 'customer.shipping-xaddress', 'title=' . __( 'Shipping address line 2', 'Shopp' ) ); ?>
				<?php _e('Address Line 2','Shopp'); ?>

				<?php shopp( 'customer.shipping-city', 'title=' . __( 'City shipping address', 'Shopp' ) ); ?>
				<?php _e( 'City', 'Shopp' ); ?>

				<?php shopp( 'customer.shipping-state', 'title=' . __( 'State/Provice/Region shipping address', 'Shopp' ) ); ?>
				<?php _e( 'State / Province', 'Shopp' ); ?>

				<?php shopp( 'customer.shipping-postcode', 'title=' . __( 'Postal/Zip Code shipping address', 'Shopp' ) ); ?>
				<?php _e( 'Postal / Zip Code', 'Shopp' ); ?>

				<?php shopp( 'customer.shipping-country', 'title=' . __( 'Country shipping address', 'Shopp' ) ); ?>
				<?php _e( 'Country', 'Shopp' ); ?>

<?php shopp( 'customer.save-button', 'label=' . __( 'Save', 'Shopp' ) ); ?>

<a href="<?php shopp( 'customer.url' ); ?>">« <?php _e( 'Return to Account Management', 'Shopp' ); ?>

</form>


code:
	<?php while( shopp( 'storefront.account-menu' ) ) : ?>

			<a href="<?php shopp( 'storefront.account-menuitem', 'url' ); ?>"><?php shopp( 'storefront.account-menuitem' ); ?>

	<?php endwhile; ?>


code:
<?php if ( shopp( 'cart.hasitems' ) ) : ?>
	<form id="cart" action="<?php shopp( 'cart.url' ); ?>" method="post">

			<a href="<?php shopp( 'cart.referrer' ); ?>" class="button">« <?php _e( 'Continue Shopping', 'Shopp' ); ?>
			<a href="<?php shopp( 'checkout.url' ); ?>" class="right button"><?php _e( 'Proceed to Checkout', 'Shopp' ); ?> »

		<?php shopp( 'cart.function' ); ?>

				<?php _e( 'Cart Items', 'Shopp' ); ?>
				<?php _e( 'Quantity', 'Shopp' ); ?>
				<?php _e( 'Item Price', 'Shopp' ); ?>
				<?php _e( 'Item Total', 'Shopp' ); ?>

			<?php while ( shopp( 'cart.items' ) ) : ?>

						<a href="<?php shopp( 'cartitem.url' ); ?>"><?php shopp( 'cartitem.name' ); ?>
						<?php shopp( 'cartitem.options' ); ?>
						<?php shopp( 'cartitem.addons-list' ); ?>
						<?php shopp( 'cartitem.inputs-list' ); ?>

						<?php shopp( 'cartitem.quantity', 'input=text' ); ?>
						<?php shopp( 'cartitem.remove', 'input=button' ); ?>

					<?php shopp( 'cartitem.unitprice' ); ?>
					<?php shopp( 'cartitem.total' ); ?>

			<?php endwhile; ?>

			<?php while ( shopp( 'cart.discounts' ) ) : ?>

						<?php shopp( 'cart.discount-name' ); ?>
						<?php shopp( 'cart.discount-applied', array( 'before' => ' — ' ) ); ?>

			<?php endwhile; ?>

					<?php if ( shopp( 'cart.needs-shipping-estimates' ) ) : ?>
						<?php _e( 'Estimate shipping & taxes for:', 'Shopp' ); ?>
						<?php shopp( 'cart.shipping-estimates' ); ?>
					<?php endif; ?>
					<?php shopp( 'cart.apply-code' ); ?>

				<?php _e( 'Subtotal', 'Shopp' ); ?>
				<?php shopp( 'cart.subtotal' ); ?>

			<?php if ( shopp( 'cart.hasdiscount' ) ) : ?>

					<?php _e( 'Discount', 'Shopp' ); ?>
					-<?php shopp( 'cart.discount' ); ?>

			<?php endif; ?>

			<?php if ( shopp( 'cart.needs-shipped' ) ) : ?>

					<?php shopp( 'cart.shipping', 'label=' . __( 'Estimated Shipping', 'Shopp' ) ); ?>
					<?php shopp( 'cart.shipping' ); ?>

			<?php endif; ?>

				<?php shopp( 'cart.tax', 'label=' . __( 'Tax', 'Shopp' ) ); ?>
				<?php shopp( 'cart.tax' ); ?>

				<?php _e( 'Total', 'Shopp' ); ?>
				<?php shopp( 'cart.total' ); ?>

				<?php shopp( 'cart.update-button' ); ?>

			<a href="<?php shopp( 'cart.referrer' ); ?>" class="button">« <?php _e( 'Continue Shopping', 'Shopp' ); ?>
			<a href="<?php shopp( 'checkout.url' ); ?>" class="right button"><?php _e( 'Proceed to Checkout', 'Shopp' ); ?> »

	</form>

<?php else : ?>

<?php _e( 'There are currently no items in your shopping cart.', 'Shopp' ); ?>

		<a href="<?php shopp( 'storefront.url' ); ?>">« <?php _e( 'Continue Shopping', 'Shopp' ); ?>

<?php endif; ?>


code: <?php shopp( 'storefront.catalog-products' ); ?>


code:
<?php
namespace ITSociaal\Themes\Houtgrutter\Shopp;

shopp('collection.description');
?>

<?php if ( shopp( 'collection.hasproducts', 'load=prices,coverimages' ) ) : ?>

			<?php while( shopp( 'collection.products' ) ) : ?>

					<a href="<?php shopp( 'product.url' ); ?>" itemprop="url">
						<?php shopp( 'product.coverimage', 'width=236&height=142' ); ?>

<?php shopp( 'product.name' ); ?>

							<?php shopp( 'product.saleprice', 'starting=' . __( 'from', 'Shopp' ) ); ?>
<?php if (false): ?>
						<?php if ( shopp( 'product.has-savings' ) ) : ?>

<?php _e( 'Save ', 'Shopp' ); ?><?php shopp( 'product.savings', 'show=percent' ); ?>

						<?php endif; ?>
<?php endif; ?>

					<form action="<?php shopp( 'cart.url' ); ?>" method="post" class="shopp product">
						<?php shopp( 'product.addtocart' ); ?>
					</form>

			<?php endwhile; ?>

<?php else: ?>

<?php _e( 'No products were found.', 'Shopp' ); ?>

<?php endif; ?>


code:
<form action="<?php shopp( 'checkout.url' ); ?>" method="post" class="shopp validate" id="checkout">

	<?php shopp( 'checkout.cart-summary' ); ?>

	<?php if ( shopp( 'cart.hasitems' ) ) : ?>

		<?php shopp( 'checkout.function' ); ?>

			<?php if ( shopp( 'customer.notloggedin' ) ) : ?>

					<?php _e('Login to Your Account','Shopp'); ?>
					<?php _e('Email','Shopp'); ?><?php shopp('customer','account-login','size=20&title='.__('Login','Shopp')); ?>
					<?php _e('Password','Shopp'); ?><?php shopp('customer','password-login','size=20&title='.__('Password','Shopp')); ?>
					<?php shopp('customer','login-button','context=checkout&value=Login'); ?>

			<?php endif; ?>

				<?php _e('Contact Information','Shopp'); ?>
				<?php _e('First','Shopp'); ?><?php shopp('checkout','firstname','required=true&minlength=2&size=8&title='.__('First Name','Shopp')); ?>
				<?php _e('Last','Shopp'); ?><?php shopp('checkout','lastname','required=true&minlength=2&size=14&title='.__('Last Name','Shopp')); ?>
				<?php _e('Company/Organization','Shopp'); ?><?php shopp('checkout','company','size=22&title='.__('Company/Organization','Shopp')); ?>

				<?php _e('Phone','Shopp'); ?><?php shopp('checkout','phone','format=phone&size=15&title='.__('Phone','Shopp')); ?>
				<?php _e('Email','Shopp'); ?><?php shopp('checkout','email','required=true&format=email&size=30&title='.__('Email','Shopp')); ?>

			<?php if ( shopp( 'customer.notloggedin' ) ) : ?>

					<?php _e('Password','Shopp'); ?>
					<?php shopp('checkout','password','required=true&format=passwords&size=16&title='.__('Password','Shopp')); ?>

					<?php _e('Confirm Password','Shopp'); ?>
					<?php shopp('checkout','confirm-password','required=true&format=passwords&size=16&title='.__('Password Confirmation','Shopp')); ?>

			<?php endif; ?>

			<?php if ( shopp( 'cart.needs-shipped' ) ) : ?>

			<?php else: ?>

			<?php endif; ?>

					<?php _e( 'Billing Address', 'Shopp' ); ?>

						<?php _e( 'Name', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-name', 'required=false&title=' . __( 'Bill to', 'Shopp' ) ); ?>

						<?php _e( 'Street Address', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-address', 'required=true&title=' . __( 'Billing street address', 'Shopp' ) ); ?>

						<?php _e( 'Address Line 2', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-xaddress', 'title=' . __( 'Billing address line 2', 'Shopp' ) ); ?>

						<?php _e( 'City', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-city', 'required=true&title=' . __( 'City billing address', 'Shopp' ) ); ?>

						<?php _e( 'State / Province', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-state', 'required=auto&title=' . __( 'State/Province/Region billing address', 'Shopp' ) ); ?>

						<?php _e( 'Postal / Zip Code', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-postcode', 'required=true&title=' . __( 'Postal/Zip Code billing address', 'Shopp' ) ); ?>

						<?php _e( 'Country', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-country', 'required=true&title=' . __( 'Country billing address', 'Shopp' ) ); ?>

			<?php if ( shopp( 'cart.needs-shipped' ) ) : ?>

						<?php shopp( 'checkout.same-shipping-address' ); ?>

					<?php _e( 'Shipping Address', 'Shopp' ); ?>

						<?php _e( 'Name', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-name', 'required=false&title=' . __( 'Ship to', 'Shopp' ) ); ?>

						<?php _e( 'Street Address', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-address', 'required=true&title=' . __( 'Shipping street address', 'Shopp' ) ); ?>

						<?php _e( 'Address Line 2', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-xaddress', 'title=' . __( 'Shipping address line 2', 'Shopp' ) ); ?>

						<?php _e( 'City', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-city', 'required=true&title=' . __( 'City shipping address', 'Shopp' ) ); ?>

						<?php _e( 'State / Province', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-state', 'required=auto&title=' . __( 'State/Provice/Region shipping address', 'Shopp' ) ); ?>

						<?php _e( 'Postal / Zip Code', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-postcode', 'required=true&title=' . __( 'Postal/Zip Code shipping address', 'Shopp' ) ); ?>

						<?php _e( 'Country', 'Shopp' ); ?>
						<?php shopp( 'checkout.shipping-country', 'required=true&title=' . __( 'Country shipping address', 'Shopp' ) ); ?>

			<?php else: ?>

			<?php endif; ?>

			<?php if ( shopp( 'checkout.billing-localities' ) ) : ?>

						<?php _e( 'Local Jurisdiction', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-locale' ); ?>

			<?php endif; ?>

Selecteer een betaalmethode:

				<?php shopp( 'checkout', 'payment-options', ['type'=>'list','default'=>'ideal'] ); ?>
				<?php shopp( 'checkout.gateway-inputs' ); ?>

			<?php if ( shopp( 'checkout.card-required' ) ) : ?>

					<?php _e( 'Payment Information', 'Shopp' ); ?>

						<?php _e( 'Credit/Debit Card Number', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-card', 'required=true&size=30&title=' . __( 'Credit/Debit Card Number', 'Shopp' ) ); ?>

						<?php _e( 'Security ID', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-cvv', 'size=7&minlength=3&maxlength=4&title=' . __( 'Card\'s security code (3-4 digits on the back of the card)', 'Shopp' ) ); ?>

						<?php _e('MM','Shopp'); ?>
						<?php shopp( 'checkout.billing-cardexpires-mm', 'required=true&minlength=2&maxlength=2&title=' . __( 'Card\'s 2-digit expiration month', 'Shopp' ) ); ?> /

						<?php _e( 'YY', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-cardexpires-yy', 'required=true&minlength=2&maxlength=2&title=' . __( 'Card\'s 2-digit expiration year', 'Shopp' ) ); ?>

						<?php _e( 'Card Type', 'Shopp' ); ?>
						<?php shopp( 'checkout.billing-cardtype', 'required=true&title=' . __( 'Card Type', 'Shopp' ) ); ?>

				<?php if ( shopp( 'checkout.billing-xcsc-required' ) ) : // Extra billing security fields ?>

							<?php _e( 'Start Date', 'Shopp' ); ?>
							<?php shopp( 'checkout.billing-xcsc', 'input=start&size=7&minlength=5&maxlength=5&title=' . __( 'Card\'s start date (MM/YY)', 'Shopp' ) ); ?>

							<?php _e( 'Issue #', 'Shopp' ); ?>
							<?php shopp( 'checkout.billing-xcsc', 'input=issue&size=7&minlength=3&maxlength=4&title=' . __( 'Card\'s issue number', 'Shopp' ) ); ?>

				<?php endif; ?>

			<?php endif; ?>

<?php if (false): ?>

					<?php shopp('checkout','marketing'); ?> <?php _e( 'Yes, I would like to receive e-mail updates and special offers!', 'Shopp' ); ?>

<?php endif; ?>

<?php shopp( 'checkout.submit', 'value=' . __( 'Submit Order', 'Shopp' ) ); ?>

	<?php endif; ?>
</form>


code:
<?php shopp( 'checkout.cart-summary' ); ?>

<form action="<?php shopp( 'checkout.url' ); ?>" method="post" class="shopp" id="checkout">
	<?php shopp( 'checkout.function', 'value=confirmed' ); ?>

<?php shopp( 'checkout.confirm-button', 'value=' . __( 'Confirm Order', 'Shopp') ); ?>

</form>


code:
Content-type: text/html; charset=utf-8
From: <?php shopp( 'purchase.email-from' ); ?>
To: <?php shopp( 'purchase.email-to' ); ?>
Subject: <?php shopp( 'purchase.email-subject' ); ?>

<?php bloginfo( 'name' ); ?>

<?php _e( 'Order', 'Shopp' ); ?> <?php shopp( 'purchase.id' ); ?>

		<?php shopp( 'purchase.receipt' ); ?>
		<?php if ( shopp( 'purchase.notpaid' ) && shopp( 'checkout.get-offline-instructions' ) ) : ?>
			<?php shopp( 'checkout.offline-instructions' ); ?>
		<?php endif; ?>


code:
Content-type: text/html; charset=utf-8
From: <?php shopp( 'purchase.email-from' ); ?>
To: <?php shopp( 'purchase.email-to' ); ?>
Subject: <?php shopp( 'purchase.email-subject' ); ?>

<?php bloginfo( 'name' ); ?>

<?php _e( 'Order Shipment Notification', 'Shopp' ); ?> <?php shopp( 'purchase','id' ); ?>

						<fieldset class="shipping">
							<legend><?php _e( 'Ship to', 'Shopp' ); ?></legend>
							<address><?php shopp( 'purchase.shipname' ); ?>

								<?php shopp( 'purchase.shipaddress' ); ?>

								<?php shopp( 'purchase.shipxaddress' ); ?>
								<?php shopp( 'purchase.shipcity' ); ?>, <?php shopp( 'purchase.shipstate' ); ?> <?php shopp( 'purchase.shippostcode' ); ?>

								<?php shopp( 'purchase.shipcountry' ); ?></address>
						</fieldset>

						<fieldset class="shipping">
							<legend><?php _e( 'Shipment', 'Shopp' ); ?></legend>

									<?php _e( 'Tracking Number:', 'Shopp' ); ?>
									<?php shopp( 'purchase.email-event', 'name=tracking&link=on' ); ?>

									<?php _e( 'Carrier:', 'Shopp' ); ?>
									<?php shopp( 'purchase.email-event', 'name=carrier' ); ?>

									<?php _e( 'Order Date:', 'Shopp' ); ?>
									<?php shopp( 'purchase.date' ); ?>

						</fieldset>

			<?php if ( shopp( 'purchase.hasitems' ) ) : ?>

							<?php _e( 'Items', 'Shopp' ); ?>
							<?php _e( 'Quantity', 'Shopp' ); ?>

					<?php while ( shopp( 'purchase.items' ) ) : ?>

								<?php shopp( 'purchase.item-name' ); ?><?php shopp( 'purchase.item-options', 'before= – ' ); ?>

								<?php shopp( 'purchase.item-sku' ); ?>

								<?php shopp( 'purchase.item-addons-list' ); ?>

							<?php shopp( 'purchase.item-quantity' ); ?>

					<?php endwhile; ?>

			<?php endif; ?>


code:
Content-type: text/html; charset=utf-8
From: <?php shopp( 'purchase.email-from' ); ?>
To: <?php shopp( 'purchase.email-to' ); ?>
Subject: <?php shopp( 'purchase.email-subject' ); ?>

<?php bloginfo( 'name' ); ?>

<?php _e( 'Order Update', 'Shopp' ); ?>

		<?php shopp( 'purchase.email-note' ); ?>

<?php _e( 'Your order is', 'Shopp' ); ?>: <?php shopp( 'purchase.status' ); ?>

		<?php shopp( 'purchase.receipt' ); ?>


code:
<?php _e( 'Errors', 'Shopp' ); ?>

		<?php shopp( 'storefront.errors' ); ?>


code:
<form action="<?php shopp( 'customer', 'url' ); ?>" method="post" class="shopp" id="login">

<?php _e( 'Recover your password', 'Shopp'); ?>

			<?php shopp('customer','account-login','size=20&title='.__('Login','Shopp')); ?><?php shopp('customer','login-label'); ?>
			<?php shopp('customer','recover-button'); ?>

</form>


code:
<?php if ( shopp( 'customer.notloggedin' ) ) : ?>
	<form action="<?php shopp( 'customer.url' ); ?>" method="post" class="shopp shopp_page" id="login">

				<?php _e( 'Account Login', 'Shopp' ); ?>

					<?php shopp( 'customer.login-label' ); ?>
					<?php shopp( 'customer.account-login', 'size=20&title=' . __( 'Login', 'Shopp' ) ); ?>

					<?php _e( 'Password', 'Shopp' ); ?>
					<?php shopp( 'customer.password-login', 'size=20&title=' . __( 'Password', 'Shopp' ) ); ?>

					<?php shopp( 'customer.login-button' ); ?>

				<a href="<?php shopp( 'customer.recover-url' ); ?>"><?php _e( 'Lost your password?', 'Shopp' ); ?>

	</form>
<?php endif; ?>


code:
<?php if ( shopp( 'product.found' ) ) : ?>
	<?php shopp( 'product.gallery', 'p_setting=gallery-previews&thumbsetting=gallery-thumbnails' ); ?>

<?php shopp( 'product.name' ); ?>

<?php shopp( 'product.summary' ); ?>

	<?php shopp('product.schema'); ?>

	<?php if ( shopp( 'product.onsale' ) ) : ?>

<?php shopp( 'product.price' ); ?>

<?php shopp( 'product.saleprice' ); ?>

		<?php if ( shopp( 'product.has-savings' ) ): ?>

<?php _e( 'You save', 'Shopp' ); ?> <?php shopp( 'product.savings' ); ?> (<?php shopp( 'product.savings', 'show=%' ); ?>)!

		<?php endif; ?>
	<?php else: ?>

<?php shopp( 'product.price' ); ?>

	<?php endif; ?>

	<?php if ( shopp( 'product.freeshipping' ) ) : ?>

<?php _e( 'Free Shipping!', 'Shopp' ); ?>

	<?php endif; ?>

	<form action="<?php shopp( 'cart.url' ); ?>" method="post" class="shopp validate validation-alerts">
		<?php if ( shopp( 'product.has-variants' ) ) : ?>

				<?php shopp( 'product.variants', 'mode=multiple&label=true&defaults=' . __( 'Select an option', 'Shopp') . '&before_menu=
&after_menu=
' ); ?>

		<?php endif; ?>

		<?php if ( shopp( 'product.has-addons' ) ) : ?>

				<?php shopp( 'product.addons', 'mode=menu&label=true&defaults=' . __( 'Select an add-on', 'Shopp') . '&before_menu=
&after_menu=
' ); ?>

		<?php endif; ?>

			<?php shopp( 'product.quantity', 'class=selectall&input=menu' ); ?>
			<?php shopp( 'product.addtocart' ); ?>

	</form>

	<?php shopp( 'product.description' ); ?>

	<?php if ( shopp( 'product.has-specs' ) ) : ?>

			<?php while ( shopp( 'product.specs' ) ) : ?>

<?php shopp( 'product.spec', 'name' ); ?>:

<?php shopp( 'product.spec', 'content' ); ?>

			<?php endwhile; ?>

	<?php endif; ?>

<?php else : ?>

<?php _e( 'Product Not Found', 'Shopp' ); ?>

<?php _e( 'Sorry! The product you requested is not found in our catalog!', 'Shopp' ); ?>

<?php endif; ?>