<?php

namespace Ekyna\Component\Payum\Sips\Api;

use Ekyna\Component\Payum\Sips\Client\Client;

/**
 * Class Api
 * @package Ekyna\Component\Payum\Sips\Api
 * @author Étienne Dauvergne <contact@ekyna.com>
 */
class Api
{
    /**
     * @var array
     */
    private $config;

    /**
     * @var Client
     */
    private $client;

    /**
     * Constructor.
     *
     * @param array  $config
     * @param Client $client
     */
    public function __construct(array $config, Client $client)
    {
        $this->config = array_filter($config, function ($value) {
            return null !== $value;
        });

        $this->client = $client;
    }

    /**
     * Runs the request binary with given data
     * and returns the generated form.
     *
     * @param array $data
     * @return string
     */
    public function request(array $data)
    {
        $data = array_replace($this->config, $data);

        return $this->client->callRequest($data);
    }

    /**
     * Runs the response binary and returns the new data.
     *
     * @param string $hash
     * @return array
     */
    public function response($hash)
    {
        return $this->client->callResponse($hash);
    }
}


<?php

namespace Sbp\Plugins\Core;

use Sbp\Plugins\Helpers\FileHelper;

class Constants
{
    /**
     * Get constant regex pattern.
     *
     * @param string constant name
     *
     * @return string regex pattern
     */
    private static function constantPattern($constant)
    {
        return '#(?<![a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff$]|::|->)__'.preg_quote($constant).'(?![a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff])#';
    }

    /***********************************/
    /* Replace quick access constants. */
    /***********************************/
    public static function quickAccessConstants($content, $caller)
    {
        $validSubst = call_user_func(array($caller, 'getValidStringSurrogates'));
        $validComments = call_user_func(array($caller, 'getValidComments'));
        $lastParsedFile = call_user_func(array($caller, 'getLastParsedFile'));

        $__file = is_null($lastParsedFile) ? null : FileHelper::cleanPath($lastParsedFile);
        $__dir = is_null($__file) ? null : dirname($__file);
        $__file = call_user_func(array($caller, 'includeString'), $__file);
        $__dir = call_user_func(array($caller, 'includeString'), $__dir);
        $__server = array(
            'QUERY_STRING',
            'AUTH_USER',
            'AUTH_PW',
            'PATH_INFO',
            'REQUEST_METHOD',
            'USER_AGENT' => 'HTTP_USER_AGENT',
            'REFERER' => 'HTTP_REFERER',
            'HOST' => 'HTTP_HOST',
            'URI' => 'REQUEST_URI',
            'IP' => 'REMOTE_ADDR',
        );
        foreach ($__server as $key => $value) {
            if (is_int($key)) {
                $key = $value;
            }
            $content = preg_replace(
                static::constantPattern($key),
                '$_SERVER['.call_user_func(array($caller, 'includeString'), $value).']',
                $content
            );
        }

        /************************/
        /* Constantes spéciales */
        /************************/
        $content = preg_replace(
            static::constantPattern('FILE'),
            $__file,
            $content
        );

        $content = preg_replace(
            static::constantPattern('DIR'),
            $__dir,
            $content
        );

        foreach (array(
            'CLASS',
            'FUNCTION',
            'LINE',
            'METHOD',
            'NAMESPACE',
            'TRAIT',
        ) as $constant) {
            $content = preg_replace(
                static::constantPattern($constant),
                '__'.$constant.'__',
                $content
            );
        }

        return $content;
    }

    /********************/
    /* Ohter constants. */
    /********************/
    public static function otherConstants($content, $caller)
    {
        return array(
            '#'.constant($caller.'::START').'('.constant($caller.'::CONSTNAME').')\s*=#' => '$1const $2 =',
            '#\#('.constant($caller.'::CONSTNAME').')\s*=([^;]+);#' => 'define("$1",$2);',
            '#([\(;\s\.+/*=])~:('.constant($caller.'::CONSTNAME').')#' => '$1static::$2',
            '#([\(;\s\.+/*=]):('.constant($caller.'::CONSTNAME').')#' => '$1static::$2',
        );
    }
}


<?php
/**
 * Project vn-telco-phonenumber.
 * Created by PhpStorm.
 * User: 713uk13m <dev@nguyenanhung.com>
 * Date: 10/22/18
 * Time: 08:44
 */

namespace nguyenanhung\VnTelcoPhoneNumber;

use nguyenanhung\MyDebug\Debug;
use nguyenanhung\MyDebug\Benchmark;
use nguyenanhung\VnTelcoPhoneNumber\Interfaces\ProjectInterface;
use nguyenanhung\VnTelcoPhoneNumber\Interfaces\PhoneRoutingInterface;
use nguyenanhung\VnTelcoPhoneNumber\Repository\DataRepository;

/**
 * Class PhoneRouting
 *
 * Thiết kế theo chuẩn tài liệu - MNP - Help Documentation
 *
 * @package    nguyenanhung\VnTelcoPhoneNumber
 * @author     713uk13m <dev@nguyenanhung.com>
 * @copyright  713uk13m <dev@nguyenanhung.com>
 */
class PhoneRouting implements ProjectInterface, PhoneRoutingInterface
{
    const IS_MNP_LENGTH = 16;
    /** @var object \nguyenanhung\VnTelcoPhoneNumber\Phone_number */
    private $phoneNumber;
    /** @var object \nguyenanhung\VnTelcoPhoneNumber\Phone_telco */
    private $phoneTelco;
    /** @var object \nguyenanhung\MyDebug\Benchmark */
    private $benchmark;
    /** @var object \nguyenanhung\MyDebug\Debug Class Debug Object */
    private $debug;
    /** @var bool DEBUG Status */
    private $debugStatus = FALSE;
    /** @var null|string Set Debug Level: DEBUG, INFO, ERROR ... etc */
    private $debugLevel = NULL;
    /** @var string Logger Path */
    private $loggerPath = NULL;
    /** @var null Logger Sub Path */
    private $loggerSubPath = NULL;
    /** @var string Filename to write Log */
    private $loggerFilename = NULL;

    /**
     * PhoneRouting constructor.
     */
    public function __construct()
    {
        if (self::USE_BENCHMARK === TRUE) {
            $this->benchmark = new Benchmark();
            $this->benchmark->mark('code_start');
        }
        $this->debug = new Debug();
        if ($this->debugStatus === TRUE) {
            $this->debug->setDebugStatus($this->debugStatus);
            $this->debug->setGlobalLoggerLevel($this->debugLevel);
            $this->debug->setLoggerPath($this->loggerPath);
            $this->debug->setLoggerSubPath(__CLASS__);
            if (empty($this->loggerFilename)) {
                $this->loggerFilename = 'Log-' . date('Y-m-d') . '.log';
            }
            $this->debug->setLoggerFilename($this->loggerFilename);
        }
        $this->phoneNumber = new Phone_number();
        $this->phoneTelco  = new Phone_telco();
    }

    /**
     * PhoneRouting destructor.
     */
    public function __destruct()
    {
        if (self::USE_BENCHMARK === TRUE) {
            $this->benchmark->mark('code_end');
            $this->debug->debug(__FUNCTION__, 'Elapsed Time: ===> ' . $this->benchmark->elapsed_time('code_start', 'code_end'));
            $this->debug->debug(__FUNCTION__, 'Memory Usage: ===> ' . $this->benchmark->memory_usage());
        }
    }

    /**
     * Get current version of Package
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 08:42
     *
     * @return mixed|string Current version of Package
     */
    public function getVersion()
    {
        return self::VERSION;
    }

    /**
     * Function setDebugStatus
     * Set Var to DEBUG and save Log
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/9/18 13:47
     *
     * @param bool $debugStatus TRUE if Enable Debug, other if Not
     *
     * @return mixed|void
     */
    public function setDebugStatus($debugStatus = FALSE)
    {
        $this->debugStatus = $debugStatus;
    }

    /**
     * Function setDebugLevel
     * Set String Debug Level
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/9/18 13:47
     *
     * @param bool|string $debugLevel Level to Set Debug: DEBUG, INFO, ERROR, etc...
     *
     * @return mixed|void
     */
    public function setDebugLevel($debugLevel = NULL)
    {
        $this->debugLevel = $debugLevel;
    }

    /**
     * Function setLoggerPath
     * Main Logger Path to Save Log if DEBUG is Enable
     *
     * @author  : 713uk13m <dev@nguyenanhung.com>
     * @time    : 10/9/18 13:51
     *
     * @param bool $loggerPath Set Logger Path to Save
     *
     * @example /your/to/path
     *
     * @return mixed|void
     */
    public function setLoggerPath($loggerPath = FALSE)
    {
        $this->loggerPath = $loggerPath;
    }

    /**
     * Function setLoggerSubPath
     * Sub Logger Path to Save Log if DEBUG is Enable
     *
     * @author  : 713uk13m <dev@nguyenanhung.com>
     * @time    : 10/8/18 14:38
     *
     * @param bool $loggerSubPath Set Logger Sub Path to Save
     *
     * @example /your/to/path
     *
     * @return mixed|void
     */
    public function setLoggerSubPath($loggerSubPath = FALSE)
    {
        $this->loggerSubPath = $loggerSubPath;
    }

    /**
     * Function setLoggerFilename
     * Logger filename to Save Log if DEBUG is Enable
     *
     * @author  : 713uk13m <dev@nguyenanhung.com>
     * @time    : 10/8/18 14:38
     *
     * @param bool $loggerFilename Set Logger Filename to Save
     *
     * @example Log-2018-10-09.log
     *
     * @return mixed|void
     */
    public function setLoggerFilename($loggerFilename = FALSE)
    {
        $this->loggerFilename = $loggerFilename;
    }

    /**
     * Hàm kiểm tra tính hợp lệ của Routing number
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 10:28
     *
     * @param string $routingNumber Routing Number của nhà mạng
     *
     * @return null|array Mảng dữ liệu của nhà mạng nếu tồn tại, null nếu không tồn tại
     */
    public function checkRoutingNumber($routingNumber = '')
    {
        $routing = (string) strval($routingNumber);
        $routing = self::NUMBER_PREFIX . $routing;
        $data    = DataRepository::getData('vn_routing_number');
        if (isset($data[$routing])) {
            return $data[$routing];
        } else {
            return NULL;
        }
    }

    /**
     * Hàm kiểm tra số thuê bao có thuộc tập MNP hay không
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 12:02
     *
     * @param string $called số thuê bao đầu vào
     *
     * @return bool|null TRUE nếu thuộc MNP, FALSE nếu không thuộc MNP, NULL nếu called là rỗng
     */
    public function isMnp($called = '')
    {
        if (empty($called)) {
            return NULL;
        }
        // Format new: 0084 + RN + MSISDN -> 0084002914692692 -> str_len = 16
        // Format old: 0084 + MSISDN -> 0084914692692 -> str_len = 13
        $length = mb_strlen($called);
        if ($length == self::IS_MNP_LENGTH) {
            $isMnp = TRUE;
        } else {
            $isMnp = FALSE;
        }

        return $isMnp;
    }

    /**
     * Hàm lấy Routing Number từ số điện thoại Input vào
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 20:20
     *
     * @param string $called Số điện thoại cần kiểm tra
     *
     * @return bool|null|string Routing Number trả về nếu hợp lệ, FALSE nếu không hợp lệ, Null nếu không thuộc dải MNP
     */
    public function getRoutingNumberFromCalled($called = '')
    {
        if ($this->isMnp($called) === TRUE) {
            // Số nằm trong dải chuyển
            $format = $this->phoneNumber->format($called, self::FORMAT_NATIONAL);
            // Đặt trong trường hợp tất cả số điện thoại đã chuyển sang dạng 10 số
            $routingNumber = mb_substr($format, 0, -9);
            if ($this->checkRoutingNumber($routingNumber) !== NULL) {
                return $routingNumber;
            } else {
                return FALSE;
            }
        } else {
            return NULL;
        }
    }

    /**
     * Hàm lấy thông tin nhà mạng từ Routing Number
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 20:33
     *
     * @param string      $number Số cần check: 0084 + RN + MSISDN
     * @param null|string $field  Tham số telco cần check
     *
     * @return array|mixed|null|string Thông tin nhà mạng trong trường hợp thành công
     *                                 Null nếu Routing number không hợp lệ
     */
    public function detectCarrierFromRoutingNumber($number = '', $field = NULL)
    {
        $checkNumberIsMnp = $this->isMnp($number);
        if ($checkNumberIsMnp === TRUE) {
            // Số thuộc dải MNP
            $routingNumber = $this->getRoutingNumberFromCalled($number);
            if (!empty($routingNumber)) {
                // Routing number hợp lệ
                $routingName = $this->checkRoutingNumber($routingNumber);
                if (empty($field)) {
                    $result = $routingName;
                } else {
                    $result = $this->phoneTelco->carrier_data($routingName, $field);
                }
            } else {
                // Routing number không hợp lệ
                $result = NULL;
            }
        } else {
            // Số không thuộc dải MNP
            $number = $this->phoneNumber->format($number);
            $result = $this->phoneNumber->detect_carrier($number, $field);
        }

        return $result;
    }
}


<?php

namespace Ekyna\Component\Payum\Sips\Action;

use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetStatusInterface;

/**
 * Class StatusAction
 * @package Ekyna\Component\Payum\Sips\Action
 * @author Étienne Dauvergne <contact@ekyna.com>
 */
class StatusAction implements ActionInterface
{
    /**
     * {@inheritdoc}
     */
    public function execute($request)
    {
        RequestNotSupportedException::assertSupports($this, $request);

        /** @var GetStatusInterface $request */

        $model = ArrayObject::ensureArrayObject($request->getModel());

        if (false == $model['transaction_id']) {
            $request->markNew();
            return;
        }

        if (false != $responseCode = $model['response_code']) {
            // Success
            if ('00' === $responseCode) {
                $request->markCaptured();
                return;
            }
            // Cancelled by user
            if ('17' === $responseCode) {
                $request->markCanceled();
                return;
            }
            // Failure
            $request->markFailed();
            return;
        }

        $request->markPending();
    }

    /**
     * {@inheritdoc}
     */
    public function supports($request)
    {
        return
            $request instanceof GetStatusInterface &&
            $request->getModel() instanceof \ArrayAccess
        ;
    }
}


<?php
/**
 * Project vn-telco-phonenumber.
 * Created by PhpStorm.
 * User: 713uk13m <dev@nguyenanhung.com>
 * Date: 10/4/18
 * Time: 14:30
 */

namespace nguyenanhung\VnTelcoPhoneNumber;

use nguyenanhung\VnTelcoPhoneNumber\Interfaces\ProjectInterface;
use nguyenanhung\VnTelcoPhoneNumber\Interfaces\SmsLinkInterface;
use nguyenanhung\VnTelcoPhoneNumber\Repository;

/**
 * Class SmsLink
 *
 * @package    nguyenanhung\VnTelcoPhoneNumber
 * @author     713uk13m <dev@nguyenanhung.com>
 * @copyright  713uk13m <dev@nguyenanhung.com>
 */
class SmsLink implements ProjectInterface, SmsLinkInterface
{
    /**
     * SmsLink constructor.
     */
    public function __construct()
    {
    }

    /**
     * Get current version of Package
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/22/18 08:42
     *
     * @return mixed|string Current version of Package
     */
    public function getVersion()
    {
        return self::VERSION;
    }

    /**
     * Function addScript
     * Call with add Content Js Sms
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/9/18 13:39
     *
     * @return mixed|null Content Js Sms Link from file config sms_link
     * @see   /Repository/config/sms_link.php
     */
    public function addScript()
    {
        $smsLink = Repository\DataRepository::getData('sms_link');
        if (isset($smsLink['script'])) {
            return $smsLink['script'];
        }

        return NULL;
    }

    /**
     * Function getLink
     * Get Link include Sms to Sending, use Content place href='''
     *
     * @author: 713uk13m <dev@nguyenanhung.com>
     * @time  : 10/9/18 13:40
     *
     * @param string $phone_number Phone number to parse
     * @param string $body         Body Sms to Sending
     *
     * @return mixed|string Content Send Sms
     */
    public function getLink($phone_number = '', $body = '')
    {
        if (!empty($body)) {
            $body = "?body=" . $body;
        }
        $sms = 'sms:' . trim($phone_number . $body);

        return $sms;
    }
}


<?php

namespace Sbp\Plugins\Core;

class Indentation
{
    protected static function findLastBlock(&$line, array $blocks)
    {
        $position = false;
        foreach ($blocks as $block) {
            if (preg_match('#(?<![a-zA-Z0-9$_])'.$block.'(?![a-zA-Z0-9_])#s', $line, $match, PREG_OFFSET_CAPTURE)) {
                $pos = $match[0][1] + 1;
                if ($position === false || $pos > $position) {
                    $position = $pos;
                }
            }
        }

        return $position;
    }

    protected static function isBlock(&$line, &$grouped, $iRead, $pattern)
    {
        if (substr(rtrim($line), -1) === ';') {
            return false;
        }
        $blocks = explode('|', $pattern);
        $find = static::findLastBlock($line, $blocks);
        $pos = $find ?: 0;
        $open = substr_count($line, '(', $pos);
        $close = substr_count($line, ')', $pos);
        if ($open > $close) {
            return false;
        }
        if ($open < $close) {
            $indent = $close - $open;
            $content = ' '.implode("\n", array_slice($grouped, 0, $iRead));
            while ($indent !== 0) {
                $open = strrpos($content, '(') ?: 0;
                $close = strrpos($content, ')') ?: 0;
                if ($open > $close) {
                    $indent--;
                    $content = substr($content, 0, $open);
                } else {
                    $indent++;
                    $content = substr($content, 0, $close);
                }
            }
            $content = substr($content, 1);
            $find = static::findLastBlock($content, $blocks);
            $pos = $find ?: 0;

            return $find !== false && !preg_match('#(?<!->)\s*\{#U', substr($content, $pos));
        }

        return $find !== false && !preg_match('#(?<!->)\s*\{#U', substr($line, $pos));
    }

    /**
     * Add { on indent and } on outdent.
     */
    public static function addBracesOnIndent($content, $caller)
    {
        $content = explode("\n", $content);
        $curind = array();
        $previousRead = '';
        $previousWrite = '';
        $iRead = 0;
        $iWrite = 0;
        $inInterface = false;
        foreach ($content as $index => &$line) {
            if (trim($line) !== '') {
                $espaces = strlen(str_replace("\t", '    ', $line)) - strlen(ltrim($line));
                $indent = empty($curind) ? -1 : end($curind);
                if ($inInterface !== false && $indent <= $inInterface) {
                    $inInterface = false;
                }
                if (preg_match('`^\s*interface\s`', $previousRead)) {
                    $inInterface = $indent;
                }
                if (($espaces <= $indent || ($indent === -1 && $espaces === 0)) && preg_match('#(?<![a-zA-Z0-9_\x7f-\xff$\(])('.constant($caller.'::ALLOW_EMPTY_BLOCKS').')(?![a-zA-Z0-9_\x7f-\xff])#', $previousRead) && strpos($previousRead, '{') === false) {
                    $previousRead .= preg_match('`^\s*namespace\s`', $previousRead) || (preg_match('`^\s*([a-zA-Z_]+\s+)*function\s`', $previousRead) && $inInterface !== false) ? ';' : ' {}';
                }
                if ($espaces > $indent) {
                    if (static::isBlock($previousRead, $content, $iRead, constant($caller.'::BLOCKS'))) {
                        if (substr(rtrim($previousRead), -1) !== '{'
                        && substr(ltrim($line), 0, 1) !== '{') {
                            $curind[] = $espaces;
                            $previousRead .= '{';
                        }
                    }
                } elseif ($espaces < $indent) {
                    while ($espaces < ($pop = end($curind))) {
                        if (trim($previousWrite, "\t }") === '') {
                            if (strpos($previousWrite, '}') === false) {
                                $previousWrite = str_repeat(' ', $espaces);
                            }
                            $previousWrite .= '}';
                        } else {
                            $length = strlen(ltrim($line));
                            if ($length && ($diff = strlen($line) - $length) > 0) {
                                $line = substr($line, 0, $diff).'} '.substr($line, $diff);
                            } else {
                                $line = '}'.$line;
                            }
                        }
                        array_pop($curind);
                    }
                }
                $previousRead = &$line;
                $iRead = $index;
            }
            $previousWrite = &$line;
            $iWrite = $index;
        }
        $content = implode("\n", $content);
        if (!empty($curind)) {
            $braces = str_repeat('}', count($curind));
            $content .= substr($content, -1) === "\n" ? $braces."\n" : "\n".$braces;
        }

        return $content;
    }
}


<?php

namespace Sbp\Plugins\Core;

class ClassName
{
    /**************************/
    /* Parse class structure. */
    /**************************/
    public static function className($content, $caller)
    {
        return array(
            '#
            (
                (?:^|\S\s*)
                \n[\t ]*
            )
            (
                (?:
                    (?:'.constant($caller.'::ABSTRACT_SHORTCUTS').')
                    \s+
                )?
                \\\\?
                (?:'.constant($caller.'::VALIDNAME').'\\\\)*
                '.constant($caller.'::VALIDNAME').'
            )
            (?:
                (?::|\s+:\s+|\s+extends\s+)
                (
                    \\\\?
                    '.constant($caller.'::VALIDNAME').'
                    (?:\\\\'.constant($caller.'::VALIDNAME').')*
                )
            )?
            (?:
                (?:<<<|\s+<<<\s+|\s+implements\s+)
                (
                    \\\\?
                    '.constant($caller.'::VALIDNAME').'
                    (?:\\\\'.constant($caller.'::VALIDNAME').')*
                    (?:
                        \s*,\s*
                        \\\\?
                        '.constant($caller.'::VALIDNAME').'
                        (?:\\\\'.constant($caller.'::VALIDNAME').')*
                    )*
                )
            )?
            (
                \s*
                (?:{(?:.*})?)?
                \s*\n
            )
            #xi',
            array(get_class(), '__parseClass'),
        );
    }

    /***********************************/
    /* Parse class structure callback. */
    /***********************************/
    public static function __parseClass($match, $caller)
    {
        list($all, $start, $class, $extend, $implement, $end) = $match;
        $class = trim($class);
        if (in_array(substr($all, 0, 1), str_split(',(+-/*&|'))
        || in_array($class, array_merge(
            array('else', 'try', 'default:', 'echo', 'print', 'exit', 'continue', 'break', 'return', 'do'),
            explode('|', constant($caller.'::PHP_WORDS'))
        ))) {
            return $all;
        }
        $className = preg_replace('#^(?:'.constant($caller.'::ABSTRACT_SHORTCUTS').')\s+#', '', $class, -1, $isAbstract);
        $codeLine = $start.($isAbstract ? 'abstract ' : '').'class '.$className.
            (empty($extend) ? '' : ' extends '.trim($extend)).
            (empty($implement) ? '' : ' implements '.trim($implement)).
            ' '.trim($end);

        return $codeLine.str_repeat("\n", substr_count($all, "\n") - substr_count($codeLine, "\n"));
    }
}


<?php

namespace Evaneos\Hector\Exchange;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Context\ContextRegistry;

class ExchangeFactory
{
    /** @var  ContextRegistry */
    private $contextRegistry;

    /** @var  ExchangeRegistry */
    private $exchangeRegistry;

    /**
     * ExchangeFactory constructor.
     *
     * @param ContextRegistry  $contextRegistry
     * @param ExchangeRegistry $exchangeRegistry
     */
    public function __construct(ContextRegistry $contextRegistry, ExchangeRegistry $exchangeRegistry)
    {
        $this->contextRegistry  = $contextRegistry;
        $this->exchangeRegistry = $exchangeRegistry;
    }

    /**
     * @param string  $name
     * @param Channel $channel
     *
     * @return Exchange
     */
    public function createNamed($name, Channel $channel)
    {
        $exchange = new Exchange($name, $channel, $this->contextRegistry->getExchangeContext($name));
        $this->exchangeRegistry->addExchange($exchange);

        return $exchange;
    }
}


<?php

namespace Evaneos\Hector\Queue;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Context\ContextRegistry;
use Evaneos\Hector\Exchange\Exchange;

class QueueFactory
{
    /**
     * @var ContextRegistry
     */
    private $contextRegistry;

    /**
     * @var QueueRegistry
     */
    private $registry;

    /**
     * QueueFactory constructor.
     *
     * @param ContextRegistry $contextRegistry
     * @param QueueRegistry   $registry
     */
    public function __construct(ContextRegistry $contextRegistry, QueueRegistry $registry)
    {
        $this->contextRegistry = $contextRegistry;
        $this->registry        = $registry;
    }

    /**
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     *
     * @return Queue
     */
    public function createNamed($name, Channel $channel, Exchange $exchange)
    {
        $queue = new Queue($name, $channel, $exchange, $this->contextRegistry->getQueueContext($name));
        $this->registry->addQueue($queue);

        return $queue;
    }
}


<?php

namespace Evaneos\Hector\Connection;

use Evaneos\Hector\Exception\NotFoundException;

class ConnectionRegistry
{
    /** @var array  */
    private $connections;

    public function __construct()
    {
        $this->connections = [];
    }

    /**
     * @param Connection $connection
     */
    public function addConnection(Connection $connection)
    {
        $this->connections[$connection->getName()] = $connection;
    }

    /**
     * @param $name
     *
     * @throws NotFoundException
     *
     * @return mixed
     */
    public function getConnection($name)
    {
        if (!isset($this->connections[$name])) {
            throw new NotFoundException(sprintf(
                'Connection %s not registered, available are [ %s ]'),
                $name,
                implode(', ', array_keys($this->connections))
            );
        }

        return $this->connections[$name];
    }
}


<?php

namespace Evaneos\Hector\Connection;

use Evaneos\Hector\Exception\HectorException;

class ConnectionFactory
{
    /**
     * @var ConnectionRegistry
     */
    private $registry;

    /** @var array */
    private $configs;

    /**
     * ConnectionFactory constructor.
     *
     * @param ConnectionRegistry $registry
     * @param array              $configs
     */
    public function __construct(ConnectionRegistry $registry, array $configs)
    {
        $this->registry = $registry;
        $this->configs  = $configs;
    }

    /**
     * @param $name
     *
     * @throws HectorException
     *
     * @return Connection
     */
    public function createNamed($name)
    {
        if (!isset($this->configs[$name])) {
            throw new HectorException(sprintf('Unable to load config for connection %s', $name));
        }

        $connection = new Connection(new \AMQPConnection($this->configs[$name]), $name);
        $this->registry->addConnection($connection);

        return $connection;
    }
}


<?php

namespace Evaneos\Hector\Publisher;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Channel\ChannelFactory;
use Evaneos\Hector\Connection\Connection;
use Evaneos\Hector\Connection\ConnectionRegistry;
use Evaneos\Hector\Exchange\ExchangeFactory;
use Evaneos\Hector\Exchange\ExchangeRegistry;
use Evaneos\Hector\Identity\Identity;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class PublisherFactory
{
    /** @var ConnectionRegistry  */
    private $connectionRegistry;

    /** @var ExchangeFactory  */
    private $exchangeFactory;

    /** @var ChannelFactory  */
    private $channelFactory;

    /** @var EventDispatcherInterface */
    private $eventDispatcher;

    /** @var  ExchangeRegistry */
    private $exchangeRegistry;

    /**
     * PublisherFactory constructor.
     *
     * @param ConnectionRegistry       $connectionRegistry
     * @param ExchangeFactory          $exchangeFactory
     * @param ChannelFactory           $channelFactory
     * @param EventDispatcherInterface $eventDispatcher
     * @param ExchangeRegistry         $exchangeRegistry
     */
    public function __construct(
        ConnectionRegistry $connectionRegistry,
        ExchangeFactory $exchangeFactory,
        ChannelFactory $channelFactory,
        EventDispatcherInterface $eventDispatcher = null,
        ExchangeRegistry $exchangeRegistry
    ) {
        $this->connectionRegistry = $connectionRegistry;
        $this->exchangeFactory    = $exchangeFactory;
        $this->channelFactory     = $channelFactory;
        $this->exchangeRegistry   = $exchangeRegistry;
    }

    /**
     * @param Connection $connection
     * @param string     $exchangeName
     * @param array      $options
     *
     * @return Publisher
     */
    public function createFromConnection(Connection $connection, $exchangeName, Channel $channel = null, array $options = [])
    {
        $identity = new Identity();

        if (null === $channel) {
            $channel = $this->channelFactory->createFromConnection($connection, $identity);
        }

        if (!$this->exchangeRegistry->hasExchange($exchangeName, $channel)) {
            $exchange = $this->exchangeFactory->createNamed($exchangeName, $channel);
        } else {
            $exchange = $this->exchangeRegistry->getExchange($exchangeName, $channel);
        }

        $publisher = new Publisher(
            $identity,
            $this->eventDispatcher,
            $connection,
            $channel,
            $exchange,
            $options
        );

        return $publisher;
    }

    /**
     * @param string $connectionName
     * @param string $exchangeName
     * @param array  $options
     *
     * @return Publisher
     */
    public function create($connectionName, $exchangeName, Channel $channel = null, array $options = [])
    {
        $connection = $this->connectionRegistry->getConnection($connectionName);

        return $this->createFromConnection($connection, $exchangeName, $channel, $options);
    }
}


<?php

namespace Evaneos\Hector\Exchange;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Exception\HectorException;

class Exchange
{
    /** @var Context */
    private $context;

    /** @var  \AMQPExchange */
    private $exchange;

    /** @var  bool */
    private $initialized;

    /** @var  Channel */
    private $channel;

    /** @var  string */
    private $name;

    /** @var string */
    private $fingerPrint;

    /**
     * Exchange constructor.
     *
     * @param string  $name
     * @param Channel $channel
     * @param Context $context
     */
    public function __construct($name, Channel $channel, Context $context)
    {
        $this->channel     = $channel;
        $this->name        = $name;
        $this->context     = $context;
        $this->initialized = false;
        $this->fingerPrint = sha1($this->channel->getIdentity() . $this->name);
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return $this->initialized;
    }

    /**
     * @return Channel
     */
    public function getChannel()
    {
        return $this->channel;
    }

    /**
     * @return Context
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * @param \AMQPExchange|null $exchange
     *
     * @throws HectorException
     */
    public function initialize(\AMQPExchange $exchange = null)
    {
        if (null == $exchange) {
            $exchange = new \AMQPExchange($this->channel->getWrappedChannel());
        }

        $this->exchange = $exchange;
        $this->exchange->setName($this->getName());
        $this->exchange->setType($this->context->getType());
        $this->exchange->setArguments($this->context->getArguments());
        $this->exchange->setFlags((int) $this->context->getFlags());
        $this->exchange->declareExchange();
        $this->initialized = true;
    }

    /**
     * @return string
     */
    public function getFingerPrint()
    {
        return $this->fingerPrint;
    }

    /**
     * @param string  $name
     * @param Channel $channel
     *
     * @return bool
     */
    public function isEqual($name, Channel $channel)
    {
        return sha1($channel->getIdentity() . $name) === $this->fingerPrint;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @throws HectorException
     *
     * @return \AMQPExchange
     */
    public function getWrappedExchange()
    {
        if (false === $this->isInitialized()) {
            throw new HectorException('You must initialize exchange before access it');
        }

        return $this->exchange;
    }
}


<?php

namespace Evaneos\Hector\Queue;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Exception\HectorException;
use Evaneos\Hector\Exchange\Exchange;

class Queue
{
    /** @var \AMQPQueue */
    private $queue;

    /** @var bool  */
    private $initialized;

    /** @var Context  */
    private $context;

    /** @var Channel  */
    private $channel;

    /** @var  Exchange */
    private $exchange;

    /** @var  string */
    private $name;

    /** @var  string */
    private $fingerPrint;

    /**
     * Queue constructor.
     *
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     * @param Context  $context
     *
     * @throws HectorException
     */
    public function __construct($name = '', Channel $channel, Exchange $exchange, Context $context)
    {
        if (!is_string($name)) {
            throw new HectorException(sprintf(
                'Queue name should be a string, %s given',
                gettype($name)
            ));
        }

        $this->name        = $name;
        $this->channel     = $channel;
        $this->context     = $context;
        $this->exchange    = $exchange;
        $this->initialized = false;
        $this->fingerPrint = $this->computeFingerPrint($name, $channel, $exchange);
    }

    /**
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     *
     * @return string
     */
    private function computeFingerPrint($name, Channel $channel, Exchange $exchange)
    {
        return sha1($channel->getIdentity() . $exchange->getName() . $name);
    }

    /**
     * @return Context
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * @return string
     */
    public function getFingerPrint()
    {
        return $this->fingerPrint;
    }

    /**
     * @throws HectorException
     *
     * @return \AMQPQueue
     */
    public function getWrappedQueue()
    {
        if (false === $this->isInitialized()) {
            throw new HectorException('You must initialize exchange before access it');
        }

        return $this->queue;
    }

    /**
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     *
     * @return string
     */
    public function isEqual($name, Channel $channel, Exchange $exchange)
    {
        return $this->computeFingerPrint($name, $channel, $exchange) === $this->fingerPrint;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return $this->initialized;
    }

    /**
     * @param \AMQPQueue|null $queue
     *
     * @throws HectorException
     */
    public function initialize(\AMQPQueue $queue = null)
    {
        if (true === $this->isInitialized()) {
            throw new HectorException('Queue already initialized');
        }

        if (null === $queue) {
            $queue = new \AMQPQueue($this->channel->getWrappedChannel());
        }

        $this->queue = $queue;
        $this->queue->setName($this->getName());
        $this->queue->bind($this->exchange->getName());
        $this->queue->setFlags($this->context->getFlags());
        $this->queue->setArguments($this->context->getArguments());
        $this->queue->declareQueue();
        $this->initialized = true;
    }
}


<?php

namespace Evaneos\Hector\Channel;

use Evaneos\Hector\Connection\Connection;
use Evaneos\Hector\Exception\HectorException;
use Evaneos\Hector\Identity\Identity;

class Channel
{
    /** @var Connection  */
    private $connection;

    /** @var Identity  */
    private $identity;

    /** @var \AMQPChannel  */
    private $channel;

    /** @var  bool */
    private $initialized;

    /**
     * Channel constructor.
     *
     * @param Connection    $connection
     * @param Identity|null $identity
     */
    public function __construct(Connection $connection, Identity $identity, \AMQPChannel $channel = null)
    {
        $this->identity   = $identity;
        $this->connection = $connection;

        if (null === $channel) {
            $this->initialized = false;
        } else {
            $this->connection->connect();
            $this->channel     = $channel;
            $this->initialized = true;
        }
    }

    public function initialize()
    {
        $this->connection->connect();
        $this->channel     = new \AMQPChannel($this->connection->getWrappedConnection());
        $this->initialized = true;
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return $this->initialized;
    }

    /**
     * @return bool
     */
    public function startTransaction()
    {
        if (!$this->isInitialized()) {
            $this->initialize();
        }

        return $this->channel->startTransaction();
    }

    /**
     * @return bool
     */
    public function commitTransaction()
    {
        if (!$this->isInitialized()) {
            $this->initialize();
        }

        return $this->channel->commitTransaction();
    }

    /**
     * @return bool
     */
    public function rollbackTransaction()
    {
        if (!$this->isInitialized()) {
            $this->initialize();
        }

        return $this->channel->rollbackTransaction();
    }

    /**
     * @param \Closure $closure
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function transaction(\Closure $closure)
    {
        if (!$this->isInitialized()) {
            $this->initialize();
        }

        try {
            $this->startTransaction();

            $result = $closure($this);

            if (!$result) {
                return $this->rollbackTransaction();
            }

            return $this->commitTransaction();
        } catch (\Exception $e) {
            $this->rollbackTransaction();
            throw new HectorException('Transaction failed', 255, $e);
        }
    }

    /**
     * @throws HectorException
     *
     * @return \AMQPChannel
     */
    public function getWrappedChannel()
    {
        if (false === $this->isInitialized()) {
            throw new HectorException('You must initialize exchange before access it');
        }

        return $this->channel;
    }

    /**
     * @return string
     */
    public function getIdentity()
    {
        return $this->identity->getIdentifier();
    }
}


<?php

namespace Evaneos\Hector\Exchange;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Exception\NotFoundException;

class ExchangeRegistry
{
    /**
     * @var Exchange[]
     */
    private $exchanges;

    public function __construct()
    {
        $this->exchanges = [];
    }

    /**
     * @param Exchange $exchange
     */
    public function addExchange(Exchange $exchange)
    {
        $this->exchanges[$exchange->getFingerPrint()] = $exchange;
    }

    /**
     * @param string  $name
     * @param Channel $channel
     *
     * @return bool
     */
    public function hasExchange($name, Channel $channel)
    {
        /*
         * @var string
         * @var Exchange
         */
        foreach ($this->exchanges as $exchange) {
            if (true == $exchange->isEqual($name, $channel)) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param string  $name
     * @param Channel $channel
     *
     * @throws \Exception
     *
     * @return Exchange
     */
    public function getExchange($name, Channel $channel)
    {
        /*
         * @var string
         * @var Exchange
         */
        foreach ($this->exchanges as $exchange) {
            if ($exchange->isEqual($name, $channel)) {
                return $exchange;
            }
        }

        throw new NotFoundException(sprintf(
            'Unable to find exchange %s for channel %s',
            $name,
            $channel->getIdentity()
        ));
    }
}


<?php

namespace Evaneos\Hector\Queue;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Exception\NotFoundException;
use Evaneos\Hector\Exchange\Exchange;

class QueueRegistry
{
    /**
     * @var Queue[]
     */
    private $queues;

    public function __construct()
    {
        $this->queues = [];
    }

    /**
     * @param Queue $queue
     */
    public function addQueue(Queue $queue)
    {
        $this->queues[$queue->getFingerPrint()] = $queue;
    }

    /**
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     *
     * @return bool
     */
    public function hasQueue($name, Channel $channel, Exchange $exchange)
    {
        foreach ($this->queues as $fingerPrint => $queue) {
            if ($queue->isEqual($name, $channel, $exchange)) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param string   $name
     * @param Channel  $channel
     * @param Exchange $exchange
     *
     * @throws \Exception
     *
     * @return Queue
     */
    public function getQueue($name, Channel $channel, Exchange $exchange)
    {
        /*
         * @var string
         * @var Queue
         */
        foreach ($this->queues as $fingerPrint => $queue) {
            if ($queue->isEqual($name, $channel, $exchange)) {
                return $queue;
            }
        }

        throw new NotFoundException(sprintf(
            'Unable to find queue %s for channel %s and exchange %s',
            $name,
            $channel->getIdentity(),
            $exchange->getName()
        ));
    }

    /**
     * @param $name
     *
     * @throws NotFoundException
     *
     * @return Context
     */
    public function getQueueContext($name)
    {
        /*
         * @var string
         * @var Queue
         */
        foreach ($this->queues as $fingerPrint => $queue) {
            if ($queue->getName() === $name) {
                return $queue->getContext();
            }
        }

        throw new NotFoundException(sprintf(
            'Unable to find queue %s',
            $name
        ));
    }
}


<?php

namespace Evaneos\Hector\Channel;

use Evaneos\Hector\Connection\Connection;
use Evaneos\Hector\Connection\ConnectionRegistry;
use Evaneos\Hector\Identity\Identity;

class ChannelFactory
{
    /**
     * @var ChannelRegistry
     */
    private $channelRegistry;

    /**
     * @var ConnectionRegistry
     */
    private $connectionRegistry;

    /**
     * ChannelFactory constructor.
     *
     * @param ConnectionRegistry $connectionRegistry
     * @param ChannelRegistry    $channelRegistry
     */
    public function __construct(ConnectionRegistry $connectionRegistry, ChannelRegistry $channelRegistry)
    {
        $this->channelRegistry    = $channelRegistry;
        $this->connectionRegistry = $connectionRegistry;
    }

    /**
     * @param Connection $connection
     * @param Identity   $identity
     *
     * @return Channel
     */
    public function createFromConnection(Connection $connection, Identity $identity)
    {
        $channel = new Channel($connection, $identity);

        $this->channelRegistry->addChannel($channel);

        return $channel;
    }

    /**
     * @param string   $connectionName
     * @param Identity $identity
     *
     * @return Channel
     */
    public function createFromConnectionName($connectionName, Identity $identity)
    {
        $connection = $this->connectionRegistry->getConnection($connectionName);

        return $this->createFromConnection($connection, $identity);
    }
}


<?php

namespace Evaneos\Hector\Consumer;

use Evaneos\Hector\Channel\ChannelFactory;
use Evaneos\Hector\Connection\Connection;
use Evaneos\Hector\Connection\ConnectionRegistry;
use Evaneos\Hector\Exchange\ExchangeFactory;
use Evaneos\Hector\Exchange\ExchangeRegistry;
use Evaneos\Hector\Identity\Identity;
use Evaneos\Hector\Queue\QueueFactory;
use Evaneos\Hector\Queue\QueueRegistry;

class ConsumerFactory
{
    /** @var ConnectionRegistry  */
    private $connectionRegistry;

    /** @var  QueueFactory */
    private $queueFactory;

    /** @var  ExchangeFactory */
    private $exchangeFactory;

    /** @var ChannelFactory */
    private $channelFactory;

    /** @var  ExchangeRegistry */
    private $exchangeRegistry;

    /** @var  QueueRegistry */
    private $queueRegistry;

    /**
     * ConsumerFactory constructor.
     *
     * @param ChannelFactory     $channelFactory
     * @param QueueFactory       $queueFactory
     * @param ExchangeFactory    $exchangeFactory
     * @param ConnectionRegistry $connectionRegistry
     * @param ExchangeRegistry   $exchangeRegistry
     * @param QueueRegistry      $queueRegistry
     */
    public function __construct(
        ChannelFactory $channelFactory,
        QueueFactory $queueFactory,
        ExchangeFactory $exchangeFactory,
        ConnectionRegistry $connectionRegistry,
        ExchangeRegistry $exchangeRegistry,
        QueueRegistry $queueRegistry
    ) {
        $this->channelFactory     = $channelFactory;
        $this->exchangeFactory    = $exchangeFactory;
        $this->queueFactory       = $queueFactory;
        $this->connectionRegistry = $connectionRegistry;
        $this->exchangeRegistry   = $exchangeRegistry;
        $this->queueRegistry      = $queueRegistry;
    }

    /**
     * @param Connection $connection
     * @param string     $exchangeName
     * @param string     $queueName
     *
     * @return Consumer
     */
    public function createFromConnection(Connection $connection, $exchangeName, $queueName)
    {
        $identity = new Identity();
        $channel  = $this->channelFactory->createFromConnection($connection, $identity);

        if (!$this->exchangeRegistry->hasExchange($exchangeName, $channel)) {
            $exchange = $this->exchangeFactory->createNamed($exchangeName, $channel);
        } else {
            $exchange = $this->exchangeRegistry->getExchange($exchangeName, $channel);
        }

        if (!$this->queueRegistry->hasQueue($queueName, $channel, $exchange)) {
            $queue = $this->queueFactory->createNamed($queueName, $channel, $exchange);
        } else {
            $queue = $this->queueRegistry->getQueue($queueName, $channel, $exchange);
        }

        $consumer = new Consumer($identity, $connection, $channel, $exchange, $queue);

        return $consumer;
    }

    /**
     * @param string $connectionName
     * @param string $exchangeName
     * @param string $queueName
     *
     * @return Consumer
     */
    public function create($connectionName, $exchangeName, $queueName)
    {
        $connection = $this->connectionRegistry->getConnection($connectionName);

        return $this->createFromConnection($connection, $exchangeName, $queueName);
    }
}


<?php

namespace Evaneos\Hector\Publisher;

use Evaneos\Hector\Channel\Channel;
use Evaneos\Hector\Connection\Connection;
use Evaneos\Hector\Events\FailedPublisherEvent;
use Evaneos\Hector\Events\PublisherEvent;
use Evaneos\Hector\Events\PublisherEvents;
use Evaneos\Hector\Events\SuccessPublisherEvent;
use Evaneos\Hector\Exchange\Exchange;
use Evaneos\Hector\Identity\Identity;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class Publisher
{
    /** @var Connection  */
    private $connection;

    /** @var EventDispatcherInterface  */
    private $eventDispatcher;

    /** @var Channel  */
    private $channel;

    /** @var Exchange  */
    private $exchange;

    /** @var Identity  */
    private $identity;

    /** @var string  */
    private $routingKeyPrefix;

    /** @var  bool */
    private $initialized;

    /**
     * Publisher constructor.
     *
     * @param Identity                 $identity
     * @param EventDispatcherInterface $eventDispatcher
     * @param Connection               $connection
     * @param Channel                  $channel
     * @param Exchange                 $exchange
     * @param array                    $otpions
     */
    public function __construct(
        Identity $identity,
        EventDispatcherInterface $eventDispatcher = null,
        Connection $connection,
        Channel $channel,
        Exchange $exchange,
        array $options = []
    ) {
        $this->connection      = $connection;
        $this->eventDispatcher = $eventDispatcher;
        $this->identity        = $identity;
        $this->channel         = $channel;
        $this->exchange        = $exchange;
        $this->initialized     = false;

        if (isset($options['routing_key_prefix'])) {
            $this->routingKeyPrefix = $options['routing_key_prefix'];
        }
    }

    public function initialize()
    {
        $this->connection->connect();

        if (false === $this->channel->isInitialized()) {
            $this->channel->initialize();
        }

        if (false === $this->exchange->isInitialized()) {
            $this->exchange->initialize();
        }

        $this->initialized = true;
    }

    /**
     * @return Connection
     */
    public function getConnection()
    {
        return $this->connection;
    }

    /**
     * @return Exchange
     */
    public function getExchange()
    {
        return $this->exchange;
    }

    /**
     * @return Channel
     */
    public function getChannel()
    {
        return $this->channel;
    }

    /**
     * @return string
     */
    public function getIdentity()
    {
        return $this->identity->getIdentifier();
    }

    /**
     * @return bool
     */
    public function startTransaction()
    {
        return $this->channel->startTransaction();
    }

    /**
     * @return bool
     */
    public function commitTransaction()
    {
        return $this->channel->commitTransaction();
    }

    /**
     * @return bool
     */
    public function rollbackTransaction()
    {
        return $this->channel->rollbackTransaction();
    }

    /**
     * @param \Closure $closure
     *
     * @throws \Evaneos\Hector\Exception\HectorException
     *
     * @return bool
     */
    public function transaction(\Closure $closure)
    {
        return $this->channel->transaction($closure);
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return $this->initialized;
    }

    /**
     * @param string $message
     * @param null   $routingKeyArgument::type(Publisher::class)
     * @param int    $flags
     * @param array  $attributes
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function publish($message, $routingKey = null, $flags = AMQP_NOPARAM, array $attributes = [])
    {
        $hasEventDispatcher = null !== $this->eventDispatcher;

        if(!empty($this->routingKeyPrefix)){
            $routingKey = $this->routingKeyPrefix . $routingKey;
        }

        if (!$this->isInitialized()) {
            $this->initialize();
        }

        if (true === $hasEventDispatcher) {
            $event = new PublisherEvent(
                $message,
                $routingKey,
                $flags,
                $attributes,
                $this->exchange
            );
        }

        try {
            if (true === $hasEventDispatcher) {
                $this->eventDispatcher->dispatch(PublisherEvents::PRE_PUBLISH, $event);

                $result = $this->exchange->getWrappedExchange()->publish(
                    $event->getMessage(),
                    $event->getRoutingKey(),
                    $event->getFlags(),
                    $event->getAttributes()
                );
            } else {
                $result = $this->exchange->getWrappedExchange()->publish(
                    $message,
                    $routingKey,
                    $flags,
                    $attributes
                );
            }

            if (!$result) {
                if (true === $hasEventDispatcher) {
                    $this->eventDispatcher->dispatch(PublisherEvents::FAIL_PUBLISH, new FailedPublisherEvent($event, null, $this));
                }
            } else {
                if (true === $hasEventDispatcher) {
                    $this->eventDispatcher->dispatch(PublisherEvents::SUCCESS_PUBLISH, new SuccessPublisherEvent($event));
                }
            }
        } catch (\Exception $e) {
            if (true === $hasEventDispatcher) {
                $this->eventDispatcher->dispatch(PublisherEvents::FAIL_PUBLISH, new FailedPublisherEvent($event, $e, $this));
            }

            throw $e;
        }

        return $result;
    }
}


<?php
namespace Ferdirn\Countries;

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class MigrationCommand extends Command {

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'countries:migration';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Creates a migration of countries table';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
        $app = app();
        $app['view']->addNamespace('countries',substr(__DIR__,0,-8).'views');
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {
        $this->line('');
        $this->info('Welcome to package ferdirn/laravel-id-countries');
        $this->line('');
        $this->info('The migration file will create a table countries and a seeder for the countries data');

        $this->line('');

        if ( $this->confirm("Create migration file? [Yes|no]") )
        {
            $this->line('');

            $this->info( "Creating migration and seed file..." );
            if( $this->createMigration( 'countries' ) )
            {
                $this->line('');

                $this->call('dump-autoload', array());

                $this->line('');

                $this->info( "Migration successfully created!" );
            }
            else{
                $this->error(
                    "Error! Failed to create migration.\n Check the write permissions".
                    " within the app/database/migrations directory."
                );
            }

            $this->line('');
        }
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return array();
    }

    /**
     * Create the migration
     *
     * @param  string $name
     * @return bool
     */
    protected function createMigration()
    {
        //Create the migration
        $app = app();
        $migrationFiles = array(
            $this->laravel->path."/database/migrations/*_create_countries_table.php" => 'countries::generators.migration',
        );

        $seconds = 0;

        foreach ($migrationFiles as $migrationFile => $outputFile) {
            if (sizeof(glob($migrationFile)) == 0) {
                $migrationFile = str_replace('*', date('Y_m_d_His', strtotime('+' . $seconds . ' seconds')), $migrationFile);

                $fs = fopen($migrationFile, 'x');
                if ($fs) {
                    $output = "<?php\n\n" .$app['view']->make($outputFile)->with('table', 'countries')->render();

                    fwrite($fs, $output);
                    fclose($fs);
                } else {
                    return false;
                }

                $seconds++;
            }
        }

        //Create the seeder
        $seeder_file = $this->laravel->path."/database/seeds/CountriesSeeder.php";
        $output = "<?php\n\n" .$app['view']->make('countries::generators.seeder')->render();

        if (!file_exists( $seeder_file )) {
            $fs = fopen($seeder_file, 'x');
            if ($fs) {
                fwrite($fs, $output);
                fclose($fs);
            } else {
                return false;
            }
        }

        return true;
    }

}


<?php
/**
 * This file is part of the EkiPayumBundle package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Action;

use Payum\Be2Bill\Api;
use Payum\Core\Action\PaymentAwareAction;
use Payum\Core\ApiAwareInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Exception\UnsupportedApiException;
use Payum\Core\Request\Capture;
use Payum\Core\Request\GetHttpRequest;
use Payum\Core\Reply\HttpPostRedirect;

class CaptureOnsiteAction extends PaymentAwareAction implements ApiAwareInterface
{
    /**
     * @var Api
     */
    protected $api;

    /**
     * {@inheritDoc}
     */
    public function setApi($api)
    {
        if (false === $api instanceof Api) {
            throw new UnsupportedApiException('Not supported.');
        }

        $this->api = $api;
    }

    /**
     * {@inheritDoc}
     *
     * @param Capture $request
     */
    public function execute($request)
    {
        /** @var $request Capture */
        RequestNotSupportedException::assertSupports($this, $request);

        $model = ArrayObject::ensureArrayObject($request->getModel());

        if ( null !== $model['token'] )
			return;

        if (false == $model['return_url'] && $request->getToken()) {
            $model['return_url'] = $request->getToken()->getTargetUrl();
        }

        if (false == $model['cancel_url'] && $request->getToken()) {
            $model['cancel_url'] = $request->getToken()->getTargetUrl();
        }

        $this->payment->execute(new SetExpressCheckout($model));

        if ( $model['error_code'] == '00' )
		{
			if ( !isset($model['checkout_url']) )
			{
				throw new \LogicException('Payment gateway Nganluong is not returned "checkout_url"');
			}

            throw new HttpRedirect(	$model['checkout_url'] );
		}
        else
		{
            return;   // failed
        }
    }

    /**
     * {@inheritDoc}
     */
    public function supports($request)
    {
        return
            $request instanceof Capture &&
            $request->getModel() instanceof \ArrayAccess
        ;
    }
}


<?php

namespace FondOfSpryker\Yves\AvailabilityAlert;

use FondOfSpryker\Yves\AvailabilityAlert\Form\DataProvider\SubscriptionFormDataProvider;
use FondOfSpryker\Yves\AvailabilityAlert\Form\SubscriptionForm;
use Spryker\Shared\Application\ApplicationConstants;
use Spryker\Yves\Kernel\AbstractFactory;

class AvailabilityAlertFactory extends AbstractFactory
{
    /**
     * @param int $idProductAbstract
     *
     * @return \Symfony\Component\Form\FormInterface
     */
    public function createSubscriptionForm($idProductAbstract)
    {
        $dataProvider = $this->createSubscriptionFormDataProvider();

        $form = $this->getFormFactory()->create(
            $this->getSubscriptionFormType(),
            $dataProvider->getData($idProductAbstract),
            $dataProvider->getOptions()
        );

        return $form;
    }

    /**
     * @return \FondOfSpryker\Yves\AvailabilityAlert\Form\DataProvider\SubscriptionFormDataProvider
     */
    public function createSubscriptionFormDataProvider()
    {
        return new SubscriptionFormDataProvider();
    }

    /**
     * @return \Symfony\Component\Form\FormFactory
     */
    protected function getFormFactory()
    {
        return $this->getProvidedDependency(ApplicationConstants::FORM_FACTORY);
    }

    /**
     * @return string
     */
    protected function getSubscriptionFormType()
    {
        return SubscriptionForm::class;
    }

    /**
     * @return \FondOfSpryker\Client\AvailabilityAlert\AvailabilityAlertClientInterface
     */
    public function getAvailabilityAlertClient()
    {
        return $this->getProvidedDependency(AvailabilityAlertDependencyProvider::CLIENT_AVAILABILITY_ALERT);
    }
}


<?php

namespace Eki\Payum\Nganluong\Bridge\Buzz;

use Buzz\Message\Response as BaseResponse;
use Payum\Core\Exception\LogicException;

class Response extends BaseResponse
{
    /**
     * @throws \Payum\Core\Exception\LogicException
     *
     * @return array
     */
    public function toArray()
    {
		$content = $this->getContent();

        if (count($content) < 1) {
            throw new LogicException("Response content is not valid response: \n\n{$this->getContent()}");
        }

		$response = array();

		$xml_result = str_replace('&','&', (string)$content);
		$xml_result = $content;
		$xmlElement  = simplexml_load_string($xml_result);

		foreach($xmlElement->attributes() as $key => $value)
		{
			$response[$key] = is_object($value) ? $value->__toString() : $value;
		}

        return $response;
    }
}


<?php
/**
 * This file is part of the EkiSyliusPayumBundle package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Bridge\Sylius;

use Doctrine\Common\Persistence\ObjectManager;
use Payum\Core\Bridge\Symfony\Reply\HttpResponse;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetHttpRequest;
use Payum\Core\Request\Notify;
use SM\Factory\FactoryInterface;
use Sylius\Bundle\PayumBundle\Payum\Action\AbstractPaymentStateAwareAction;
use Sylius\Bundle\PayumBundle\Payum\Request\GetStatus;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class NotifyAction extends AbstractPaymentStateAwareAction
{
    /**
     * @var RepositoryInterface
     */
    protected $paymentRepository;

    /**
     * @var EventDispatcherInterface
     */
    protected $eventDispatcher;

    /**
     * @var ObjectManager
     */
    protected $objectManager;

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

    public function __construct(
        RepositoryInterface $paymentRepository,
        EventDispatcherInterface $eventDispatcher,
        ObjectManager $objectManager,
        FactoryInterface $factory,
        $identifier
    ) {
        parent::__construct($factory);

        $this->paymentRepository = $paymentRepository;
        $this->eventDispatcher   = $eventDispatcher;
        $this->objectManager     = $objectManager;
        $this->identifier        = $identifier;
    }

    /**
     * {@inheritDoc}
     *
     * @param $request Notify
     */
    public function execute($request)
    {
        if (!$this->supports($request)) {
            throw RequestNotSupportedException::createActionNotSupported($this, $request);
        }

        $this->payment->execute($httpRequest = new GetHttpRequest());
        $details = $httpRequest->query;

        if (empty($details['order_code'])) {
            throw new BadRequestHttpException('Order code cannot be guessed');
        }

        $payment = $this->paymentRepository->findOneBy(array($this->identifier => $details['order_code']));

        if (null === $payment) {
            throw new BadRequestHttpException('Paymenet cannot be retrieved.');
        }

        if ((int) $details['total_amount'] !== $payment->getAmount()) {
            throw new BadRequestHttpException('Request amount cannot be verified against payment amount.');
        }

        // Actually update payment details
        $details = array_merge($payment->getDetails(), $details);
        $payment->setDetails($details);

        $status = new GetStatus($payment);
        $this->payment->execute($status);

        $nextState = $status->getValue();

        $this->updatePaymentState($payment, $nextState);

        $this->objectManager->flush();

        throw new HttpResponse(new Response('OK', 200));
    }

    /**
     * {@inheritDoc}
     */
    public function supports($request)
    {
        return $request instanceof Notify;
    }
}


<?php
//
// +---------------------------------------------------------------------+
// | CODE INC. SOURCE CODE                                               |
// +---------------------------------------------------------------------+
// | Copyright (c) 2017 - Code Inc. SAS - All Rights Reserved.           |
// | Visit https://www.codeinc.fr for more information about licensing.  |
// +---------------------------------------------------------------------+
// | NOTICE:  All information contained herein is, and remains the       |
// | property of Code Inc. SAS. The intellectual and technical concepts  |
// | contained herein are proprietary to Code Inc. SAS are protected by  |
// | trade secret or copyright law. Dissemination of this information or |
// | reproduction of this material  is strictly forbidden unless prior   |
// | written permission is obtained from Code Inc. SAS.                  |
// +---------------------------------------------------------------------+
//
// Author:   Joan Fabrégat <joan@codeinc.fr>
// Date:     13/03/2018
// Time:     11:31
// Project:  SessionManager
//
declare(strict_types = 1);
namespace CodeInc\SessionManager;
use CodeInc\SessionManager\Exceptions\SessionReservedOffsetException;
use Psr\Http\Message\ServerRequestInterface;

/**
 * Class SessionDataHolder
 *
 * @package CodeInc\Session
 * @author Joan Fabrégat <joan@codeinc.fr>
 */
class SessionDataHolder implements \IteratorAggregate, \ArrayAccess
{
    // session data headers
    public const HEADER_IP = "__clientIp";
    public const HEADER_LAST_REQ = "__lastRequest";
    public const HEADER_CLEAN_UP = "__cleanUp";
    private const ALL_HEADERS = [
        self::HEADER_IP,
        self::HEADER_LAST_REQ,
        self::HEADER_CLEAN_UP
    ];

    /**
     * Parent session manager.
     *
     * @var SessionManager
     */
    private $sessionManager;

    /**
     * Session ID
     *
     * @var string
     */
    protected $id;

    /**
     * Session data
     *
     * @var array
     */
    protected $data;

    /**
     * Session constructor.
     *
     * @param SessionManager $sessionManager
     * @param string $id
     * @param array|null $data
     * @throws \Exception
     */
    public function __construct(SessionManager $sessionManager, string $id,
        ?array $data = null)
    {
        $this->sessionManager = $sessionManager;
        $this->id = $id;
        $this->data = $data ?? [];
    }

    /**
     * @param SessionManager $sessionManager
     * @param ServerRequestInterface $request
     * @return SessionDataHolder
     * @throws \Exception
     */
    public static function factory(SessionManager $sessionManager,
        ServerRequestInterface $request):SessionDataHolder
    {
        return new SessionDataHolder($sessionManager, bin2hex(random_bytes(32)), [
            self::HEADER_IP => $request->getServerParams()["REMOTE_ADDR"] ?? null,
            self::HEADER_LAST_REQ => time()
        ]);
    }

    /**
     * Returns the session id.
     *
     * @return string
     */
    public function getId():string
    {
        return $this->id;
    }

    /**
     * Returns the session data.
     *
     * @return array
     */
    public function getData():array
    {
        return $this->data;
    }

    /**
     * Unsets all session data.
     */
    public function unsetData():void
    {
        foreach (array_keys($this->data) as $var) {
            if (!in_array($var, self::ALL_HEADERS)) {
                unset($this->data[$var]);
            }
        }
    }

    /**
     * Return the timestmap of the last request.
     *
     * @return int|null
     */
    public function getLastRequestTime():?int
    {
        return $this->data[self::HEADER_LAST_REQ];
    }

    /**
     * Updates the last request timestamp.
     */
    public function updateLastRequestTime():void
    {
        $this->data[self::HEADER_LAST_REQ] = time();
    }

    /**
     * Returns the IP used to start the current session.
     *
     * @return null|string
     */
    public function getClientIp():?string
    {
        return $this->data[self::HEADER_IP] ?? null;
    }

    /**
     * @inheritdoc
     * @return \ArrayIterator
     */
    public function getIterator():\ArrayIterator
    {
        return new \ArrayIterator($this->data);
    }

    /**
     * @inheritdoc
     * @throws SessionReservedOffsetException
     */
    public function offsetSet($offset, $value):void
    {
        if (in_array($offset, self::ALL_HEADERS)) {
            throw new SessionReservedOffsetException($offset, $this);
        }
        $this->data[$offset] = $value;
    }

    /**
     * @inheritdoc
     * @param mixed $offset
     * @return mixed|null
     */
    public function offsetGet($offset)
    {
        return $this->data[$offset] ?? null;
    }

    /**
     * @inheritdoc
     * @param mixed $offset
     * @return bool
     */
    public function offsetExists($offset):bool
    {
        return isset($this->data[$offset]);
    }

    /**
     * @inheritdoc
     * @throws SessionReservedOffsetException
     */
    public function offsetUnset($offset):void
    {
        if (in_array($offset, self::ALL_HEADERS)) {
            throw new SessionReservedOffsetException($offset, $this);
        }
        unset($this->data[$offset]);
    }
}


<?php
/**
 * This file is part of the EkiPayumNganluong package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Action;

//use Eki\Payum\Nganluong\Api;
use Eki\Payum\Nganluong\Api\State\StateInterface;
use Eki\Payum\Nganluong\Api\Errors;
use Eki\Payum\Nganluong\Api\TransactionStatus;
use Eki\Payum\Nganluong\Request\Api\GetTransactionDetails;

use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Request\Sync;
use Payum\Core\Action\PaymentAwareAction;
use Payum\Core\Exception\RequestNotSupportedException;

class SyncAction extends PaymentAwareAction
{
    /**
     * {@inheritDoc}
     */
    public function execute($request)
    {
        /** @var $request Sync */
        RequestNotSupportedException::assertSupports($this, $request);

        $model = ArrayObject::ensureArrayObject($request->getModel());

        if (false == $model['token']) {
            return;
        }

        $copiedModel = new ArrayObject(array(
            'token' => $model['token'],
        ));

        $this->payment->execute(new GetTransactionDetails($copiedModel));
		if ( $copiedModel['error_code'] === Errors::ERRCODE_NO_ERROR )
		{
			if ( $copiedModel['transaction_status'] )
			{
				if ( $model['status'] != null )
				{
					if ( $copiedModel['transaction_status'] === TransactionStatus::PAID_WAITING_FOR_PROCESS )
					{
						$model['status'] = StateInterface::STATE_NOTIFIED;
					}
					else if ( $copiedModel['transaction_status'] === TransactionStatus::PAID )
					{
						$model['status'] = StateInterface::STATE_CONFIRMED;
					}
				}
				else
				{
					throw new \RuntimeException('Unknown error....');
				}
			}
			else
			{
				throw new \RuntimeException('Unknown error.');
			}
		}
    }

    /**
     * {@inheritDoc}
     */
    public function supports($request)
    {
        if (false == $request instanceof Sync) {
            return false;
        }

        $model = $request->getModel();
        if (false == $model instanceof \ArrayAccess) {
            return false;
        }
    }
}


<?php
/**
 * This file is part of the EkiPayumNganluong package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Bridge\Symfony;

use Eki\Payum\Nganluong\Bridge\Symfony\BasePaymentFactory;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;

class NganluongPaymentFactory extends BasePaymentFactory
{
    /**
     * {@inheritdoc}
     */
    public function create(ContainerBuilder $container, $contextName, array $config)
    {
        if (false == class_exists('\Eki\Payum\Nganluong\PaymentFactory')) {
            throw new RuntimeException('Cannot find nganluong payment factory class');
        }

        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/Resources/config'));
        $loader->load('nganluong.xml');

        return parent::create($container, $contextName, $config);
    }

    public function getName()
    {
        return 'nganluong';
    }
}


<?php
/**
 * This file is part of the EkiPayum package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong;

use Eki\Payum\Nganluong\Api;

use Eki\Payum\Nganluong\Action\CaptureAction;
use Eki\Payum\Nganluong\Action\FillOrderDetailsAction;
use Eki\Payum\Nganluong\Action\StatusAction;

use Eki\Payum\Nganluong\Action\Api\SetExpressCheckoutAction;
use Eki\Payum\Nganluong\Action\Api\GetTransactionDetailsAction;

use Payum\Core\Action\ExecuteSameRequestWithModelDetailsAction;
use Payum\Core\Action\CaptureOrderAction;
use Payum\Core\Action\GetHttpRequestAction;
use Payum\Core\Action\NotifyOrderAction;
use Payum\Core\Payment;
use Payum\Core\Extension\EndlessCycleDetectorExtension;

abstract class PaymentFactory
{
    /**
     * @param Api $api
     *
     * @return \Payum\Core\Payment
     */
    public static function create(Api $api)
    {
        $payment = new Payment;

        $payment->addApi($api);

        $payment->addExtension(new EndlessCycleDetectorExtension);

        $payment->addAction(new SetExpressCheckoutAction);
        $payment->addAction(new GetTransactionDetailsAction);

        $payment->addAction(new CaptureAction);
        $payment->addAction(new CaptureOrderAction);
        $payment->addAction(new NotifyOrderAction);
        $payment->addAction(new FillOrderDetailsAction);
        $payment->addAction(new StatusAction);
        $payment->addAction(new ExecuteSameRequestWithModelDetailsAction);
        $payment->addAction(new GetHttpRequestAction);

        return $payment;
    }

    /**
     */
    private  function __construct()
    {
    }
}


<?php

namespace FondOfSpryker\Zed\AvailabilityAlert\Business\Model;

use FondOfSpryker\Zed\AvailabilityAlert\Communication\Plugin\Mail\AvailabilityAlertMailTypePlugin;
use FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToMailInterface;
use FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToProductInterface;
use Generated\Shared\Transfer\AvailabilityAlertSubscriptionTransfer;
use Generated\Shared\Transfer\LocaleTransfer;
use Generated\Shared\Transfer\MailTransfer;
use Generated\Shared\Transfer\ProductAbstractTransfer;
use Orm\Zed\AvailabilityAlert\Persistence\FosAvailabilityAlertSubscription;

class MailHandler
{
    /**
     * @param \FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToMailInterface $mailFacade
     * @param \FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToProductInterface $productFacade
     */
    public function __construct(AvailabilityAlertToMailInterface $mailFacade, AvailabilityAlertToProductInterface $productFacade)
    {
        $this->mailFacade = $mailFacade;
        $this->productFacade = $productFacade;
    }

    /**
     * @param \Orm\Zed\AvailabilityAlert\Persistence\FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription
     *
     * @return void
     */
    public function sendAvailabilityAlertMail(FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription)
    {
        $availabilityAlertSubscriptionTransfer = $this->getAvailabilityAlertSubscriptionTransfer($fosAvailabilityAlertSubscription);
        $localeTransfer = $this->getLocaleTransfer($fosAvailabilityAlertSubscription);
        $productAbstractTransfer = $this->getProductAbstractTransfer($fosAvailabilityAlertSubscription);
        $productUrlTransfer = $this->productFacade->getProductUrl($productAbstractTransfer);
        $priceProductTransfer = $productAbstractTransfer->getPrices();

        /** @var \Generated\Shared\Transfer\LocalizedUrlTransfer $localizedUrlTransfer */
        foreach ($productUrlTransfer->getUrls() as $localizedUrlTransfer) {
            if ($localizedUrlTransfer->getLocale()->getIdLocale() == $localeTransfer->getIdLocale()) {
                $currentLocaleProductUrlTransfer = $localizedUrlTransfer;

                break;
            }
        }

        /** @var \Generated\Shared\Transfer\PriceProductTransfer $transfer */
        foreach ($priceProductTransfer as $transfer) {
            /** @var \Generated\Shared\Transfer\MoneyValueTransfer $moneyValueTransfer */
            $moneyValueTransfer = $transfer->getMoneyValue();

            break;
        }

        $mailTransfer = new MailTransfer();
        $mailTransfer->setAvailabilityAlertSubscription($availabilityAlertSubscriptionTransfer);
        $mailTransfer->setLocale($localeTransfer);
        $mailTransfer->setProductAbstract($productAbstractTransfer);
        $mailTransfer->setType(AvailabilityAlertMailTypePlugin::MAIL_TYPE);
        $mailTransfer->setLocalizedUrl($currentLocaleProductUrlTransfer);
        $mailTransfer->setMoneyValue($moneyValueTransfer);

        $this->mailFacade->handleMail($mailTransfer);
    }

    /**
     * @param \Orm\Zed\AvailabilityAlert\Persistence\FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription
     *
     * @return \Generated\Shared\Transfer\AvailabilityAlertSubscriptionTransfer
     */
    protected function getAvailabilityAlertSubscriptionTransfer(
        FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription
    ) {
        $availabilityAlertSubscriptionTransfer = new AvailabilityAlertSubscriptionTransfer();

        $availabilityAlertSubscriptionTransfer->fromArray($fosAvailabilityAlertSubscription->toArray(), true);

        return $availabilityAlertSubscriptionTransfer;
    }

    /**
     * @param \Orm\Zed\AvailabilityAlert\Persistence\FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription
     *
     * @return \Generated\Shared\Transfer\LocaleTransfer
     */
    protected function getLocaleTransfer(FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription)
    {
        $spyLocale = $fosAvailabilityAlertSubscription->getSpyLocale();

        $localeTransfer = new LocaleTransfer();

        $localeTransfer->fromArray($spyLocale->toArray(), true);

        return $localeTransfer;
    }

    /**
     * @param \Orm\Zed\AvailabilityAlert\Persistence\FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription
     *
     * @return \Generated\Shared\Transfer\ProductAbstractTransfer
     */
    protected function getProductAbstractTransfer(FosAvailabilityAlertSubscription $fosAvailabilityAlertSubscription): ProductAbstractTransfer
    {
        $spyProductAbstract = $fosAvailabilityAlertSubscription->getSpyProductAbstract();

        return $this->productFacade->findProductAbstractById($spyProductAbstract->getPrimaryKey());
    }
}


<?php
/**
 * This file is part of the EkiPayumNganluong package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Request;

class Log
{
	const DEFAULT_PREFIX = 'Nganluong';

	/**
	*
	* @var string
	*
	*/
	private $msg;

	/**
	*
	* @var string
	*
	*/
	private $type;

	/**
	*
	* @var string
	*
	*/
	private $prefix;

	/**
	*
	* @var object
	*
	*/
	private $context;

	/**
	*
	* @param string $msg
	* @param string $type
	* @param object $context Contex on which log shows
	* @param string $prefix
	*
	*/
	public function __construct( $msg, $context = null, $prefix = self::DEFAULT_PREFIX, $type = 'debug' )
	{
		$this->msg = $msg;
		$this->prefix = $prefix;
		$this->context = $context;
		$this->type = $type;
	}

	/**
	* Get type of message (info, debug, ....)
	*
	*/
	public function getType()
	{
		return $this->type;
	}

	/**
	* Get log message
	*
	*/
	public function getMessage()
	{
		return '['.$this->prefix.( $this->context === null ? '' : (' - '.get_class($this->context)) ).'] ' . $this->msg;
	}
}


<?php
/**
 * This file is part of the EkiPayumBundle package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Action;

use Payum\Core\Action\ActionInterface;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\FillOrderDetails;
use Payum\Core\Security\GenericTokenFactoryInterface;

class FillOrderDetailsAction implements ActionInterface
{
    /**
     * @var GenericTokenFactoryInterface
     */
    protected $tokenFactory;

    /**
     * @param GenericTokenFactoryInterface $tokenFactory
     */
    public function __construct(GenericTokenFactoryInterface $tokenFactory = null)
    {
        $this->tokenFactory = $tokenFactory;
    }

    /**
     * {@inheritDoc}
     *
     * @param FillOrderDetails $request
     */
    public function execute($request)
    {
        RequestNotSupportedException::assertSupports($this, $request);

        $order = $request->getOrder();
        $divisor = pow(10, $order->getCurrencyDigitsAfterDecimalPoint());

        $details = $order->getDetails();

        $details['order_code'] = $order->getNumber();
        $details['total_amount'] = $order->getTotalAmount() / $divisor;
        $details['cur_code'] = $order->getCurrencyCode();
		$details['order_description'] = $order->getDescription();

		$details['buyer_email'] = $order->getClientEmail();

		// need more, fill later....

/*
R	order_code
R	total_amount
R   cur_code

payment_method
payment_type

R order_description
tax_amount
discount_amount
fee_shipping
R return_url
R cancel_url
time_limit
buyer_fullname
R buyer_email
buyer_mobile
buyer_address
affiliate_code
total_item
item_name1
item_quantity1
item_amount1
item_url1
*/
        $order->setDetails($details);
    }

    /**
     * {@inheritDoc}
     */
    public function supports($request)
    {
        return $request instanceof FillOrderDetails;
    }
}


<?php

namespace FondOfSpryker\Yves\AvailabilityAlert;

;

use Spryker\Yves\Kernel\AbstractBundleDependencyProvider;
use Spryker\Yves\Kernel\Container;

class AvailabilityAlertDependencyProvider extends AbstractBundleDependencyProvider
{
    const CLIENT_AVAILABILITY_ALERT = 'CLIENT_AVAILABILITY_ALERT';

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    public function provideDependencies(Container $container)
    {
        $container = parent::provideDependencies($container);

        $container = $this->addAvailabilityAlertClient($container);

        return $container;
    }

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function addAvailabilityAlertClient(Container $container)
    {
        $container[static::CLIENT_AVAILABILITY_ALERT] = function (Container $container) {
            return $container->getLocator()->availabilityAlert()->client();
        };

        return $container;
    }
}


<?php

namespace FondOfSpryker\Zed\AvailabilityAlert\Communication\Controller\Mapper;

use FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToLocaleInterface;
use FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToStoreInterface;
use Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer;
use Generated\Shared\Transfer\AvailabilityAlertSubscriptionTransfer;

class AvailabilityAlertSubscriptionSubmitMapper implements AvailabilityAlertSubscriptionSubmitMapperInterface
{
    /**
     * @var \FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToLocaleInterface
     */
    protected $localeFacade;

    /**
     * @var \FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToStoreInterface
     */
    protected $storeFacade;

    /**
     * @param \FondOfSpryker\Zed\AvailabilityAlert\Dependency\Facade\AvailabilityAlertToLocaleInterface $localeFacade
     */
    public function __construct(
        AvailabilityAlertToLocaleInterface $localeFacade,
        AvailabilityAlertToStoreInterface $storeFacade
    ) {
        $this->localeFacade = $localeFacade;
        $this->storeFacade = $storeFacade;
    }

    /**
     * @param \Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
     *
     * @return \Generated\Shared\Transfer\AvailabilityAlertSubscriptionTransfer
     */
    public function mapRequestTransfer(
        AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
    ) {

        $this->assertAvailabilityAlertSubscriptionRequestTransfer($availabilityAlertSubscriptionRequestTransfer);

        $availabilityAlertSubscriptionTransfer = new AvailabilityAlertSubscriptionTransfer();

        $availabilityAlertSubscriptionTransfer
            ->fromArray($availabilityAlertSubscriptionRequestTransfer->modifiedToArray(), true)
            ->setFkProductAbstract($availabilityAlertSubscriptionRequestTransfer->getIdProductAbstract())
            ->setFkLocale($this->getIdLocale($availabilityAlertSubscriptionRequestTransfer))
            ->setFkStore($this->getIdStore($availabilityAlertSubscriptionRequestTransfer));

        return $availabilityAlertSubscriptionTransfer;
    }

    /**
     * @param \Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
     *
     * @return string
     */
    protected function getIdLocale(
        AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
    ) {
        return $this->localeFacade->getLocale($availabilityAlertSubscriptionRequestTransfer->getLocaleName())->getIdLocale();
    }

    /**
     * @param \Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
     *
     * @return string
     */
    protected function getIdStore(
        AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
    ) {

        return $this->storeFacade->getStore($availabilityAlertSubscriptionRequestTransfer->getStore())->getIdStore();
    }

    /**
     * @param \Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
     *
     * @return void
     */
    protected function assertAvailabilityAlertSubscriptionRequestTransfer(
        AvailabilityAlertSubscriptionRequestTransfer $availabilityAlertSubscriptionRequestTransfer
    ) {
        $availabilityAlertSubscriptionRequestTransfer
            ->requireIdProductAbstract()
            ->requireEmail()
            ->requireLocaleName();
    }
}


<?php
//
// +---------------------------------------------------------------------+
// | CODE INC. SOURCE CODE                                               |
// +---------------------------------------------------------------------+
// | Copyright (c) 2017 - Code Inc. SAS - All Rights Reserved.           |
// | Visit https://www.codeinc.fr for more information about licensing.  |
// +---------------------------------------------------------------------+
// | NOTICE:  All information contained herein is, and remains the       |
// | property of Code Inc. SAS. The intellectual and technical concepts  |
// | contained herein are proprietary to Code Inc. SAS are protected by  |
// | trade secret or copyright law. Dissemination of this information or |
// | reproduction of this material  is strictly forbidden unless prior   |
// | written permission is obtained from Code Inc. SAS.                  |
// +---------------------------------------------------------------------+
//
// Author:   Joan Fabrégat <joan@codeinc.fr>
// Date:     13/03/2018
// Time:     12:37
// Project:  SessionManager
//
declare(strict_types = 1);
namespace CodeInc\SessionManager\Handlers;
use CodeInc\SessionManager\Exceptions\HandlerException;

/**
 * Class FileHandler
 *
 * @package CodeInc\Session\Handlers
 * @author Joan Fabrégat <joan@codeinc.fr>
 */
class FileHandler implements HandlerInterface
{
    /**
     * @var string
     */
    private $savePath;

    /**
     * FileHandler constructor.
     *
     * @param string $savePath
     */
    public function __construct(string $savePath)
    {
        $this->savePath = $savePath;
    }

    /**
     * Returns the local file path for a given id.
     *
     * @param string $id
     * @return string
     * @throws HandlerException
     */
    private function getIdPath(string $id):string
    {
        if (!preg_match("/^[a-z0-9]$/ui", $id)) {
            throw new HandlerException(
                sprintf("The session id %s is invalid", $id),
                $this
            );
        }
        return $this->savePath."/$id.session";
    }

    /**
     * @inheritdoc
     * @throws HandlerException
     */
    public function read(string $id):?array
    {
        $path = $this->getIdPath($id);
        if (file_exists($path)) {
            if (($data = file_get_contents($path)) === false) {
                throw new HandlerException(
                    sprintf("Unable to read the file for the session %s",
                        $id),
                    $this
                );
            }
            if (($data = unserialize($data)) === false) {
                throw new HandlerException(
                    sprintf("Error while parsing the file for the session %s",
                        $id),
                    $this
                );
            }
            return $data;
        }
        return null;
    }

    /**
     * @inheritdoc
     * @throws HandlerException
     */
    public function write(string $id, array $data):void
    {
        if (file_put_contents($this->getIdPath($id), serialize($data)) === false) {
            throw new HandlerException(
                sprintf("Unable to write the file for the session %s",
                    $id),
                $this
            );
        }
    }

    /**
     * @inheritdoc
     */
    public function cleanup(int $maxlifetime):void
    {
        $expiringTime = time() - $maxlifetime;
        foreach (glob($this->savePath."/*.session") as $sessionFile) {
            if (filemtime($sessionFile) < $expiringTime) {
                unlink($sessionFile);
            }
        }
    }

    /**
     * @inheritdoc
     * @throws HandlerException
     */
    public function destroy(string $id):void
    {
        $path = $this->getIdPath($id);
        if (file_exists($path)) {
            unlink($path);
        }
    }
}


<?php

namespace FondOfSpryker\Yves\AvailabilityAlert\Controller;

use Spryker\Shared\Kernel\Store;
use Spryker\Yves\Kernel\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * @method \FondOfSpryker\Yves\AvailabilityAlert\AvailabilityAlertFactory getFactory()
 */
class SubmitController extends AbstractController
{
    /**
     * @param \Symfony\Component\HttpFoundation\Request $request
     *
     * @return array
     */
    public function indexAction(Request $request)
    {
        $parentRequest = $this->getParentRequest();
        $idProductAbstract = $request->attributes->get('idProductAbstract');

        $subscriptionForm = $this->getFactory()
            ->createSubscriptionForm($idProductAbstract)
            ->handleRequest($parentRequest);

        $this->processSubscriptionForm($subscriptionForm, $request);

        return [
            'subscriptionForm' => $subscriptionForm->createView(),
        ];
    }

    /**
     * @param \Symfony\Component\Form\FormInterface $form
     * @param \Symfony\Component\HttpFoundation\Request $request
     *
     * @return bool
     */
    protected function processSubscriptionForm(FormInterface $form, Request $request): bool
    {
        if (!$form->isSubmitted() || !$form->isValid()) {
            return false;
        }

        $availabilityAlertSubscriptionResponseTransfer = $this->getFactory()
            ->getAvailabilityAlertClient()
            ->subscribe(
                $this->getSubscriptionFormData($form)
                    ->setLocaleName($this->getLocale())
                    ->setStore(Store::getInstance()->getStoreName())
            );

        if ($availabilityAlertSubscriptionResponseTransfer->getIsSuccess()) {
            $request->getSession()
                ->getFlashBag()
                ->add('availability-alert-success', 'availibility_alert.feedback.success');

            return true;
        }

        $error = new FormError($availabilityAlertSubscriptionResponseTransfer->getErrors()[0]->getMessage());

        $form->addError($error);

        return false;
    }

    /**
     * @param \Symfony\Component\Form\FormInterface $form
     *
     * @return \Generated\Shared\Transfer\AvailabilityAlertSubscriptionRequestTransfer
     */
    protected function getSubscriptionFormData(FormInterface $form)
    {
        return $form->getData();
    }

    /**
     * @return \Symfony\Component\HttpFoundation\Request
     */
    protected function getParentRequest()
    {
        return $this->getApplication()['request_stack']->getParentRequest();
    }
}


<?php
/**
 * This file is part of the EkiPayumNganluongBundle package.
 *
 * (c) EkiPower <http://ekipower.github.com/>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Eki\Payum\Nganluong\Action;

use Eki\Payum\Nganluong\Api\TransactionStatus;
use Eki\Payum\Nganluong\Api\State\StateInterface;

use Eki\Payum\Nganluong\Api;
use Eki\Payum\Nganluong\Request\Api\GetTransactionDetails;

use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Request\Sync;
use Payum\Core\Action\PaymentAwareAction;
use Payum\Core\Exception\RequestNotSupportedException;

class PaymentDetailsSyncAction extends PaymentAwareAction
{
    /**
     * {@inheritDoc}
     */
    public function execute($request)
    {
        /** @var $request Sync */
        RequestNotSupportedException::assertSupports($this, $request);

        $model = ArrayObject::ensureArrayObject($request->getModel());

        if (false == $model['token']) {
            return;
        }

        $this->payment->execute(new GetTransactionDetails($model));

        if ( isset($model['error_code']) && $model['error_code'] === Errors::ERRCODE_NO_ERROR )
		{
			if ( isset($model['transaction_status']) )
			{
				if ( $model['transaction_status'] === TransactionStatus::PAID )
				{
					$model['state'] = StateInterface::STATE_CONFIRMED;
				}
				else if ( $model['transaction_status'] === TransactionStatus::NOT_PAID )
				{
					$model['state'] = StateInterface::STATE_ERROR;
				}
				else if ( $model['transaction_status'] === TransactionStatus::PAID_WAITING_FOR_PROCESS )
				{
					$model['state'] = StateInterface::STATE_NOTIFIED;
				}
			}
		}
    }

    /**
     * {@inheritDoc}
     */
    public function supports($request)
    {
        if (false == $request instanceof Sync) {
            return false;
        }

        $model = $request->getModel();
        if (false == $model instanceof \ArrayAccess) {
            return false;
        }
    }
}