<?php
namespace Core\Mailer;

/**
 * AbstractMail.php
 *
 * @author Michael "Tekkla" Zorn <tekkla@tekkla.de>
 * @copyright 2016
 * @license MIT
 */
abstract class AbstractMail implements MailInterface
{

    /**
     *
     * @var string
     */
    protected $subject = '';

    /**
     *
     * @var string
     */
    protected $body = '';

    /**
     *
     * @var string
     */
    protected $altbody = '';

    /**
     *
     * @var array
     */
    protected $attachements = [];

    /**
     *
     * @var array
     */
    protected $images = [];

    /**
     *
     * @var boolean
     */
    protected $html = false;

    /**
     *
     * @var string
     */
    protected $charset = 'UTF-8';

    /**
     *
     * @var string
     */
    protected $encoding = '8bit';

    /**
     *
     * @var string
     */
    protected $from = '';

    /**
     *
     * @var string
     */
    protected $fromname = '';

    /**
     *
     * @var string
     */
    protected $sender = '';

    protected $replyto = [];

    /**
     *
     * @var array
     */
    protected $recipients = [
        'to' => [],
        'cc' => [],
        'bcc' => []
    ];

    /**
     *
     * @var string
     */
    protected $confirm_reading_to = '';

    /**
     *
     * @var int
     */
    protected $priority = 3;

    /**
     *
     * @var array
     */
    protected $headers = [];

    /**
     *
     * @var string
     */
    protected $mta = '';

    /**
     *
     * @var bool
     */
    protected $sent_status = false;

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getSubject()
     */
    public function getSubject(): string
    {
        return $this->subject;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setSubject($subject)
     */
    public function setSubject(string $subject)
    {
        $this->subject = $subject;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getBody()
     */
    public function getBody(): string
    {
        return $this->body;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setBody($body)
     */
    public function setBody(string $body)
    {
        $this->body = $body;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getAltbody()
     */
    public function getAltbody(): string
    {
        return $this->altbody;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setAltbody($altbody)
     */
    public function setAltbody(string $altbody)
    {
        $this->altbody = $altbody;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getAttachements()
     */
    public function getAttachements(): array
    {
        return $this->attachements;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addAttachment($path, $name, $encoding, $type)
     */
    public function addAttachment(string $path, string $name = '', string $encoding = 'base64', string $type = 'application/octet-stream')
    {
        $this->attachements[] = [
            'path' => $path,
            'name' => $name,
            'encoding' => $encoding,
            'type' => $type
        ];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearAttachements()
     */
    public function clearAttachements()
    {
        $this->attachements = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getEmbeddedImages()
     */
    public function getEmbeddedImages(): array
    {
        return $this->images;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addEmbeddedImage($path, $cid, $name, $encoding, $type)
     */
    public function addEmbeddedImage(string $path, string $cid, string $name = '', string $encoding = 'base64', string $type = 'application/octet-stream')
    {
        $this->images[] = [
            'path' => $path,
            'cid' => $cid,
            'name' => $name,
            'encoding' => $encoding,
            'type' => $type
        ];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearEmbeddedImages()
     */
    public function clearEmbeddedImages()
    {
        $this->images = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::isHtml($flag)
     */
    public function isHtml(bool $flag = null): bool
    {
        if (empty($flag)) {
            return $this->html;
        }

        $this->html = (bool) $flag;

        return $flag;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getCharset()
     */
    public function getCharset(): string
    {
        return $this->charset;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setCharset($charset)
     */
    public function setCharset(string $charset)
    {
        $this->charset = $charset;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getFrom()
     */
    public function getFrom(): array
    {
        return [
            'from' => $this->from,
            'name' => $this->fromname
        ];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setFrom($from, $name)
     */
    public function setFrom(string $from, string $name = '')
    {
        $this->from = $from;

        if ($name) {
            $this->fromname = $name;
        }
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getFromName()
     */
    public function getFromName(): string
    {
        return $this->fromname;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setFromName($name)
     */
    public function setFromName(string $name)
    {
        $this->fromname = $name;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addReplyto($mailaddress, $name)
     */
    public function addReplyto(string $mailaddress, string $name = '')
    {
        $this->replyto[$mailaddress] = $name;
    }

    /**
     * Adds a list of contacts to the replytolist
     *
     * @param array $reply_tos
     *            List of contacts to add. This array can be an indexed array with only
     *            the contacts mailaddress or an assoc array with mailaddress as key and
     *            the contacts name as value.
     */
    public function addReplytos(array $reply_tos)
    {
        foreach ($reply_tos as $key => $val) {
            if (is_numeric($key)) {
                $this->addReplyto($val);
            } else {
                $this->addReplyto($key, $val);
            }
        }
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getReplyto()
     */
    public function getReplyto(): array
    {
        return $this->replyto;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addRecipient($type, $recipient, $name)
     */
    public function addRecipient(string $type, string $recipient, string $name = '')
    {
        $types = [
            'to',
            'cc',
            'bcc'
        ];

        if (! in_array($type, $types)) {
            Throw new MailException(sprintf('The recipienttype "%" is not allowed. Please select from "to", "cc" or "bcc"'), $type);
        }

        $this->recipients[$type][$recipient] = $name;
    }

    /**
     * Adds a list of recipients to the recipientslist
     *
     * @param string $type
     *            Name of the list to add the recipients. Can be "to", "cc" or "bcc".
     * @param array $recipients
     *            List of recipients to add. This array can be an indexed array with only
     *            the recipients mailaddress or an assoc array with mailaddress as key and
     *            the recipients name as value.
     *
     * @throws MailException when no valid type should be used
     */
    public function addRecipients(string $type, array $recipients)
    {
        $types = [
            'to',
            'cc',
            'bcc'
        ];

        if (! in_array($type, $types)) {
            Throw new MailException(sprintf('The recipienttype "%" is not allowed. Please select from "to", "cc" or "bcc"'), $type);
        }

        foreach ($recipients as $key => $val) {
            if (is_numeric($key)) {
                $this->addRecipient($type, $val);
            } else {
                $this->addRecipient($type, $key, $val);
            }
        }
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getRecipients()
     */
    public function getRecipients(): array
    {
        return $this->recipients;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearRecipients()
     */
    public function clearRecipients()
    {
        $this->recipients = [
            'to' => [],
            'cc' => [],
            'bcc' => []
        ];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addTo($address, $name)
     */
    public function addTo(string $address, string $name = '')
    {
        $this->addRecipient('to', $address, $name);
    }

    /**
     * Adds a arraylist of recipients to recipients "to" list.
     *
     * Works similiar to addRecipients() method.
     *
     * @param array $tos
     *            List of recipients to add. This array can be an indexed array with only
     *            the recipients mailaddress or an assoc array with mailaddress as key and
     *            the recipients name as value.
     */
    public function addTos(array $tos)
    {
        $this->addRecipients('to', $tos);
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearTo()
     */
    public function clearTo()
    {
        $this->recipients['to'] = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addCc($address, $name)
     */
    public function addCc(string $address, string $name = '')
    {
        $this->addRecipient('cc', $address, $name);
    }

    /**
     * Adds a arraylist of recipients to recipients "cc" list.
     *
     * Works similiar to addRecipients() method.
     *
     * @param array $ccs
     *            List of recipients to add. This array can be an indexed array with only
     *            the recipients mailaddress or an assoc array with mailaddress as key and
     *            the recipients name as value.
     */
    public function addCcs(array $tos)
    {
        $this->addRecipients('cc', $tos);
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearCc()
     */
    public function clearCc()
    {
        $this->recipients['cc'] = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addBcc($address, $name)
     */
    public function addBcc(string $address, string $name = '')
    {
        $this->addRecipient('bcc', $address, $name);
    }

    /**
     * Adds a arraylist of recipients to recipients "bcc" list.
     *
     * Works similiar to addRecipients() method.
     *
     * @param array $bccs
     *            List of recipients to add. This array can be an indexed array with only
     *            the recipients mailaddress or an assoc array with mailaddress as key and
     *            the recipients name as value.
     */
    public function addBcs(array $tos)
    {
        $this->addRecipients('bcc', $tos);
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::clearBcc()
     */
    public function clearBcc()
    {
        $this->recipients['bcc'] = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setEncoding($encoding)
     */
    public function setEncoding(string $encoding)
    {
        $this->encoding = $encoding;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getEncoding()
     */
    public function getEncoding(): string
    {
        return $this->encoding;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setConfirmReadingTo($mailadress)
     */
    public function setConfirmReadingTo(string $mailadress)
    {
        $this->confirm_reading_to = $mailadress;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getConfirmReadingTo()
     */
    public function getConfirmReadingTo(): string
    {
        return $this->confirm_reading_to;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::addHeader($header, $value)
     */
    public function addHeader(string $header, string $value = '')
    {
        $this->headers[$header] = $value;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getHeaders()
     */
    public function getHeaders(): array
    {
        return $this->headers;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::cleanHeaders()
     */
    public function cleanHeaders()
    {
        $this->headers = [];
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getPriority()
     */
    public function getPriority(): int
    {
        return $this->priority;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setPriority($priority)
     */
    public function setPriority(int $priority)
    {
        if ($priority < 1 || $priority > 5) {
            Throw new MailException('Mail priority has to be betwenn 1 (high) to 5 (low)');
        }

        $this->priority = $priority;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getMta()
     */
    public function getMta(): string
    {
        if (! $this->mta) {
            Throw new MailException('No MTA id set.');
        }

        return $this->mta;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setMta($id)
     */
    public function setMta(string $id)
    {
        $this->mta = $id;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::getSentStatus()
     */
    public function getSentStatus(): bool
    {
        return $this->sent_status;
    }

    /**
     *
     * {@inheritdoc}
     *
     * @see \Core\Mailer\MailInterface::setSentStatus()
     */
    public function setSentStatus(bool $send_status): void
    {
        $this->sent_status = $send_status;
    }
}


<?php

namespace yii2lab\validator\helpers;

use Exception;
use Yii;

class IinParser {

	const IIN_LENGTH = 12;

	/**
	 * @param $value
	 *
	 * @return mixed
	 * @throws Exception
	 * @deprecated use \yii2woop\operation\domain\v2\helpers\iin\IinParser::parse()
	 */
	public static function parse($value) {
		self::validate($value);
		$part['date'] = IinDateHelper::parseDate($value);
		$part['number'] = substr($value, 7, 4);
		$part['sex'] = self::getSex($value);
		//self::validateSum($value);
		return $part;
	}

	private static function validateIsNumeric($value) {
		$value = strval($value);
		if (!is_numeric($value)) {
			throw new Exception();
		}
	}

	private static function validateLength($value) {
		$value = strval($value);
		if (strlen($value) != self::IIN_LENGTH) {
			throw new Exception(Yii::t('yii', '{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.', [
				'max' => self::IIN_LENGTH,
			]));
		}
	}

	private static function validate($value) {
		self::validateIsNumeric($value);
		self::validateLength($value);
	}

	private static function validateSum($value) {
		$sum = intval(substr($value, 11, 1));
		$sumCalculated = self::generateSum($value);
		if($sum != $sumCalculated) {
			throw new Exception();
		}
	}

	private static function getSex($value) {
		$century = IinDateHelper::parseCentury($value);
		return !empty($century % 2) ? 'male' : 'female';
	}

	private static function generateSum($inn) {
		$multiplication = 7 * $inn[0] + 2 * $inn[1] + 4 * $inn[2] + 10 * $inn[3] + 3 * $inn[4] + 5 * $inn[5] + 9 * $inn[6] + 4 * $inn[7] + 6 * $inn[8] + 8 * $inn[9];
		$sum = $multiplication % 11 % 10;
		return $sum;
	}

}


<?php

namespace liteAuth;

class liteAuth
{
    public $db;
    private $dbfile;
    public $user;
    private $authtoken;
    public function __construct($db, $prefix = 'liteauth_', $preMigrationBackup = False)
    {
        session_start();
        $this->dbfile = $db;
        $this->prefix = $prefix;
        $this->opendb($preMigrationBackup);
        $this->authtoken = isset($_SESSION['liteauth']['token']) ? $_SESSION['liteauth']['token'] : '';
        $this->resumeSession($this->authtoken);
    }

    private function opendb($preMigrationBackup){
        $this->db = new \Medoo\Medoo([
            'database_type' => 'sqlite',
            'database_file' => $this->dbfile
        ]);
        $this->runmigrations($preMigrationBackup);
    }

    private function runmigrations($preMigrationBackup) {
        $next = $this->db->get($this->prefix.'migrations', 'id', [ "ORDER" => ['id' => 'DESC']]) + 1;
        while(file_exists(__DIR__.'/db/'.$next.'.sql'))
        {
            if($preMigrationBackup == True)
            {
                $backupdir = dirname($this->dbfile).'/premigrationbackups';
                if(!file_exists($backupdir))
                {
                    mkdir($backupdir);
                }
                copy($this->dbfile, $backupdir.'/pre-'.$next.'-'.basename($this->dbfile));
            }
            $sql = file_get_contents(__DIR__.'/db/'.$next.'.sql');
            $runsql = str_replace('__TABLE_PREF__', $this->prefix , $sql);
            $sqlarray = explode(';', $runsql);
            foreach($sqlarray as $stmt)
            {
                $this->db->query($stmt);
            }
            $this->db->insert($this->prefix.'migrations' , ['id' => $next] );
            $next++;
        }
    }

    /** Creates a new user with the provided details
    */
    public function newUser($user, $pass, $email = '', $fname = '', $sname = '' , $admin = False){
        $hash = password_hash($pass, PASSWORD_BCRYPT);
        return $this->db->insert($this->prefix.'users', ['user' => $user, 'pass' => $hash, 'admin' => $admin, 'email' => $email, 'first_name' => $fname, 'surname' => $sname]) ? $this->db->id() : False;
    }

    /** Returns True if $pass matches the password for $user
    */
    public function authUser($user, $pass){
        $record = $this->db->get($this->prefix.'users', ['user', 'pass', 'id'], ['user' => $user]);
        if(password_verify($pass, $record['pass']))
        {
            return $record['id'];
        }
        else
        {
            return False;
        }
    }

    /** Checks the password against the given user, and if it authenticates successfully,
    * populates the $this->user property with an instance of the User class for that user.
    */
    public function login($user, $pass)
    {
        if( $id = $this->authUser($user, $pass))
        {
            $this->user = new User($this, $id);
            $newtoken = bin2hex(random_bytes(16));
            $this->db->insert($this->prefix.'authtokens', ['user_id'=>$id, 'token'=>$newtoken]);
            $_SESSION['liteauth']['token'] = $newtoken;
            $this->authtoken = $newtoken;
			return True;
        }
        else
            return False;
    }

    /** Runs when the library is loaded to authenticate and resume the user session
    */
    public function resumeSession($authtoken)
    {
        if( $id = $this->db->get($this->prefix.'authtokens', 'user_id', ['token'=>$authtoken]) )
            $this->user = new User($this, $id);
        else
            return False;
    }

    /** Logs the current user out and destroys the current session token
    * if the $everywhere flag is true, *all* of the current users sessions will be destroyed
    * (effectively logging that user out from any logged in machine)
    */
    public function logout($everywhere = False)
    {
        if($everywhere)
            $this->db->delete($this->prefix.'authtokens', ['user_id' => $this->user->id]);
        else
            $this->db->delete($this->prefix.'authtokens', ['token' => $this->authtoken]);
        $this->user = '';
    }

    /** A helper function which looks for $_POST['user'] and $_POST['pass'] variables, and
    * attempts to log in using them
    */
    public function loginFromPost($user = 'user', $pass='pass')
    {
        if(isset($_POST[$user]) && isset($_POST[$pass]))
            return $this->login($_POST[$user], $_POST[$pass]);
    }

    /** Returns a count of users that exist in the database
    */
    public function countUsers()
    {
        return $this->db->count($this->prefix.'users');
    }

    /** Returns False if no users exist (This is useful to allow for 'first run' setup procedures)
    */
    public function existUsers()
    {
        return $this->countUsers() > 0 ? True : False;
    }

    /** Similarly to loginFromPost(), takes POST data and uses it to register a new user
    * NOTE: it looks for both 'pass1' and 'pass2', and requires both to exist, and match, to be successful
    */
    public function registerFromPost()
    {
        if($_SERVER['REQUEST_METHOD'] == 'POST')
        {
            if(!isset($_POST['user']) OR $_POST['user'] == '')
            {
                throw new \Exception('Must set a username.');
            }
            if(!isset($_POST['pass']) OR $_POST['pass'] == '')
            {
                throw new \Exception('Must set a password.');
            }
            if($_POST['pass']!=$_POST['pass2'])
            {
                throw new \Exception('passwords don\'t match.');
            }
            $email = isset($_POST['email']) ? $_POST['email'] : null;
            $fname = isset($_POST['fname']) ? $_POST['fname'] : null;
            $sname = isset($_POST['sname']) ? $_POST['sname'] : null;
            $admin = isset($_POST['admin']) ? 1 : 0;
            return $this->newUser($_POST['user'], $_POST['pass'], $email, $fname, $sname , $admin);
        }
    }
}


<?php
/**
 * OpenWebPresence Support Library - openwebpresence.com
 *
 * @copyright 2001 - 2017, Brian Tafoya.
 * @package   OwpDb
 * @author    Brian Tafoya <btafoya@briantafoya.com>
 * @version   1.0
 * @license   MIT
 * @license   https://opensource.org/licenses/MIT The MIT License
 * @category  OpenWebPresence_Support_Library
 * @link      http://openwebpresence.com OpenWebPresence
 *
 * Copyright (c) 2017, Brian Tafoya
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * OpenWebPresence Database Support Library
 */
class OwpDb
{

    /**
     * @var object $ezSqlDB ezSQL Database Object
     */
    static public $ezSqlDB = false;

    /**
     * init
     *
     * @access public
     *
     * @author  Brian Tafoya <btafoya@briantafoya.com>
     * @version 1.0
     *
     * @param $DB_USER
     * @param $DB_PASS
     * @param $DB_NAME
     * @param $DB_HOST
     *
     * @return object|OwpEzSqlMysql
     */
    static public function init($DB_USER, $DB_PASS, $DB_NAME, $DB_HOST)
    {
        /**
         * Init the database class
         */
        self::$ezSqlDB = new OwpDBMySQLi($DB_USER, $DB_PASS, $DB_NAME, $DB_HOST);
        self::$ezSqlDB->use_disk_cache = false;
        self::$ezSqlDB->cache_queries  = false;
        self::$ezSqlDB->hide_errors();

        return self::$ezSqlDB;

    }//end init()
}


<?php

namespace Think\Model;

use Think\BaseException;
use Think\Model;

/**
 * 高级模型扩展
 */
abstract class AdvModel extends Model
{
    protected $optimLock = 'lock_version';
    protected $returnType = 'array';
    protected $blobFields = [];
    protected $blobValues = null;
    protected $serializeField = [];
    protected $readonlyField = [];
    protected $_filter = [];
    protected $partition = [];

    public function __construct($name = '')
    {
        if ('' !== $name || is_subclass_of(static::class, $this)) {
            // 如果是AdvModel子类或者有传入模型名称则获取字段缓存
        } else {
            // 空的模型 关闭字段缓存
            $this->autoCheckFields = false;
        }
        parent::__construct($name);
    }

    /**
     * 利用__call方法重载 实现一些特殊的Model方法 （魔术方法）

     *
     * @param string $method 方法名称
     * @param mixed $args 调用参数
     *
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (strtolower(substr($method, 0, 3)) == 'top') {
            // 获取前N条记录
            $count = substr($method, 3);
            array_unshift($args, $count);

            return call_user_func_array([&$this, 'topN'], $args);
        } else {
            return parent::__call($method, $args);
        }
    }

    /**
     * 对保存到数据库的数据进行处理

     *
     * @param mixed $data 要操作的数据
     *
     * @return bool
     */
    protected function _facade($data)
    {
        // 检查序列化字段
        $data = $this->serializeField($data);

        return parent::_facade($data);
    }

    /**
     * 查询成功后的回调方法
     *
     * @param        $result
     * @param string $options
     */
    protected function _after_find(&$result, $options = '')
    {
        // 检查序列化字段
        $this->checkSerializeField($result);
        // 获取文本字段
        $this->getBlobFields($result);
        // 检查字段过滤
        $result = $this->getFilterFields($result);
        // 缓存乐观锁
        $this->cacheLockVersion($result);
    }

    /**
     * 查询数据集成功后的回调方法
     *
     * @param        $resultSet
     * @param string $options
     */
    protected function _after_select(&$resultSet, $options = '')
    {
        // 检查序列化字段
        $resultSet = $this->checkListSerializeField($resultSet);
        // 获取文本字段
        $resultSet = $this->getListBlobFields($resultSet);
        // 检查列表字段过滤
        $resultSet = $this->getFilterListFields($resultSet);
    }

    /**
     * 写入前的回调方法
     *
     * @param        $data
     * @param string $options
     */
    protected function _before_insert(&$data, $options = '')
    {
        // 记录乐观锁
        $data = $this->recordLockVersion($data);
        // 检查文本字段
        $data = $this->checkBlobFields($data);
        // 检查字段过滤
        $data = $this->setFilterFields($data);
    }

    /**
     * 写入后的回调方法
     *
     * @param $data
     * @param $options
     */
    protected function _after_insert($data, $options)
    {
        // 保存文本字段
        $this->saveBlobFields($data);
    }

    /**
     * 更新前的回调方法
     *
     * @param  array $data
     * @param array $options
     *
     * @return bool
     */
    protected function _before_update(&$data, array $options = [])
    {
        // 检查乐观锁
        $pk = $this->getPk();
        if (isset($options['where'][$pk])) {
            $id = $options['where'][$pk];
            if (!$this->checkLockVersion($id, $data)) {
                return false;
            }
        }
        // 检查文本字段
        $data = $this->checkBlobFields($data);
        // 检查只读字段
        $data = $this->checkReadonlyField($data);
        // 检查字段过滤
        $data = $this->setFilterFields($data);
    }

    /**
     * 更新后的回调方法
     *
     * @param $data
     * @param $options
     */
    protected function _after_update($data, $options)
    {
        // 保存文本字段
        $this->saveBlobFields($data);
    }

    /**
     * 删除后的回调方法
     *
     * @param $data
     * @param $options
     */
    protected function _after_delete($data, $options)
    {
        // 删除Blob数据
        $this->delBlobFields($data);
    }

    /**
     * 记录乐观锁

     *
     * @param array $data 数据对象
     *
     * @return array
     */
    protected function recordLockVersion($data)
    {
        // 记录乐观锁
        if ($this->optimLock && !isset($data[$this->optimLock])) {
            if (in_array($this->optimLock, $this->fields, true)) {
                $data[$this->optimLock] = 0;
            }
        }

        return $data;
    }

    /**
     * 缓存乐观锁

     *
     * @param array $data 数据对象
     *
     * @return void
     */
    protected function cacheLockVersion($data)
    {
        if ($this->optimLock) {
            if (isset($data[$this->optimLock]) && isset($data[$this->getPk()])) {
                // 只有当存在乐观锁字段和主键有值的时候才记录乐观锁
                $_SESSION[$this->name.'_'.$data[$this->getPk()].'_lock_version'] = $data[$this->optimLock];
            }
        }
    }

    /**
     * 检查乐观锁

     *
     * @param int $id 当前主键
     * @param array $data 当前数据
     *
     * @return mixed
     */
    protected function checkLockVersion($id, &$data)
    {
        // 检查乐观锁
        $identify = $this->name.'_'.$id.'_lock_version';
        if ($this->optimLock && isset($_SESSION[$identify])) {
            $lock_version = $_SESSION[$identify];
            $vo = $this->field($this->optimLock)->find($id);
            $_SESSION[$identify] = $lock_version;
            $curr_version = $vo[$this->optimLock];
            if (isset($curr_version)) {
                if ($curr_version > 0 && $lock_version != $curr_version) {
                    // 记录已经更新
                    $this->error = L('_RECORD_HAS_UPDATE_');

                    return false;
                } else {
                    // 更新乐观锁
                    $save_version = $data[$this->optimLock];
                    if ($save_version != $lock_version + 1) {
                        $data[$this->optimLock] = $lock_version + 1;
                    }
                    $_SESSION[$identify] = $lock_version + 1;
                }
            }
        }

        return true;
    }

    /**
     * 查找前N个记录

     *
     * @param int $count 记录个数
     * @param array $options 查询表达式
     *
     * @return array
     */
    public function topN($count, $options = [])
    {
        $options['limit'] = $count;

        return $this->select($options);
    }

    /**
     * 查询符合条件的第N条记录
     * 0 表示第一条记录 -1 表示最后一条记录

     *
     * @param int $position 记录位置
     * @param array $options 查询表达式
     *
     * @return mixed
     */
    public function getN($position = 0, $options = [])
    {
        // 正向查找
        if ($position >= 0) {
            $options['limit'] = $position.',1';
            $list = $this->select($options);

            return $list ? $list[0] : false;
            // 逆序查找
        } else {
            $list = $this->select($options);

            return $list ? $list[count($list) - abs($position)] : false;
        }
    }

    /**
     * 获取满足条件的第一条记录

     *
     * @param array $options 查询表达式
     *
     * @return mixed
     */
    public function first($options = [])
    {
        return $this->getN(0, $options);
    }

    /**
     * 获取满足条件的最后一条记录

     *
     * @param array $options 查询表达式
     *
     * @return mixed
     */
    public function last($options = [])
    {
        return $this->getN(-1, $options);
    }

    /**
     * 返回数据

     *
     * @param array $data 数据
     * @param string $type 返回类型 默认为数组
     * @return mixed
     * @throws BaseException
     */
    public function returnResult($data, $type = '')
    {
        if ('' === $type) {
            $type = $this->returnType;
        }
        switch ($type) {
            case 'array' :
                return $data;
            case 'object':
                return (object)$data;
            // 允许用户自定义返回类型
            default:
                if (class_exists($type)) {
                    return new $type($data);
                } else {
                    throw new BaseException(L('_CLASS_NOT_EXIST_').':'.$type);
                }
        }
    }

    /**
     * 获取数据的时候过滤数据字段

     *
     * @param mixed $result 查询的数据
     *
     * @return array
     */
    protected function getFilterFields(&$result)
    {
        if (!empty($this->_filter)) {
            foreach ($this->_filter as $field => $filter) {
                if (isset($result[$field])) {
                    $fun = $filter[1];
                    if (!empty($fun)) {
                        if (isset($filter[2]) && $filter[2]) {
                            // 传递整个数据对象作为参数
                            $result[$field] = call_user_func($fun, $result);
                        } else {
                            // 传递字段的值作为参数
                            $result[$field] = call_user_func($fun, $result[$field]);
                        }
                    }
                }
            }
        }

        return $result;
    }

    /**
     * @param $resultSet
     *
     * @return mixed
     */
    protected function getFilterListFields(&$resultSet)
    {
        if (!empty($this->_filter)) {
            foreach ($resultSet as $key => $result) {
                $resultSet[$key] = $this->getFilterFields($result);
            }
        }

        return $resultSet;
    }

    /**
     * 写入数据的时候过滤数据字段

     *
     * @param mixed $data 查询的数据
     *
     * @return array
     */
    protected function setFilterFields($data)
    {
        if (!empty($this->_filter)) {
            foreach ($this->_filter as $field => $filter) {
                if (isset($data[$field])) {
                    $fun = $filter[0];
                    if (!empty($fun)) {
                        if (isset($filter[2]) && $filter[2]) {
                            // 传递整个数据对象作为参数
                            $data[$field] = call_user_func($fun, $data);
                        } else {
                            // 传递字段的值作为参数
                            $data[$field] = call_user_func($fun, $data[$field]);
                        }
                    }
                }
            }
        }

        return $data;
    }

    /**
     * 返回数据列表

     *
     * @param array $resultSet 数据
     * @param string $type 返回类型 默认为数组
     *
     * @return array|mixed
     */
    protected function returnResultSet(&$resultSet, $type = '')
    {
        foreach ($resultSet as $key => $data) {
            $resultSet[$key] = $this->returnResult($data, $type);
        }

        return $resultSet;
    }

    /**
     * @param array $data
     *
     * @return mixed
     */
    protected function checkBlobFields(&$data)
    {
        // 检查Blob文件保存字段
        if (!empty($this->blobFields)) {
            foreach ($this->blobFields as $field) {
                if (isset($data[$field])) {
                    if (isset($data[$this->getPk()])) {
                        $this->blobValues[$this->name.'/'.$data[$this->getPk()].'_'.$field] = $data[$field];
                    } else {
                        $this->blobValues[$this->name.'/@?id@_'.$field] = $data[$field];
                    }
                    unset($data[$field]);
                }
            }
        }

        return $data;
    }

    /**
     * 获取数据集的文本字段

     *
     * @param array $resultSet 查询的数据
     * @param string $field 查询的字段
     *
     * @return array|mixed
     */
    protected function getListBlobFields(&$resultSet, $field = '')
    {
        if (!empty($this->blobFields)) {
            foreach ($resultSet as $key => $result) {
                $result = $this->getBlobFields($result, $field);
                $resultSet[$key] = $result;
            }
        }

        return $resultSet;
    }

    /**
     * 获取数据的文本字段

     *
     * @param array $data 查询的数据
     * @param string $field 查询的字段
     *
     * @return array|mixed
     */
    protected function getBlobFields(&$data, $field = '')
    {
        if (!empty($this->blobFields)) {
            $pk = $this->getPk();
            $id = $data[$pk];
            if (empty($field)) {
                foreach ($this->blobFields as $field) {
                    $identify = $this->name.'/'.$id.'_'.$field;
                    $data[$field] = F($identify);
                }

                return $data;
            } else {
                $identify = $this->name.'/'.$id.'_'.$field;

                return F($identify);
            }
        }
    }

    /**
     * 保存File方式的字段

     *
     * @param array $data 保存的数据
     *
     * @return void
     */
    protected function saveBlobFields(&$data)
    {
        if (!empty($this->blobFields)) {
            foreach ($this->blobValues as $key => $val) {
                if (strpos($key, '@?id@')) {
                    $key = str_replace('@?id@', $data[$this->getPk()], $key);
                }
                F($key, $val);
            }
        }
    }

    /**
     * 删除File方式的字段

     *
     * @param array $data 保存的数据
     * @param string $field 查询的字段
     *
     * @return void
     */
    protected function delBlobFields(&$data, $field = '')
    {
        if (!empty($this->blobFields)) {
            $pk = $this->getPk();
            $id = $data[$pk];
            if (empty($field)) {
                foreach ($this->blobFields as $field) {
                    $identify = $this->name.'/'.$id.'_'.$field;
                    F($identify, null);
                }
            } else {
                $identify = $this->name.'/'.$id.'_'.$field;
                F($identify, null);
            }
        }
    }

    /**
     * 检查序列化数据字段

     *
     * @param array $data 数据
     *
     * @return array
     */
    protected function serializeField(&$data)
    {
        // 检查序列化字段
        if (!empty($this->serializeField)) {
            // 定义方式  $this->serializeField = array('ser'=>array('name','email'));
            foreach ($this->serializeField as $key => $val) {
                if (empty($data[$key])) {
                    $serialize = [];
                    foreach ($val as $name) {
                        if (isset($data[$name])) {
                            $serialize[$name] = $data[$name];
                            unset($data[$name]);
                        }
                    }
                    if (!empty($serialize)) {
                        $data[$key] = serialize($serialize);
                    }
                }
            }
        }

        return $data;
    }

    /**
     * 检查返回数据的序列化字段
     *
     * @param array $result
     *
     * @return mixed
     */
    protected function checkSerializeField(&$result)
    {
        // 检查序列化字段
        if (!empty($this->serializeField)) {
            foreach ($this->serializeField as $key => $val) {
                if (isset($result[$key])) {
                    $serialize = unserialize($result[$key]);
                    foreach ($serialize as $name => $value) {
                        $result[$name] = $value;
                    }
                    unset($serialize, $result[$key]);
                }
            }
        }

        return $result;
    }

    /**
     * 检查数据集的序列化字段
     *
     * @param array $resultSet
     *
     * @return mixed
     */
    protected function checkListSerializeField(&$resultSet)
    {
        // 检查序列化字段
        if (!empty($this->serializeField)) {
            foreach ($this->serializeField as $key => $val) {
                foreach ($resultSet as $k => $result) {
                    if (isset($result[$key])) {
                        $serialize = unserialize($result[$key]);
                        foreach ($serialize as $name => $value) {
                            $result[$name] = $value;
                        }
                        unset($serialize, $result[$key]);
                        $resultSet[$k] = $result;
                    }
                }
            }
        }

        return $resultSet;
    }

    /**
     * 检查只读字段

     *
     * @param array $data 数据
     *
     * @return array
     */
    protected function checkReadonlyField(&$data)
    {
        if (!empty($this->readonlyField)) {
            foreach ($this->readonlyField as $field) {
                if (isset($data[$field])) {
                    unset($data[$field]);
                }
            }
        }

        return $data;
    }

    /**
     * 批处理执行SQL语句
     * 批处理的指令都认为是execute操作

     *
     * @param array $sql SQL批处理指令
     *
     * @return bool
     * @throws BaseException
     */
    public function patchQuery($sql = [])
    {
        if (!is_array($sql)) {
            return false;
        }
        // 自动启动事务支持
        $this->startTrans();
        try {
            foreach ($sql as $_sql) {
                $result = $this->execute($_sql);
                if (false === $result) {
                    // 发生错误自动回滚事务
                    $this->rollback();

                    return false;
                }
            }
            // 提交事务
            $this->commit();
        } catch (BaseException $e) {
            $this->rollback();
        }

        return true;
    }

    /**
     * 得到分表的的数据表名

     *
     * @param array $data 操作的数据
     *
     * @return string
     */
    public function getPartitionTableName($data = [])
    {
        // 对数据表进行分区
        if (isset($data[$this->partition['field']])) {
            $field = $data[$this->partition['field']];
            switch ($this->partition['type']) {
                case 'id':
                    // 按照id范围分表
                    $step = $this->partition['expr'];
                    $seq = floor($field / $step) + 1;
                    break;
                case 'year':
                    // 按照年份分表
                    if (!is_numeric($field)) {
                        $field = strtotime($field);
                    }
                    $seq = date('Y', $field) - $this->partition['expr'] + 1;
                    break;
                case 'mod':
                    // 按照id的模数分表
                    $seq = ($field % $this->partition['num']) + 1;
                    break;
                case 'md5':
                    // 按照md5的序列分表
                    $seq = (ord(substr(md5($field), 0, 1)) % $this->partition['num']) + 1;
                    break;
                default :
                    if (function_exists($this->partition['type'])) {
                        // 支持指定函数哈希
                        $fun = $this->partition['type'];
                        $seq = (ord(substr($fun($field), 0, 1)) % $this->partition['num']) + 1;
                    } else {
                        // 按照字段的首字母的值分表
                        $seq = (ord($field{0}) % $this->partition['num']) + 1;
                    }
            }

            return $this->getTableName().'_'.$seq;
        } else {
            // 当设置的分表字段不在查询条件或者数据中
            // 进行联合查询，必须设定 partition['num']
            $tableName = [];
            for ($i = 0; $i < $this->partition['num']; $i++) {
                $tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.($i + 1);
            }

            return '( '.implode(" UNION ", $tableName).') AS '.$this->name;

//                return $tableName;
        }
    }
}


<?php
namespace Mamoto\Api;

use Mamoto\Exceptions\JsonException;
use Mamoto\Exceptions\ServerException;

/**
 * Authentication Class to authenticate login/password credentials
 *
 * @author andre
 *
 */
class Authentication extends AbstractApi
{

    const URL = "/oauth2/authorize";

    // access token data
    protected $access_token = null;

    // in how many seconds access token will expire
    protected $access_token_expires_in = null;

    // at what unix-timestamp it will be expire
    protected $access_token_expires_at = null;

    // returned token type
    protected $token_type = null;

    /**
     * return access_token
     *
     * @return string|null access token
     */
    public function getAccessToken()
    {
        return $this->access_token;
    }

    /**
     * return access token type
     *
     * @return string|null type
     */
    public function getTokenType()
    {
        return $this->token_type;
    }

    /**
     * authentication method
     *
     * @return boolean TRUE if authentication was sucessful
     * @throws \Exception
     */
    public function authenticate()
    {
        $returnData = FALSE;
        $process = curl_init($this->base_url . self::URL);
        curl_setopt($process, CURLOPT_HEADER, 0);
        curl_setopt($process, CURLOPT_USERPWD, $this->login . ":" . $this->password);
        curl_setopt($process, CURLOPT_TIMEOUT, 30);
        curl_setopt($process, CURLOPT_POST, 1);
        curl_setopt($process, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
        curl_setopt($process, CURLOPT_RETURNTRANSFER, TRUE);
        $return = curl_exec($process);

        if ($return != FALSE) {
            $json_data = json_decode($return, TRUE);
            if (isset($json_data["errors"])) {
                $err_msg = array();
                foreach ($json_data["errors"] as $error) {
                    $err_msg[] = $error["Message"];
                }
                throw new JsonException(implode(";", $err_msg));
            } else {
                $this->access_token = $json_data["access_token"];
                $this->token_type = $json_data["token_type"];
                $this->access_token_expires_in = (int) $json_data["expires_in"];
                $this->access_token_expires_at = time() + $this->access_token_expires_in - 1;

                $returnData = TRUE;
            }
        } else {
            throw new ServerException(curl_error($process));
        }
        curl_close($process);

        return $returnData;
    }
}


<?php

namespace gries\Pokemath;

use gries\NumberSystem\Exception\NumberParseException;
use gries\NumberSystem\Expression;
use gries\NumberSystem\ExpressionConverter;
use gries\NumberSystem\Number;
use gries\NumberSystem\NumberSystem;

/**
 * Class PokeCalculator
 *
 * The PokeCalculator can be used to translate or calculate mathematical expressions
 * that use the Pokemath Numbersystem.
 *
 * @package gries\Pokemath
 */
class PokeCalculator
{
    const INPUT_DECIMAL = 'decimal';
    const INPUT_POKENUMBER = 'pokenumber';

    /**
     * @var PokeNumberSystem
     */
    protected $numberSystem;

    /**
     * @var ExpressionConverter
     */
    protected $converter;

    public function __construct()
    {
        $this->numberSystem = new PokeNumberSystem();
        $this->converter = new ExpressionConverter();
    }

    /**
     * Translate all PokeNumbers found inside of an expression to decimal numbers.
     * Note: Only expression that use spaces to seperate strings can be parsed
     * This means: "snorlax+jigglypuff" will NOT be recognised whereas "snorlax + jigglypuff" will be parseable.
     *
     * @param string $expression
     *
     * @return string
     */
    public function translate($expression, $inputFormat = self::INPUT_POKENUMBER)
    {
        $inputSystem = $this->numberSystem;
        $outputSystem = new NumberSystem();

        if ($inputFormat === self::INPUT_DECIMAL) {
            $inputSystem = new NumberSystem();
            $outputSystem = $this->numberSystem;
        }

        $expression = new Expression($expression, $inputSystem);

        return $this->converter->convert($expression, $outputSystem)->value();
    }

    /**
     * Calculate a mathematical expression that uses pokemath-numbers
     *
     * @param $expression
     *
     * @return Number
     */
    public function calculate($expression)
    {
        $translatedExpression = $this->translate($expression);
        $result = eval('return '.$translatedExpression.';');

        $decimalResult = new Number($result); // this is bad and needs some work

        return $decimalResult->convert($this->numberSystem);
    }
}


<?php namespace Ordercloud\Entities\Orders;

use JsonSerializable;
use Ordercloud\Entities\Products\ProductExtraDisplay;
use Ordercloud\Entities\Products\ProductOptionDisplay;
use Ordercloud\Entities\Products\ProductPriceDiscount;

class OrderItem implements JsonSerializable
{
    /** @var integer */
    private $id;
    /** @var float */
    private $price;
    /**
     * @var float
     */
    private $markup;
    /**
     * @var float
     */
    private $unitPrice;
    /** @var integer */
    private $quantity;
    /** @var float */
    private $linePrice;
    /** @var boolean */
    private $enabled;
    /** @var OrderItemDetail */
    private $detail;
    /** @var OrderStatus */
    private $status;
    /** @var string */
    private $note;
    /** @var array |ProductPriceDiscount */
    private $itemDiscount;
    /** @var integer */
    private $readyEstimate;
    /**
     * @var array|ProductExtraDisplay[]
     * @reflectType Ordercloud\Entities\Products\ProductExtraDisplay
     */
    private $extras;
    /**
     * @var array|ProductOptionDisplay[]
     * @reflectType Ordercloud\Entities\Products\ProductOptionDisplay
     */
    private $options;
    /** @var bool */
    private $instorePaymentRequired;

    public function __construct(
        $id,
        $price,
        $markup,
        $unitPrice,
        $quantity,
        $linePrice,
        $enabled,
        OrderItemDetail $detail,
        OrderStatus $status,
        $note,
        array  $itemDiscount,
        $readyEstimate,
        array $extras,
        array $options,
        $instorePaymentRequired
    )
    {
        $this->id = $id;
        $this->price = $price;
        $this->markup = $markup;
        $this->quantity = $quantity;
        $this->linePrice = $linePrice;
        $this->enabled = $enabled;
        $this->detail = $detail;
        $this->status = $status;
        $this->note = $note;
        $this->itemDiscount = $itemDiscount;
        $this->readyEstimate = $readyEstimate;
        $this->extras = $extras;
        $this->options = $options;
        $this->instorePaymentRequired = $instorePaymentRequired;
        $this->unitPrice = $unitPrice;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Returns the price per order item.
     * Including options & extras.
     * Excludes quantity.
     *
     * @return float
     */
    public function getPrice()
    {
        return floatval($this->price);
    }

    /**
     * @return float
     */
    public function getMarkup()
    {
        return floatval($this->markup);
    }

    /**
     * @return float
     */
    public function getUnitPrice()
    {
        return floatval($this->unitPrice);
    }

    /**
     * Returns the total price of the order item.
     * Including quantity, options & extras.
     *
     * @return string
     */
    public function getLinePrice()
    {
        return floatval($this->linePrice);
    }

    /**
     * Returns the price of the product.
     * Excludes quantity, options & extras.
     *
     * @return float
     */
    public function getItemPrice()
    {
        return $this->getDetail()->getPrice();
    }

    /**
     * @return int
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return boolean
     */
    public function isEnabled()
    {
        return $this->enabled;
    }

    /**
     * @return OrderItemDetail
     */
    public function getDetail()
    {
        return $this->detail;
    }

    /**
     * @return OrderStatus
     */
    public function getStatus()
    {
        return $this->status;
    }

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

    /**
     * @return ProductPriceDiscount
     */
    public function getItemDiscount()
    {
        return $this->itemDiscount;
    }

    /**
     * @return int
     */
    public function getReadyEstimate()
    {
        return $this->readyEstimate;
    }

    /**
     * @return array|ProductExtraDisplay[]
     */
    public function getExtras()
    {
        return $this->extras;
    }

    /**
     * @return bool
     */
    public function hasExtras()
    {
        return ! empty($this->extras);
    }

    /**
     * @return array|ProductOptionDisplay[]
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * @return bool
     */
    public function hasOptions()
    {
        return ! empty($this->options);
    }

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

    /**
     * Specify data which should be serialized to JSON
     */
    public function jsonSerialize()
    {
        return [
            'id' => $this->getId(),
            'price' => $this->getPrice(),
            'markup' => $this->getMarkup(),
            'unitPrice' => $this->getUnitPrice(),
            'quantity' => $this->getQuantity(),
            'linePrice' => $this->getLinePrice(),
            'enabled' => $this->isEnabled(),
            'detail' => $this->getDetail(),
            'status' => $this->getStatus(),
            'note' => $this->getNote(),
            'itemDiscount' => $this->getItemDiscount(),
            'readyEstimate' => $this->getReadyEstimate(),
            'extras' => $this->getExtras(),
            'options' => $this->getOptions(),
            'instorePaymentRequired' => $this->isInstorePaymentRequired(),
        ];
    }
}


<?php namespace Osufpp\OAuth2\Client\Provider;

use Guzzle\Http\Exception\BadResponseException;
use League\OAuth2\Client\Entity\User;
use League\OAuth2\Client\Exception\IDPException;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;

class Ifsta extends AbstractProvider
{
    public $domain = 'https://auth.ifsta.org';
    public $uidKey = 'id';

    /**
     * Get authorization URL to begin OAuth flow
     *
     * @return string
     */
    public function urlAuthorize()
    {
        return $this->domain . '/dialog/authorize';
    }

    /**
     * Get access token URL to retrieve token
     *
     * @return string
     */
    public function urlAccessToken()
    {
        return $this->domain . '/oauth/token';
    }

    /**
     * Get provider URL to fetch user details
     *
     * @param AccessToken $token
     * @return string
     */
    public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
    {
        return $this->domain . '/api/userinfo?access_token=' . $token;
    }

    /**
     * @param object $response
     * @param AccessToken $token
     * @return User
     */
    public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
    {
        $user = new User();

        $name = (isset($response->name)) ? $response->name : null;
        $firstName = (isset($name)) ? $name->givenName : null;
        $lastName = (isset($name)) ? $name->familyName : null;
        $emails = (isset($response->emails)) ? $response->emails : null;
        $email = ((isset($emails)) && (count($emails) > 0)) ? $emails[0]->value : null;
        $photos = (isset($response->photos)) ? $response->photos : null;
        $photo = ((isset($photos)) && (count($photos) > 0)) ? $photos[0]->value : null;

        $user->exchangeArray([
            'uid' => $response->id,
            'name' => $response->displayName,
            'firstname' => $firstName,
            'lastname' => $lastName,
            'email' => $email,
            'imageurl' => $photo
        ]);

        return $user;
    }
}


<?php

namespace Colorium\Orm;

class Mapper extends SafePDO implements Contract\SourceInterface
{

    /** @var Mapper\Entity[] */
    protected $entities = [];

    /** @var array */
    protected $classmap = [];

    /**
     * Native PDO driver constructor
     *
     * @param \PDO $pdo
     * @param array $classmap
     */
    public function __construct(\PDO $pdo, array $classmap = [])
    {
        parent::__construct($pdo);
        foreach($classmap as $entity => $class) {
            $this->entities[$entity] = Mapper\Entity::of($class);
            $this->classmap[$class] = $entity;
        }
    }

    /**
     * Get entity definition (from name of class)
     *
     * @param string $entity
     * @return Mapper\Entity
     */
    public function entity($entity)
    {
        if(isset($this->classmap[$entity])) {
            $entity = $this->classmap[$entity];
        }
        elseif(!isset($this->entities[$entity])) {
            $this->entities[$entity] = new Mapper\Entity($entity);
        }

        return $this->entities[$entity];
    }

    /**
     * Generate query
     *
     * @param string $entity
     * @return Mapper\Query
     */
    public function query($entity)
    {
        $entity = $this->entity($entity);
        return new Mapper\Query($entity, $this->pdo);
    }

    /**
     * Generate builder
     *
     * @param string $entity
     * @return Mapper\Builder
     */
    public function builder($entity)
    {
        $entity = $this->entity($entity);
        return new Mapper\Builder($entity, $this->pdo);
    }

    /**
     * Alias of query(name)
     *
     * @param $entity
     * @return Mapper\Query
     */
    public function __get($entity)
    {
        return $this->query($entity);
    }

    /**
     * Execute raw query
     *
     * @param string $sql
     * @param array $values
     * @param string $class
     * @return mixed
     */
    public function raw($sql, array $values = [], $class = null)
    {
        return $this->execute($sql, $values, function(\PDOStatement $statement) use($class)
        {
            if($statement->columnCount() > 0) {
                return $class
                    ? $statement->fetchAll(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE, $class)
                    : $statement->fetchAll(\PDO::FETCH_OBJ);
            }

            return $statement->rowCount();
        });
    }

}