diff --git a/.travis.yml b/.travis.yml index e0a7a4458..2aa812ed6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,56 +1,89 @@ +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + language: php +dist: trusty +sudo: required + php: - 5.5 - 5.6 - - 7.0 -sudo: required -dist: trusty +matrix: + include: + - php: 7.0 + env: ZEND_BACKEND="--backend=ZendEngine3" + +services: + - memcached + - redis + - mongodb + - mysql + +git: + depth: 1 + +cache: + apt: true + ccache: true + timeout: 691200 + directories: + - .temp + - vendor + - $HOME/.ccache + - $HOME/.composer/cache env: global: - - DOCKER_COMPOSE_VERSION="1.8.1" PHALCON_SRC_PATH="${TRAVIS_BUILD_DIR}/cphalcon" - matrix: - - PHALCON_VERSION="3.0.x" + - ZEND_DONT_UNLOAD_MODULES=1 + - CC="ccache gcc" + - PATH="$PATH:~/bin" - PHALCON_VERSION="v3.0.2" before_install: - - sudo service memcached stop - - sudo service docker stop - # Fix Hash Sum mismatch - - sudo apt-get purge -y google-chrome-stable - - sudo rm -f /etc/apt/sources.list.d/google* - - phpenv config-rm xdebug.ini + - phpenv config-rm xdebug.ini || true + - sudo ln -s /home/travis/.phpenv/versions/$(phpenv version-name)/bin/phpize /usr/bin/ + - sudo ln -s /home/travis/.phpenv/versions/$(phpenv version-name)/bin/php-config /usr/bin/ + - export PHP_MAJOR="$(echo $TRAVIS_PHP_VERSION | cut -d '.' -f 1,2)" + - if [[ ! -z "${GH_TOKEN}" ]]; then composer config github-oauth.github.com ${GH_TOKEN}; echo "Configured Github token"; fi; + # Install dev-dependencies + - travis_retry composer install --prefer-dist --no-interaction --ignore-platform-reqs + - travis_retry composer require "phalcon/zephir:dev-master" --ignore-platform-reqs + - travis_retry composer require duncan3dc/fork-helper:$(if [[ "${PHP_MAJOR:0:1}" = "7" ]]; then echo "^2.0"; else echo "^1.0"; fi) --ignore-platform-reqs install: - - git clone --depth=1 -q --branch=${PHALCON_VERSION} https://github.com/phalcon/cphalcon.git ${PHALCON_SRC_PATH} - # Install Docker - - sudo apt-get update -qq - - sudo apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y --force-yes docker-engine - - sudo service docker restart - # Install Docker Compose - - sudo rm /usr/local/bin/docker-compose - - curl -s -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose - - chmod +x docker-compose - - sudo mv docker-compose /usr/local/bin - # Install Dependencies - - composer self-update - - travis_retry composer install --ignore-platform-reqs --prefer-source --no-interaction - - travis_retry composer require --ignore-platform-reqs duncan3dc/fork-helper:$(if [[ "${TRAVIS_PHP_VERSION:0:1}" = "7" ]]; then echo "^2.0"; else echo "^1.0"; fi) - # Pull images - - docker pull phalconphp/php:${TRAVIS_PHP_VERSION} - - docker pull phalconphp/zephir:${TRAVIS_PHP_VERSION} + - ( bash tests/_ci/install_zephir.sh ) + # See https://github.com/aerospike/aerospike-client-php/issues/127 + - '[[ "${PHP_MAJOR:0:1}" == "7" ]] || bash ${TRAVIS_BUILD_DIR}/tests/_ci/install_aerospike.sh' + - git clone -q --depth=1 https://github.com/phalcon/cphalcon.git -b ${PHALCON_VERSION} + - ln -s ${TRAVIS_BUILD_DIR}/.temp ${TRAVIS_BUILD_DIR}/cphalcon/.temp + - ( cd cphalcon; zephir fullclean && zephir generate $ZEND_BACKEND ) + - ( cd cphalcon/ext; export CFLAGS="-g3 -O1 -std=gnu90 -Wall -DZEPHIR_RELEASE=1"; /usr/bin/phpize &> /dev/null && ./configure --silent --enable-phalcon &> /dev/null && make --silent -j3 &> /dev/null && make --silent install ) + - ( bash tests/_ci/install_prereqs_$PHP_MAJOR.sh ) before_script: - stty cols 160 - - docker-compose -p incubator up -d - - docker-compose -p incubator ps - - docker logs incubator_aerospike - - sleep 1 + # Create database and user + - echo 'CREATE DATABASE incubator CHARSET=utf8 COLLATE=utf8_unicode_ci' | mysql -u root + - echo "CREATE USER 'incubator'@'%' IDENTIFIED BY 'secret'" | mysql -u root + - echo "GRANT ALL PRIVILEGES ON incubator.* TO 'incubator'@'%' WITH GRANT OPTION" | mysql -u root + - cat ${TRAVIS_BUILD_DIR}/tests/_data/dump.sql | mysql -u root incubator + # See https://github.com/aerospike/aerospike-client-php/issues/127 + - '[[ "${PHP_MAJOR:0:1}" == "7" ]] || bash ${TRAVIS_BUILD_DIR}/tests/_ci/install_aserver.sh' script: - - bash tests/build.sh + - vendor/bin/phpcs + - vendor/bin/codecept build + - vendor/bin/codecept run notifications: email: @@ -58,3 +91,21 @@ notifications: - build@phalconphp.com on_success: change on_failure: always + +addons: + apt: + packages: + - re2c + - beanstalkd + - python-bcrypt + - build-essential + - autoconf + - libssl-dev + - libyaml-dev + - liblua5.1-dev + - mysql-server-5.6 + - mysql-server-core-5.6 + - mysql-client-5.6 + hosts: + - db + - incubator.local diff --git a/Library/Phalcon/Annotations/Adapter/Aerospike.php b/Library/Phalcon/Annotations/Adapter/Aerospike.php index 095e33933..e99ba03ba 100644 --- a/Library/Phalcon/Annotations/Adapter/Aerospike.php +++ b/Library/Phalcon/Annotations/Adapter/Aerospike.php @@ -79,7 +79,8 @@ public function __construct(array $options = []) if (!isset($options['hosts']) || !is_array($options['hosts']) || !isset($options['hosts'][0]) || - !is_array($options['hosts'][0]) + !is_array($options['hosts'][0]) || + empty($options['hosts'][0]) ) { throw new Exception('No hosts given in options'); } diff --git a/Library/Phalcon/Annotations/Extended/AbstractAdapter.php b/Library/Phalcon/Annotations/Extended/AbstractAdapter.php new file mode 100644 index 000000000..ba7afcf23 --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/AbstractAdapter.php @@ -0,0 +1,92 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Annotations\Extended; + +use Phalcon\Annotations\Adapter; +use Phalcon\Annotations\Exception; +use Phalcon\Annotations\Reflection; +use Phalcon\Traits\ConfigurableTrait; + +/** + * Phalcon\Annotations\Extended\AbstractAdapter + * + * This is the base class for Phalcon\Annotations\Extended adapters + * + * @package Phalcon\Annotations\Extended + */ +abstract class AbstractAdapter extends Adapter implements AdapterInterface +{ + use ConfigurableTrait; + + /** + * Configurable properties. + * @var array + */ + protected $configurable = []; + + /** + * AbstractAdapter constructor. + * + * @param array $options + */ + public function __construct(array $options = []) + { + $this->setParameters($options); + } + + /** + * Returns prefixed identifier. + * + * @param string $id + * @return string + */ + abstract protected function getPrefixedIdentifier($id); + + /** + * Check and cast returned result. + * + * @param mixed $result + * @return bool + */ + protected function castResult($result) + { + if ($result instanceof Reflection) { + return $result; + } + + return false; + } + + /** + * Check annotation key. + * + * @param string $key + * + * @throws Exception + */ + protected function checkKey($key) + { + if (!is_string($key)) { + throw new Exception( + sprintf('Invalid key type key to retrieve annotations. Expected string but got %s.', gettype($key)) + ); + } + } +} diff --git a/Library/Phalcon/Annotations/Extended/Adapter/Apc.php b/Library/Phalcon/Annotations/Extended/Adapter/Apc.php new file mode 100644 index 000000000..49982066f --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/Adapter/Apc.php @@ -0,0 +1,201 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Annotations\Extended\Adapter; + +use Phalcon\Annotations\Exception; +use Phalcon\Annotations\Reflection; +use Phalcon\Annotations\Extended\AbstractAdapter; + +/** + * Phalcon\Annotations\Extended\Adapter\Apc + * + * Extended Apc adapter for storing annotations in the APC(u). + * This adapter is suitable for production. + * + * + * use Phalcon\Annotations\Extended\Adapter\Apc; + * + * $annotations = new Apc( + * [ + * 'prefix' => 'app-annotations', // Optional + * 'lifetime' => 8600, // Optional + * 'statsKey' => '_PHAN', // Optional + * ] + * ); + * + * + * @package Phalcon\Annotations\Extended\Adapter + */ +class Apc extends AbstractAdapter +{ + /** + * The storage key prefix. + * @var string + */ + protected $prefix = ''; + + /** + * The storage lifetime. + * @var int + */ + protected $lifetime = 8600; + + /** + * Storage stats key + * @var string + */ + protected $statsKey = '_PHAN'; + + /** + * Configurable properties. + * @var array + */ + protected $configurable = [ + 'prefix', + 'lifetime', + 'statsKey', + ]; + + /** + * Reads parsed annotations from APC(u). + * + * @param string $key + * @return Reflection|bool + * + * @throws Exception + */ + public function read($key) + { + $this->checkKey($key); + + $prefixedKey = $this->getPrefixedIdentifier($key); + + if (function_exists('apcu_fetch')) { + $result = apcu_fetch($prefixedKey); + } else { + $result = apc_fetch($prefixedKey); + } + + return $this->castResult($result); + } + + /** + * Writes parsed annotations to APC(u) + * + * @param string $key + * @param Reflection $data + * @return bool + * + * @throws Exception + */ + public function write($key, Reflection $data) + { + $this->checkKey($key); + + $prefixedKey = $this->getPrefixedIdentifier($key); + + if (function_exists('apcu_store')) { + return apcu_store($prefixedKey, $data, $this->lifetime); + } + + return apc_store($prefixedKey, $data, $this->lifetime); + } + + /** + * {@inheritdoc} + * + * + * use Phalcon\Annotations\Extended\Apc; + * + * $annotations = new Apc(['prefix' => 'app-annotations']); + * $annotations->flush(); + * + * + * @return bool + */ + public function flush() + { + $prefixPattern = '#^_PHAN' . preg_quote("{$this->prefix}", '#') . '#'; + + if (class_exists('\APCuIterator')) { + foreach (new \APCuIterator($prefixPattern) as $item) { + apcu_delete($item['key']); + } + + return true; + } + + foreach (new \APCIterator('user', $prefixPattern) as $item) { + apc_delete($item['key']); + } + + return true; + } + + /** + * {@inheritdoc} + * + * @param string $id + * @return string + */ + protected function getPrefixedIdentifier($id) + { + return $this->statsKey . $this->prefix . $id; + } + + /** + * Sets the storage key prefix. + * + * @param string $prefix The storage key prefix. + * @return $this + */ + protected function setPrefix($prefix) + { + $this->prefix = (string) $prefix; + + return $this; + } + + /** + * Sets the storage lifetime. + * + * @param int $lifetime The storage lifetime. + * @return $this + */ + protected function setLifetime($lifetime) + { + $this->lifetime = (int) $lifetime; + + return $this; + } + + /** + * Sets the storage stats key. + * + * @param string $statsKey The storage key prefix. + * @return $this + */ + protected function setStatsKey($statsKey) + { + $this->statsKey = (string) $statsKey; + + return $this; + } +} diff --git a/Library/Phalcon/Annotations/Extended/Adapter/Files.php b/Library/Phalcon/Annotations/Extended/Adapter/Files.php new file mode 100644 index 000000000..a22d0ceef --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/Adapter/Files.php @@ -0,0 +1,167 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Annotations\Extended\Adapter; + +use Phalcon\Annotations\Exception; +use Phalcon\Annotations\Reflection; +use Phalcon\Annotations\Extended\AbstractAdapter; + +/** + * Phalcon\Annotations\Extended\Adapter\Files + * + * Stores the parsed annotations in files. + * This adapter is suitable for production. + * + * + * use Phalcon\Annotations\Adapter\Files; + * + * $annotations = new Files( + * [ + * "annotationsDir" => "app/cache/annotations/", + * ] + * ); + * + * + * @package Phalcon\Annotations\Extended\Adapter + */ +class Files extends AbstractAdapter +{ + protected $annotationsDir = './'; + + /** + * Configurable properties. + * @var array + */ + protected $configurable = [ + 'annotationsDir', + ]; + + /** + * Files adapter constructor. + * + * @param array $options + */ + public function __construct(array $options = []) + { + if (!isset($options['annotationsDir'])) { + $options['annotationsDir'] =sys_get_temp_dir(); + } + + parent::__construct($options); + } + + /** + * Sets the annotations dir. + * + * @param string $annotationsDir The storage key prefix. + * @return $this + */ + protected function setAnnotationsDir($annotationsDir) + { + $annotationsDir = (string) $annotationsDir; + $this->annotationsDir = rtrim($annotationsDir, '\\/') . DIRECTORY_SEPARATOR; + + return $this; + } + + /** + * Reads parsed annotations from memory. + * + * @param string $key + * @return Reflection|bool + * + * @throws Exception + */ + public function read($key) + { + $this->checkKey($key); + + $result = null; + $path = $this->getPrefixedIdentifier($key); + + if (file_exists($path)) { + /** @noinspection PhpIncludeInspection */ + $result = require $path; + } + + return $this->castResult($result); + } + + /** + * Writes parsed annotations to files. + * + * @param string $key + * @param Reflection $reflection + * @return bool + * + * @throws Exception + */ + public function write($key, Reflection $reflection) + { + $this->checkKey($key); + + $path = $this->getPrefixedIdentifier($key); + + if (file_put_contents($path, ' + * use Phalcon\Annotations\Extended\Files; + * + * $annotations = new Files(['annotationsDir' => BASE_DIR . '/cache/']); + * $annotations->flush(); + * + * + * @return bool + */ + public function flush() + { + $iterator = new \DirectoryIterator($this->annotationsDir); + foreach ($iterator as $item) { + if ($item->isDot() || !$item->isFile() || $item->getExtension() !== 'php') { + continue; + } + + unlink($item->getPathname()); + } + + return true; + } + + /** + * {@inheritdoc} + * + * @param string $id + * @return string + */ + protected function getPrefixedIdentifier($key) + { + $key = strtolower(str_replace(['\\', '/', ':'], '_', $key)); + + return $this->annotationsDir . preg_replace('#_{2,}#', '_', $key) . '.php'; + } +} diff --git a/Library/Phalcon/Annotations/Extended/Adapter/Memory.php b/Library/Phalcon/Annotations/Extended/Adapter/Memory.php new file mode 100644 index 000000000..63bd07ba9 --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/Adapter/Memory.php @@ -0,0 +1,109 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Annotations\Extended\Adapter; + +use Phalcon\Annotations\Exception; +use Phalcon\Annotations\Reflection; +use Phalcon\Annotations\Extended\AbstractAdapter; + +/** + * Phalcon\Annotations\Extended\Adapter\Memory + * + * Extended Memory adapter for storing annotations in memory. + * This adapter is the suitable development/testing. + * + * + * use Phalcon\Annotations\Extended\Adapter\Memory; + * + * $annotations = new Memory(); + * + * + * @package Phalcon\Annotations\Extended\Adapter + */ +class Memory extends AbstractAdapter +{ + protected $data = []; + + /** + * Reads parsed annotations from memory. + * + * @param string $key + * @return Reflection|bool + * + * @throws Exception + */ + public function read($key) + { + $this->checkKey($key); + + $result = null; + $prefixedKey = $this->getPrefixedIdentifier($key); + + if (isset($this->data[$prefixedKey])) { + $result = $this->data[$prefixedKey]; + } + + return $this->castResult($result); + } + + /** + * Writes parsed annotations to memory. + * + * @param string $key + * @param Reflection $reflection + * @return bool + * + * @throws Exception + */ + public function write($key, Reflection $reflection) + { + $this->checkKey($key); + + $prefixedKey = $this->getPrefixedIdentifier($key); + + $this->data[$prefixedKey] = $reflection; + + + return true; + } + + /** + * Immediately invalidates all existing items. + * + * @return bool + */ + public function flush() + { + $this->data = []; + + return true; + } + + /** + * {@inheritdoc} + * + * @param string $id + * @return string + */ + protected function getPrefixedIdentifier($key) + { + return strtolower($key); + } +} diff --git a/Library/Phalcon/Annotations/Extended/AdapterInterface.php b/Library/Phalcon/Annotations/Extended/AdapterInterface.php new file mode 100644 index 000000000..b1d37ea26 --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/AdapterInterface.php @@ -0,0 +1,57 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Annotations\Extended; + +use Phalcon\Annotations\Reflection; +use Phalcon\Annotations\AdapterInterface as BaseInterface; + +/** + * Phalcon\Annotations\Extended\AdapterInterface + * + * This interface must be implemented by adapters in Phalcon\Annotations\Extended + * + * @package Phalcon\Annotations\Extended + */ +interface AdapterInterface extends BaseInterface +{ + /** + * Reads parsed annotations from the current storage. + * + * @param string $key + * @return Reflection|bool + */ + public function read($key); + + /** + * Writes parsed annotations to the current storage. + * + * @param string $key + * @param Reflection $reflection + * @return bool + */ + public function write($key, Reflection $reflection); + + /** + * Immediately invalidates all existing items. + * + * @return bool + */ + public function flush(); +} diff --git a/Library/Phalcon/Annotations/Extended/README.md b/Library/Phalcon/Annotations/Extended/README.md new file mode 100644 index 000000000..ac7a64f20 --- /dev/null +++ b/Library/Phalcon/Annotations/Extended/README.md @@ -0,0 +1,54 @@ +# Phalcon\Annotations\Extended\Adapter + +The main goals of this package: + +* Extended `AdapterInterface` with methods `read`, `write` and `flush` +* Work only with `Phalcon\Annotations\Reflection` (`read` and `write`) +* Ability to set custom `statsKey` +* Work separately from current `Phalcon\Cache\BackendInterface` + +In the future a set of these adapters will be part of the Phalcon Framework. +Usage examples of the adapters available here: + +## Apc + +Stores the parsed annotations in the [Alternative PHP Cache (APC)](http://php.net/manual/en/intro.apcu.php) +using either _APCu_ or _APC_ extension. This adapter is suitable for production. + +```php +use Phalcon\Annotations\Extended\Adapter\Apc; + +$di->set('annotations', function () { + return new Apc([ + 'lifetime' => 8600, // Optional + 'statsSey' => '_PHAN', // Optional + 'prefix' => 'app-annotations-', // Optional + ]); +}); +``` + +## Memory + +Stores the parsed annotations in the memory. This adapter is the suitable development/testing. + +```php +use Phalcon\Annotations\Extended\Adapter\Memory; + +$di->set('annotations', function () { + return new Memory(); +}); +``` + +## Files + +Stores the parsed annotations in files. This adapter is suitable for production. + +```php +use Phalcon\Annotations\Adapter\Files; + +$annotations = new Files( + [ + "annotationsDir" => "app/cache/annotations/", + ] +); +``` diff --git a/Library/Phalcon/Cache/Backend/Aerospike.php b/Library/Phalcon/Cache/Backend/Aerospike.php index 433102f9e..9263d24c3 100644 --- a/Library/Phalcon/Cache/Backend/Aerospike.php +++ b/Library/Phalcon/Cache/Backend/Aerospike.php @@ -277,6 +277,26 @@ public function delete($keyName) return $status == \Aerospike::OK; } + /** + * {@inheritdoc} + * + * @return boolean + */ + public function flush() + { + $keys = $this->queryKeys(); + + $success = true; + + foreach ($keys as $aKey) { + if (!$this->delete($aKey)) { + $success = false; + } + } + + return $success; + } + /** * {@inheritdoc} * @@ -297,9 +317,8 @@ public function exists($keyName = null, $lifetime = null) } $aKey = $this->buildKey($prefixedKey); - $status = $this->db->get($aKey, $cache); - return $status == \Aerospike::OK; + return $this->db->exists($aKey, $cache) == \Aerospike::OK; } /** diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Collection.php b/Library/Phalcon/Db/Adapter/MongoDB/Collection.php index 04e1b85fc..91a5d3dea 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Collection.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Collection.php @@ -1,47 +1,48 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB; -use MongoDB\Driver\Command; +use Traversable; use MongoDB\Driver\Cursor; use MongoDB\Driver\Manager; use MongoDB\Driver\ReadConcern; use MongoDB\Driver\ReadPreference; -use MongoDB\Driver\Server; use MongoDB\Driver\WriteConcern; +use Phalcon\Db\Adapter\MongoDB\Model; +use Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Exception\InvalidArgumentException; -use Phalcon\Db\Adapter\MongoDB\Model\IndexInfoIterator; -use Phalcon\Db\Adapter\MongoDB\Model\IndexInput; -use Phalcon\Db\Adapter\MongoDB\Operation\Aggregate; -use Phalcon\Db\Adapter\MongoDB\Operation\BulkWrite; -use Phalcon\Db\Adapter\MongoDB\Operation\CreateIndexes; -use Phalcon\Db\Adapter\MongoDB\Operation\Count; -use Phalcon\Db\Adapter\MongoDB\Operation\DeleteMany; -use Phalcon\Db\Adapter\MongoDB\Operation\DeleteOne; -use Phalcon\Db\Adapter\MongoDB\Operation\Distinct; -use Phalcon\Db\Adapter\MongoDB\Operation\DropCollection; -use Phalcon\Db\Adapter\MongoDB\Operation\DropIndexes; -use Phalcon\Db\Adapter\MongoDB\Operation\Find; -use Phalcon\Db\Adapter\MongoDB\Operation\FindOne; -use Phalcon\Db\Adapter\MongoDB\Operation\FindOneAndDelete; -use Phalcon\Db\Adapter\MongoDB\Operation\FindOneAndReplace; -use Phalcon\Db\Adapter\MongoDB\Operation\FindOneAndUpdate; -use Phalcon\Db\Adapter\MongoDB\Operation\InsertMany; -use Phalcon\Db\Adapter\MongoDB\Operation\InsertOne; -use Phalcon\Db\Adapter\MongoDB\Operation\ListIndexes; -use Phalcon\Db\Adapter\MongoDB\Operation\ReplaceOne; -use Phalcon\Db\Adapter\MongoDB\Operation\UpdateMany; -use Phalcon\Db\Adapter\MongoDB\Operation\UpdateOne; -use Traversable; +/** + * Phalcon\Db\Adapter\MongoDB\Collection + * + * @package Phalcon\Db\Adapter\MongoDB + */ class Collection { - private static $defaultTypeMap=[ - 'array' =>'Phalcon\Db\Adapter\MongoDB\Model\BSONArray', - 'document'=>'Phalcon\Db\Adapter\MongoDB\Model\BSONDocument', - 'root' =>'Phalcon\Db\Adapter\MongoDB\Model\BSONDocument', + private static $defaultTypeMap = [ + 'array' => Model\BSONArray::class, + 'document' => Model\BSONDocument::class, + 'root' => Model\BSONDocument::class, ]; - private static $wireVersionForFindAndModifyWriteConcern=4; + + private static $wireVersionForFindAndModifyWriteConcern = 4; private $collectionName; private $databaseName; @@ -172,8 +173,6 @@ public function __toString() * a command cursor) does not yet support a custom type map * (depends on: https://jira.mongodb.org/browse/PHPC-314). * - * @see Aggregate::__construct() for supported options - * * @param array $pipeline List of pipeline operations * @param array $options Command options * @@ -183,7 +182,8 @@ public function aggregate(array $pipeline, array $options = []) { $hasOutStage=Functions::isLastPipelineOperatorOut($pipeline); - /* A "majority" read concern is not compatible with the $out stage, so + /** + * A "majority" read concern is not compatible with the $out stage, so * avoid providing the Collection's read concern if it would conflict. */ if (!isset($options['readConcern'])&&!($hasOutStage&&$this->readConcern->getLevel()===ReadConcern::MAJORITY)) { @@ -202,8 +202,8 @@ public function aggregate(array $pipeline, array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new Aggregate($this->databaseName, $this->collectionName, $pipeline, $options); - $server =$this->manager->selectServer($options['readPreference']); + $operation = new Operation\Aggregate($this->databaseName, $this->collectionName, $pipeline, $options); + $server = $this->manager->selectServer($options['readPreference']); return $operation->execute($server); } @@ -211,8 +211,6 @@ public function aggregate(array $pipeline, array $options = []) /** * Executes multiple write operations. * - * @see BulkWrite::__construct() for supported options - * * @param array[] $operations List of write operations * @param array $options Command options * @@ -224,7 +222,7 @@ public function bulkWrite(array $operations, array $options = []) $options['writeConcern']=$this->writeConcern; } - $operation=new BulkWrite($this->databaseName, $this->collectionName, $operations, $options); + $operation=new Operation\BulkWrite($this->databaseName, $this->collectionName, $operations, $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -233,8 +231,6 @@ public function bulkWrite(array $operations, array $options = []) /** * Gets the number of documents matching the filter. * - * @see Count::__construct() for supported options - * * @param array|object $filter Query by which to filter documents * @param array $options Command options * @@ -250,7 +246,7 @@ public function count($filter = [], array $options = []) $options['readPreference']=$this->readPreference; } - $operation=new Count($this->databaseName, $this->collectionName, $filter, $options); + $operation=new Operation\Count($this->databaseName, $this->collectionName, $filter, $options); $server =$this->manager->selectServer($options['readPreference']); return $operation->execute($server); @@ -259,8 +255,6 @@ public function count($filter = [], array $options = []) /** * Create a single index for the collection. * - * @see Collection::createIndexes() - * * @param array|object $key Document containing fields mapped to values, * which denote order or an index type * @param array $options Index options @@ -289,9 +283,6 @@ public function createIndex($key, array $options = []) * If the "name" option is unspecified, a name will be generated from the * "key" document. * - * @see http://docs.mongodb.org/manual/reference/command/createIndexes/ - * @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/ - * * @param array[] $indexes List of index specifications * * @return string[] The names of the created indexes @@ -299,7 +290,7 @@ public function createIndex($key, array $options = []) */ public function createIndexes(array $indexes) { - $operation=new CreateIndexes($this->databaseName, $this->collectionName, $indexes); + $operation=new Operation\CreateIndexes($this->databaseName, $this->collectionName, $indexes); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -308,9 +299,6 @@ public function createIndexes(array $indexes) /** * Deletes all documents matching the filter. * - * @see DeleteMany::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/delete/ - * * @param array|object $filter Query by which to delete documents * @param array $options Command options * @@ -322,7 +310,7 @@ public function deleteMany($filter, array $options = []) $options['writeConcern']=$this->writeConcern; } - $operation=new DeleteMany($this->databaseName, $this->collectionName, $filter, $options); + $operation=new Operation\DeleteMany($this->databaseName, $this->collectionName, $filter, $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -331,9 +319,6 @@ public function deleteMany($filter, array $options = []) /** * Deletes at most one document matching the filter. * - * @see DeleteOne::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/delete/ - * * @param array|object $filter Query by which to delete documents * @param array $options Command options * @@ -345,7 +330,7 @@ public function deleteOne($filter, array $options = []) $options['writeConcern']=$this->writeConcern; } - $operation=new DeleteOne($this->databaseName, $this->collectionName, $filter, $options); + $operation=new Operation\DeleteOne($this->databaseName, $this->collectionName, $filter, $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -354,8 +339,6 @@ public function deleteOne($filter, array $options = []) /** * Finds the distinct values for a specified field across the collection. * - * @see Distinct::__construct() for supported options - * * @param string $fieldName Field for which to return distinct values * @param array|object $filter Query by which to filter documents * @param array $options Command options @@ -372,7 +355,7 @@ public function distinct($fieldName, $filter = [], array $options = []) $options['readPreference']=$this->readPreference; } - $operation=new Distinct($this->databaseName, $this->collectionName, $fieldName, $filter, $options); + $operation=new Operation\Distinct($this->databaseName, $this->collectionName, $fieldName, $filter, $options); $server =$this->manager->selectServer($options['readPreference']); return $operation->execute($server); @@ -381,8 +364,6 @@ public function distinct($fieldName, $filter = [], array $options = []) /** * Drop this collection. * - * @see DropCollection::__construct() for supported options - * * @param array $options Additional options * * @return array|object Command result document @@ -393,7 +374,7 @@ public function drop(array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new DropCollection($this->databaseName, $this->collectionName, $options); + $operation=new Operation\DropCollection($this->databaseName, $this->collectionName, $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -402,8 +383,6 @@ public function drop(array $options = []) /** * Drop a single index in the collection. * - * @see DropIndexes::__construct() for supported options - * * @param string $indexName Index name * @param array $options Additional options * @@ -422,7 +401,7 @@ public function dropIndex($indexName, array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new DropIndexes($this->databaseName, $this->collectionName, $indexName, $options); + $operation=new Operation\DropIndexes($this->databaseName, $this->collectionName, $indexName, $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -431,8 +410,6 @@ public function dropIndex($indexName, array $options = []) /** * Drop all indexes in the collection. * - * @see DropIndexes::__construct() for supported options - * * @param array $options Additional options * * @return array|object Command result document @@ -443,7 +420,7 @@ public function dropIndexes(array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new DropIndexes($this->databaseName, $this->collectionName, '*', $options); + $operation=new Operation\DropIndexes($this->databaseName, $this->collectionName, '*', $options); $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); @@ -452,9 +429,6 @@ public function dropIndexes(array $options = []) /** * Finds documents matching the query. * - * @see Find::__construct() for supported options - * @see http://docs.mongodb.org/manual/core/read-operations-introduction/ - * * @param array|object $filter Query by which to filter documents * @param array $options Additional options * @@ -474,7 +448,7 @@ public function find($filter = [], array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new Find($this->databaseName, $this->collectionName, $filter, $options); + $operation=new Operation\Find($this->databaseName, $this->collectionName, $filter, $options); $server =$this->manager->selectServer($options['readPreference']); return $operation->execute($server); @@ -483,9 +457,6 @@ public function find($filter = [], array $options = []) /** * Finds a single document matching the query. * - * @see FindOne::__construct() for supported options - * @see http://docs.mongodb.org/manual/core/read-operations-introduction/ - * * @param array|object $filter Query by which to filter documents * @param array $options Additional options * @@ -505,7 +476,7 @@ public function findOne($filter = [], array $options = []) $options['typeMap']=$this->typeMap; } - $operation=new FindOne($this->databaseName, $this->collectionName, $filter, $options); + $operation=new Operation\FindOne($this->databaseName, $this->collectionName, $filter, $options); $server =$this->manager->selectServer($options['readPreference']); return $operation->execute($server); @@ -519,19 +490,15 @@ public function findOne($filter = [], array $options = []) * Note: BSON deserialization of the returned document does not yet support * a custom type map (depends on: https://jira.mongodb.org/browse/PHPC-314). * - * @see FindOneAndDelete::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ - * - * @param array|object $filter Query by which to filter documents - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array $options Command options [Optional] * @return object|null */ public function findOneAndDelete($filter, array $options = []) { - $server=$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); - if (!isset($options['writeConcern'])&&Functions::serverSupportsFeature( + if (!isset($options['writeConcern']) && Functions::serverSupportsFeature( $server, self::$wireVersionForFindAndModifyWriteConcern ) @@ -539,7 +506,7 @@ public function findOneAndDelete($filter, array $options = []) $options['writeConcern']=$this->writeConcern; } - $operation=new FindOneAndDelete($this->databaseName, $this->collectionName, $filter, $options); + $operation = new Operation\FindOneAndDelete($this->databaseName, $this->collectionName, $filter, $options); return $operation->execute($server); } @@ -556,28 +523,30 @@ public function findOneAndDelete($filter, array $options = []) * Note: BSON deserialization of the returned document does not yet support * a custom type map (depends on: https://jira.mongodb.org/browse/PHPC-314). * - * @see FindOneAndReplace::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ - * - * @param array|object $filter Query by which to filter documents - * @param array|object $replacement Replacement document - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array|object $replacement Replacement document + * @param array $options Command options [Optional] * @return object|null */ public function findOneAndReplace($filter, $replacement, array $options = []) { - $server=$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); - if (!isset($options['writeConcern'])&&Functions::serverSupportsFeature( + if (!isset($options['writeConcern']) && Functions::serverSupportsFeature( $server, self::$wireVersionForFindAndModifyWriteConcern ) ) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new FindOneAndReplace($this->databaseName, $this->collectionName, $filter, $replacement, $options); + $operation = new Operation\FindOneAndReplace( + $this->databaseName, + $this->collectionName, + $filter, + $replacement, + $options + ); return $operation->execute($server); } @@ -594,28 +563,30 @@ public function findOneAndReplace($filter, $replacement, array $options = []) * Note: BSON deserialization of the returned document does not yet support * a custom type map (depends on: https://jira.mongodb.org/browse/PHPC-314). * - * @see FindOneAndReplace::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ - * - * @param array|object $filter Query by which to filter documents - * @param array|object $update Update to apply to the matched document - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array|object $update Update to apply to the matched document + * @param array $options Command options [Optional] * @return object|null */ public function findOneAndUpdate($filter, $update, array $options = []) { - $server=$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); - if (!isset($options['writeConcern'])&&Functions::serverSupportsFeature( + if (!isset($options['writeConcern']) && Functions::serverSupportsFeature( $server, self::$wireVersionForFindAndModifyWriteConcern ) ) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new FindOneAndUpdate($this->databaseName, $this->collectionName, $filter, $update, $options); + $operation = new Operation\FindOneAndUpdate( + $this->databaseName, + $this->collectionName, + $filter, + $update, + $options + ); return $operation->execute($server); } @@ -643,33 +614,28 @@ public function getDatabaseName() /** * Return the collection namespace. * - * @see https://docs.mongodb.org/manual/reference/glossary/#term-namespace * @return string */ public function getNamespace() { - return $this->databaseName.'.'.$this->collectionName; + return $this->databaseName . '.' . $this->collectionName; } /** * Inserts multiple documents. * - * @see InsertMany::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/insert/ - * - * @param array[]|object[] $documents The documents to insert - * @param array $options Command options - * + * @param array[]|object[] $documents The documents to insert + * @param array $options Command options [Optional] * @return InsertManyResult */ public function insertMany(array $documents, array $options = []) { if (!isset($options['writeConcern'])) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new InsertMany($this->databaseName, $this->collectionName, $documents, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\InsertMany($this->databaseName, $this->collectionName, $documents, $options); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } @@ -677,36 +643,44 @@ public function insertMany(array $documents, array $options = []) /** * Inserts one document. * - * @see InsertOne::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/insert/ - * * @param array|object $document The document to insert - * @param array $options Command options - * + * @param array $options Command options [Optional] * @return InsertOneResult */ public function insertOne($document, array $options = []) { if (!isset($options['writeConcern'])) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new InsertOne($this->databaseName, $this->collectionName, $document, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\InsertOne($this->databaseName, $this->collectionName, $document, $options); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } + /** + * Inserts the document. + * + * @param array|object $document The document to insert + * @param array $options Command options [Optional] + * @return mixed + */ + public function insert($document, array $options = []) + { + return $this->insertOne($document, $options); + } + /** * Returns information for all indexes for the collection. * - * @see ListIndexes::__construct() for supported options - * @return IndexInfoIterator + * @param array $options Command options [Optional] + * @return Model\IndexInfoIterator */ public function listIndexes(array $options = []) { - $operation=new ListIndexes($this->databaseName, $this->collectionName, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\ListIndexes($this->databaseName, $this->collectionName, $options); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } @@ -714,23 +688,26 @@ public function listIndexes(array $options = []) /** * Replaces at most one document matching the filter. * - * @see ReplaceOne::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/update/ - * - * @param array|object $filter Query by which to filter documents - * @param array|object $replacement Replacement document - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array|object $replacement Replacement document + * @param array $options Command options [Optional] * @return UpdateResult */ public function replaceOne($filter, $replacement, array $options = []) { if (!isset($options['writeConcern'])) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new ReplaceOne($this->databaseName, $this->collectionName, $filter, $replacement, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\ReplaceOne( + $this->databaseName, + $this->collectionName, + $filter, + $replacement, + $options + ); + + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } @@ -738,23 +715,19 @@ public function replaceOne($filter, $replacement, array $options = []) /** * Updates all documents matching the filter. * - * @see UpdateMany::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/update/ - * - * @param array|object $filter Query by which to filter documents - * @param array|object $update Update to apply to the matched documents - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array|object $update Update to apply to the matched documents + * @param array $options Command options [Optional] * @return UpdateResult */ public function updateMany($filter, $update, array $options = []) { if (!isset($options['writeConcern'])) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new UpdateMany($this->databaseName, $this->collectionName, $filter, $update, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\UpdateMany($this->databaseName, $this->collectionName, $filter, $update, $options); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } @@ -762,23 +735,19 @@ public function updateMany($filter, $update, array $options = []) /** * Updates at most one document matching the filter. * - * @see UpdateOne::__construct() for supported options - * @see http://docs.mongodb.org/manual/reference/command/update/ - * - * @param array|object $filter Query by which to filter documents - * @param array|object $update Update to apply to the matched document - * @param array $options Command options - * + * @param array|object $filter Query by which to filter documents + * @param array|object $update Update to apply to the matched document + * @param array $options Command options [Optional] * @return UpdateResult */ public function updateOne($filter, $update, array $options = []) { if (!isset($options['writeConcern'])) { - $options['writeConcern']=$this->writeConcern; + $options['writeConcern'] = $this->writeConcern; } - $operation=new UpdateOne($this->databaseName, $this->collectionName, $filter, $update, $options); - $server =$this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); + $operation = new Operation\UpdateOne($this->databaseName, $this->collectionName, $filter, $update, $options); + $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); return $operation->execute($server); } @@ -786,19 +755,16 @@ public function updateOne($filter, $update, array $options = []) /** * Get a clone of this collection with different options. * - * @see Collection::__construct() for supported options - * - * @param array $options Collection constructor options - * + * @param array $options Collection constructor options [Optional] * @return Collection */ public function withOptions(array $options = []) { - $options+=[ - 'readConcern' =>$this->readConcern, - 'readPreference'=>$this->readPreference, - 'typeMap' =>$this->typeMap, - 'writeConcern' =>$this->writeConcern, + $options += [ + 'readConcern' => $this->readConcern, + 'readPreference' => $this->readPreference, + 'typeMap' => $this->typeMap, + 'writeConcern' => $this->writeConcern, ]; return new Collection($this->manager, $this->databaseName, $this->collectionName, $options); diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Functions.php b/Library/Phalcon/Db/Adapter/MongoDB/Functions.php index 2311bff9e..6790130d1 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Functions.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Functions.php @@ -140,8 +140,6 @@ public static function readConcernAsDocument(ReadConcern $readConcern) /** * Return whether the server supports a particular feature. * - * @internal - * * @param Server $server Server to check * @param integer $feature Feature constant (i.e. wire protocol version) * diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Aggregate.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Aggregate.php index 32e233e89..b9638cefe 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Aggregate.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Aggregate.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -16,9 +33,7 @@ /** * Operation for the aggregate command. * - * @api - * @see MongoDB\Collection::aggregate() - * @see http://docs.mongodb.org/manual/reference/command/aggregate/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Aggregate implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/BulkWrite.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/BulkWrite.php index 9f48057bd..1e0efe875 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/BulkWrite.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/BulkWrite.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\BulkWriteResult; @@ -12,8 +29,7 @@ /** * Operation for executing multiple write operations. * - * @api - * @see MongoDB\Collection::bulkWrite() + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class BulkWrite implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Count.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Count.php index d37bb6a25..d67e7d5d3 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Count.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Count.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -13,9 +30,7 @@ /** * Operation for the count command. * - * @api - * @see MongoDB\Collection::count() - * @see http://docs.mongodb.org/manual/reference/command/count/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Count implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateCollection.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateCollection.php index 27840abcd..dcc3412e2 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateCollection.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateCollection.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -9,9 +26,7 @@ /** * Operation for the create command. * - * @api - * @see MongoDB\Database::createCollection() - * @see http://docs.mongodb.org/manual/reference/command/create/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class CreateCollection implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateIndexes.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateIndexes.php index 9e3de81e2..0f344814b 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateIndexes.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/CreateIndexes.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -13,10 +30,7 @@ /** * Operation for the createIndexes command. * - * @api - * @see MongoDB\Collection::createIndex() - * @see MongoDB\Collection::createIndexes() - * @see http://docs.mongodb.org/manual/reference/command/createIndexes/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class CreateIndexes implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DatabaseCommand.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DatabaseCommand.php index 6ccf73114..5534f0f5f 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DatabaseCommand.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DatabaseCommand.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -10,8 +27,7 @@ /** * Operation for executing a database command. * - * @api - * @see MongoDB\Database::command() + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DatabaseCommand implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Delete.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Delete.php index ac809ce5a..9b3637d4f 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Delete.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Delete.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\DeleteResult; @@ -14,8 +31,7 @@ * This class is used internally by the DeleteMany and DeleteOne operation * classes. * - * @internal - * @see http://docs.mongodb.org/manual/reference/command/delete/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Delete implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteMany.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteMany.php index c6930a1b8..69767dab7 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteMany.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteMany.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\DeleteResult; @@ -9,9 +26,7 @@ /** * Operation for deleting multiple document with the delete command. * - * @api - * @see MongoDB\Collection::deleteOne() - * @see http://docs.mongodb.org/manual/reference/command/delete/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DeleteMany implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteOne.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteOne.php index 57bc16259..67a427c36 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteOne.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DeleteOne.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\DeleteResult; @@ -9,9 +26,7 @@ /** * Operation for deleting a single document with the delete command. * - * @api - * @see MongoDB\Collection::deleteOne() - * @see http://docs.mongodb.org/manual/reference/command/delete/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DeleteOne implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Distinct.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Distinct.php index ce5afc4e1..a3060b9cd 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Distinct.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Distinct.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -13,9 +30,7 @@ /** * Operation for the distinct command. * - * @api - * @see MongoDB\Collection::distinct() - * @see http://docs.mongodb.org/manual/reference/command/distinct/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Distinct implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropCollection.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropCollection.php index 23a77883b..5e4529bbd 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropCollection.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropCollection.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -10,10 +27,7 @@ /** * Operation for the drop command. * - * @api - * @see MongoDB\Collection::drop() - * @see MongoDB\Database::dropCollection() - * @see http://docs.mongodb.org/manual/reference/command/drop/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DropCollection implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropDatabase.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropDatabase.php index 29606dc8e..51d6fd825 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropDatabase.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropDatabase.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -9,10 +26,7 @@ /** * Operation for the dropDatabase command. * - * @api - * @see MongoDB\Client::dropDatabase() - * @see MongoDB\Database::drop() - * @see http://docs.mongodb.org/manual/reference/command/dropDatabase/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DropDatabase implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropIndexes.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropIndexes.php index 9865ab92a..81630b335 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropIndexes.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/DropIndexes.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -9,9 +26,7 @@ /** * Operation for the dropIndexes command. * - * @api - * @see MongoDB\Collection::dropIndexes() - * @see http://docs.mongodb.org/manual/reference/command/dropIndexes/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class DropIndexes implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Executable.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Executable.php index 0bcbd0a25..d6c9b95c4 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Executable.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Executable.php @@ -10,7 +10,7 @@ * This interface is reserved for internal use until PHPC-378 is implemented, * since execute() should ultimately be changed to use ServerInterface. * - * @internal + * @package Phalcon\Db\Adapter\MongoDB\Operation */ interface Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Find.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Find.php index 2007d4f19..175bb1cee 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Find.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Find.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Cursor; @@ -12,10 +29,7 @@ /** * Operation for the find command. * - * @api - * @see MongoDB\Collection::find() - * @see http://docs.mongodb.org/manual/tutorial/query-documents/ - * @see http://docs.mongodb.org/manual/reference/operator/query-modifier/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Find implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindAndModify.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindAndModify.php index 0395f7217..994caca6b 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindAndModify.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindAndModify.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -15,8 +32,7 @@ * This class is used internally by the FindOneAndDelete, FindOneAndReplace, and * FindOneAndUpdate operation classes. * - * @internal - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class FindAndModify implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOne.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOne.php index f362f4ea2..148815b45 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOne.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOne.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Server; @@ -8,10 +25,7 @@ /** * Operation for finding a single document with the find command. * - * @api - * @see MongoDB\Collection::findOne() - * @see http://docs.mongodb.org/manual/tutorial/query-documents/ - * @see http://docs.mongodb.org/manual/reference/operator/query-modifier/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class FindOne implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndDelete.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndDelete.php index 9329fc9df..d200ab093 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndDelete.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndDelete.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -9,9 +26,7 @@ /** * Operation for deleting a document with the findAndModify command. * - * @api - * @see MongoDB\Collection::findOneAndDelete() - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class FindOneAndDelete implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndReplace.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndReplace.php index 1178a0c20..a1eb26fda 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndReplace.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndReplace.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -10,9 +27,7 @@ /** * Operation for replacing a document with the findAndModify command. * - * @api - * @see MongoDB\Collection::findOneAndReplace() - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class FindOneAndReplace implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndUpdate.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndUpdate.php index afaa1d172..effaa2048 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndUpdate.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/FindOneAndUpdate.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -10,9 +27,7 @@ /** * Operation for updating a document with the findAndModify command. * - * @api - * @see MongoDB\Collection::findOneAndUpdate() - * @see http://docs.mongodb.org/manual/reference/command/findAndModify/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class FindOneAndUpdate implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertMany.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertMany.php index 16e68fd2b..76651a361 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertMany.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertMany.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -12,9 +29,7 @@ /** * Operation for inserting multiple documents with the insert command. * - * @api - * @see MongoDB\Collection::insertMany() - * @see http://docs.mongodb.org/manual/reference/command/insert/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class InsertMany implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertOne.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertOne.php index 82f63d560..072072cd3 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertOne.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/InsertOne.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -12,9 +29,7 @@ /** * Operation for inserting a single document with the insert command. * - * @api - * @see MongoDB\Collection::insertOne() - * @see http://docs.mongodb.org/manual/reference/command/insert/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class InsertOne implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListCollections.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListCollections.php index 3dbc1e991..e913b8480 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListCollections.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListCollections.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -14,9 +31,7 @@ /** * Operation for the listCollections command. * - * @api - * @see MongoDB\Database::listCollections() - * @see http://docs.mongodb.org/manual/reference/command/listCollections/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class ListCollections implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListDatabases.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListDatabases.php index 07d9cda19..1a6f43dc4 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListDatabases.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListDatabases.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -12,9 +29,7 @@ /** * Operation for the ListDatabases command. * - * @api - * @see MongoDB\Client::listDatabases() - * @see http://docs.mongodb.org/manual/reference/command/ListDatabases/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class ListDatabases implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListIndexes.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListIndexes.php index 474c08773..e83524e01 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListIndexes.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ListIndexes.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use MongoDB\Driver\Command; @@ -15,9 +32,7 @@ /** * Operation for the listIndexes command. * - * @api - * @see MongoDB\Collection::listIndexes() - * @see http://docs.mongodb.org/manual/reference/command/listIndexes/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class ListIndexes implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ReplaceOne.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ReplaceOne.php index 7d618dd6d..2c94bc23c 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/ReplaceOne.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/ReplaceOne.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -10,9 +27,7 @@ /** * Operation for replacing a single document with the update command. * - * @api - * @see MongoDB\Collection::replaceOne() - * @see http://docs.mongodb.org/manual/reference/command/update/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class ReplaceOne implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Update.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Update.php index 4a148b71b..7caf394c5 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/Update.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/Update.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -15,8 +32,7 @@ * This class is used internally by the ReplaceOne, UpdateMany, and UpdateOne * operation classes. * - * @internal - * @see http://docs.mongodb.org/manual/reference/command/update/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class Update implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateMany.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateMany.php index 10ab674e5..2c7d69fda 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateMany.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateMany.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -10,9 +27,7 @@ /** * Operation for updating multiple documents with the update command. * - * @api - * @see MongoDB\Collection::updateMany() - * @see http://docs.mongodb.org/manual/reference/command/update/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class UpdateMany implements Executable { diff --git a/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateOne.php b/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateOne.php index 38ba1e365..16971026c 100644 --- a/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateOne.php +++ b/Library/Phalcon/Db/Adapter/MongoDB/Operation/UpdateOne.php @@ -1,5 +1,22 @@ | + +------------------------------------------------------------------------+ +*/ + namespace Phalcon\Db\Adapter\MongoDB\Operation; use Phalcon\Db\Adapter\MongoDB\Functions; @@ -10,9 +27,7 @@ /** * Operation for updating a single document with the update command. * - * @api - * @see MongoDB\Collection::updateOne() - * @see http://docs.mongodb.org/manual/reference/command/update/ + * @package Phalcon\Db\Adapter\MongoDB\Operation */ class UpdateOne implements Executable { diff --git a/Library/Phalcon/Error/Handler.php b/Library/Phalcon/Error/Handler.php index ebe9debbf..782f2ff73 100644 --- a/Library/Phalcon/Error/Handler.php +++ b/Library/Phalcon/Error/Handler.php @@ -23,6 +23,7 @@ namespace Phalcon\Error; use Phalcon\Di; +use Phalcon\DiInterface; use Phalcon\Logger\Formatter; use Phalcon\Logger; use Phalcon\Logger\AdapterInterface; @@ -92,12 +93,20 @@ public static function register() /** * Logs the error and dispatches an error controller. * - * @param \Phalcon\Error\Error $error - * @return mixed + * @param Error $error */ public static function handle(Error $error) { $di = Di::getDefault(); + + $type = static::getErrorType($error->type()); + $message = "$type: {$error->message()} in {$error->file()} on line {$error->line()}"; + + if (!$di instanceof DiInterface) { + echo $message; + return; + } + $config = $di->getShared('config')->error->toArray(); $logger = $config['logger']; @@ -105,9 +114,6 @@ public static function handle(Error $error) $logger = new FileLogger($logger); } - $type = static::getErrorType($error->type()); - $message = "$type: {$error->message()} in {$error->file()} on line {$error->line()}"; - if (isset($config['formatter'])) { $formatter = null; @@ -172,7 +178,8 @@ public static function handle(Error $error) $view->render($config['controller'], $config['action'], $dispatcher->getParams()); $view->finish(); - return $response->setContent($view->getContent())->send(); + $response->setContent($view->getContent())->send(); + return; } else { echo $message; } diff --git a/Library/Phalcon/Http/Client/Header.php b/Library/Phalcon/Http/Client/Header.php index 38eff4b3d..57ac80cda 100644 --- a/Library/Phalcon/Http/Client/Header.php +++ b/Library/Phalcon/Http/Client/Header.php @@ -21,10 +21,15 @@ use Phalcon\Http\Response\StatusCode; +/** + * Phalcon\Http\Client\Header + * + * @package Phalcon\Http\Client + */ class Header implements \Countable { private $fields = []; - public $version = '1.0.1'; + public $version = '1.0.2'; public $statusCode = 0; public $statusMessage = ''; public $status = ''; @@ -77,11 +82,19 @@ public function addMultiple(array $fields) /** * @param string $name + * @param mixed $default + * * @return mixed */ - public function get($name) + public function get($name, $default = null) { - return $this->fields[$name]; + foreach ($this->fields as $key => $value) { + if (strcmp(strtolower($key), strtolower($name)) === 0) { + return $value; + } + } + + return $default; } /** @@ -101,8 +114,8 @@ public function getAll() */ public function has($name) { - foreach ($this->getAll() as $key => $value) { - if (0 === strcmp(strtolower($key), strtolower($name))) { + foreach ($this->fields as $key => $value) { + if (strcmp(strtolower($key), strtolower($name)) === 0) { return true; } } diff --git a/Library/Phalcon/Http/Client/Provider/Curl.php b/Library/Phalcon/Http/Client/Provider/Curl.php index baf506c99..d54bff07f 100644 --- a/Library/Phalcon/Http/Client/Provider/Curl.php +++ b/Library/Phalcon/Http/Client/Provider/Curl.php @@ -143,6 +143,10 @@ protected function send(array $customHeader = [], $fullResponse = false) $this->setOption(CURLOPT_HEADERFUNCTION, [$this, 'headerFunction']); $this->setOption(CURLOPT_HTTPHEADER, $header); + if ($fullResponse) { + $this->setOption(CURLOPT_HEADER, true); + } + $content = curl_exec($this->handle); $this->setOption(CURLOPT_HEADERFUNCTION, null); @@ -154,11 +158,7 @@ protected function send(array $customHeader = [], $fullResponse = false) $response = new Response(); $response->header->parse($this->responseHeader); - if ($fullResponse) { - $response->body = $content; - } else { - $response->body = substr($content, strlen($this->responseHeader)); - } + $response->body = $content; return $response; } @@ -175,7 +175,7 @@ protected function initPostFields($params, $useEncoding = true) { if (is_array($params)) { foreach ($params as $param) { - if (is_string($param) && preg_match('/^@/', $param)) { + if (is_string($param) && strpos($param, '@') === 0) { $useEncoding = false; break; } diff --git a/Library/Phalcon/Mvc/MongoCollection.php b/Library/Phalcon/Mvc/MongoCollection.php index e5af25242..d32119546 100644 --- a/Library/Phalcon/Mvc/MongoCollection.php +++ b/Library/Phalcon/Mvc/MongoCollection.php @@ -21,9 +21,11 @@ use Phalcon\Di; use MongoDB\BSON\ObjectID; +use MongoDB\Driver\WriteConcern; use MongoDB\BSON\Unserializable; use Phalcon\Mvc\Collection\Document; use Phalcon\Mvc\Collection\Exception; +use Phalcon\Db\Adapter\MongoDB\InsertOneResult; use Phalcon\Mvc\Collection as PhalconCollection; use Phalcon\Db\Adapter\MongoDB\Collection as AdapterCollection; @@ -40,29 +42,31 @@ abstract class MongoCollection extends PhalconCollection implements Unserializab // @codingStandardsIgnoreEnd /** - * Sets a value for the _id property, creates a MongoId object if needed + * {@inheritdoc} * * @param mixed $id */ public function setId($id) { - $mongoId = null; - if (is_object($id)) { - $mongoId = $id; - } else { - if ($this->_modelsManager->isUsingImplicitObjectIds($this)) { - $mongoId = new ObjectID($id); - } else { - $mongoId = $id; - } + $this->_id = $id; + return; + } + + if ($this->_modelsManager->isUsingImplicitObjectIds($this)) { + $this->_id = new ObjectID($id); + return; } - $this->_id = $mongoId; + $this->_id = $id; } /** - * Creates/Updates a collection based on the values in the attributes + * {@inheritdoc} + * + * @return bool + * + * @throws Exception */ public function save() { @@ -70,7 +74,7 @@ public function save() if (!is_object($dependencyInjector)) { throw new Exception( - "A dependency injector container is required to obtain the services related to the ORM" + "A dependency injector container is required to obtain the services related to the ODM" ); } @@ -122,7 +126,7 @@ public function save() break; default: - throw new Exception('Invalid operation requested for MongoCollection->save()'); + throw new Exception('Invalid operation requested for ' . __METHOD__); } $success = false; @@ -141,6 +145,13 @@ public function save() return $this->_postSave($disableEvents, $success, $exists); } + /** + * {@inheritdoc} + * + * @param mixed $id + * + * @return array + */ public static function findById($id) { if (!is_object($id)) { @@ -160,6 +171,12 @@ public static function findById($id) return static::findFirst([["_id" => $mongoId]]); } + /** + * {@inheritdoc} + * + * @param array|null $parameters + * @return array + */ public static function findFirst(array $parameters = null) { $className = get_called_class(); @@ -173,6 +190,8 @@ public static function findFirst(array $parameters = null) } /** + * {@inheritdoc} + * * @param array $params * @param CollectionInterface $collection * @param \MongoDb $connection @@ -180,13 +199,12 @@ public static function findFirst(array $parameters = null) * * @return array * @throws Exception + * @codingStandardsIgnoreStart */ - // @codingStandardsIgnoreStart protected static function _getResultset($params, CollectionInterface $collection, $connection, $unique) { - // @codingStandardsIgnoreEnd - /** + * @codingStandardsIgnoreEnd * Check if "class" clause was defined */ if (isset($params['class'])) { @@ -196,8 +214,12 @@ protected static function _getResultset($params, CollectionInterface $collection if (!$base instanceof CollectionInterface || $base instanceof Document) { throw new Exception( - "Object of class '".$classname."' must be an implementation of - Phalcon\\Mvc\\CollectionInterface or an instance of Phalcon\\Mvc\\Collection\\Document" + sprintf( + 'Object of class "%s" must be an implementation of %s or an instance of %s', + get_class($classname), + CollectionInterface::class, + Document::class + ) ); } } else { @@ -304,7 +326,7 @@ protected static function _getResultset($params, CollectionInterface $collection } /** - * Deletes a model instance. Returning true on success or false otherwise. + * {@inheritdoc} * * * $robot = Robots::findFirst(); @@ -374,17 +396,15 @@ public function delete() } /** - * Checks if the document exists in the collection - * - * @param \MongoCollection collection + * {@inheritdoc} * + * @param \MongoCollection $collection * @return boolean + * @codingStandardsIgnoreStart */ - // @codingStandardsIgnoreStart protected function _exists($collection) { // @codingStandardsIgnoreStart - if (!$id = $this->_id) { return false; } @@ -409,7 +429,7 @@ protected function _exists($collection) } /** - * Fires an internal event that cancels the operation + * {@inheritdoc} * * @param string $eventName * @return bool @@ -435,13 +455,69 @@ public function fireEventCancel($eventName) return true; } + /** + * {@inheritdoc} + * + * @todo + * @param string $field + * @param null $conditions + * @param null $finalize + * + * @throws Exception + */ public static function summatory($field, $conditions = null, $finalize = null) { throw new Exception('The summatory() method is not implemented in the new Mvc MongoCollection'); } /** - * Pass the values from the BSON document back to the object. + * {@inheritdoc} + * + * @return bool + */ + public function create() + { + /** @var \Phalcon\Db\Adapter\MongoDB\Collection $collection */ + $collection = $this->prepareCU(); + + /** + * Check the dirty state of the current operation to update the current operation + */ + $this->_operationMade = self::OP_CREATE; + + /** + * The messages added to the validator are reset here + */ + $this->_errorMessages = []; + + /** + * Execute the preSave hook + */ + if ($this->_preSave($this->_dependencyInjector, self::$_disableEvents, false) === false) { + return false; + } + + $data = $this->toArray(); + $success = false; + + /** + * We always use safe stores to get the success state + * Save the document + */ + $result = $collection->insert($data, ['writeConcern' => new WriteConcern(1)]); + if ($result instanceof InsertOneResult && $result->getInsertedId()) { + $success = true; + $this->_id = $result->getInsertedId(); + } + + /** + * Call the postSave hooks + */ + return $this->_postSave(self::$_disableEvents, $success, false); + } + + /** + * {@inheritdoc} * * @param array $data */ diff --git a/Library/Phalcon/Traits/ConfigurableTrait.php b/Library/Phalcon/Traits/ConfigurableTrait.php new file mode 100644 index 000000000..353e98fbc --- /dev/null +++ b/Library/Phalcon/Traits/ConfigurableTrait.php @@ -0,0 +1,68 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Traits; + +use Traversable; +use InvalidArgumentException; + +/** + * Phalcon\Traits\ConfigurableTrait + * + * Allows to define parameters which can be set by passing them to the class constructor. + * These parameters should be defined in the `$configurable` array. + * + * @property array $configurable + * @package Phalcon\Traits + */ +trait ConfigurableTrait +{ + /** + * Sets the parameters. + * + * @param Traversable|array $parameters + * @return $this + * + * @throws InvalidArgumentException + */ + protected function setParameters($parameters) + { + if (!property_exists($this, 'configurable') || !is_array($this->configurable)) { + return $this; + } + + if (!is_array($parameters) && !($parameters instanceof Traversable)) { + throw new InvalidArgumentException('The $parameters argument must be either an array or Traversable'); + } + + foreach ($parameters as $key => $value) { + if (!in_array($key, $this->configurable, true)) { + continue; + } + + $method = 'set' . ucfirst($key); + + if (method_exists($this, $method)) { + $this->$method($value); + } + } + + return $this; + } +} diff --git a/Library/Phalcon/Traits/README.md b/Library/Phalcon/Traits/README.md new file mode 100644 index 000000000..e86469955 --- /dev/null +++ b/Library/Phalcon/Traits/README.md @@ -0,0 +1,41 @@ +# Phalcon\Traits + +Here is a collection of Traits that are often used or can be useful in everyday Phalcongelist life. + +## Phalcon\Traits\ConfigurableTrait + +Allows to define parameters which can be set by passing them to the class constructor. +These parameters should be defined in the `$configurable` array. + +```php +use Phalcon\Traits\ConfigurableTrait; + +class MyAdapter +{ + use ConfigurableTrait; + + protected $host; + protected $viewsDir; + protected $protectedParameter; + + protected $configurable = [ + 'host', + 'viewsDir' + ]; + + public function __construct(array $options) + { + $this->setConfig($config); + } + + protected function setHost($host) + { + $this->host = $host; + } + + protected function setViewsDir($viewsDir) + { + $this->viewsDir = $viewsDir; + } +} +``` diff --git a/Library/Phalcon/Translate/Adapter/Mongo.php b/Library/Phalcon/Translate/Adapter/Mongo.php new file mode 100644 index 000000000..9bd1e5e13 --- /dev/null +++ b/Library/Phalcon/Translate/Adapter/Mongo.php @@ -0,0 +1,218 @@ + | + +------------------------------------------------------------------------+ +*/ + +namespace Phalcon\Translate\Adapter; + +use Phalcon\Translate\Exception; +use Phalcon\Mvc\CollectionInterface; +use Phalcon\Translate\AdapterInterface; + +/** + * Phalcon\Translate\Adapter\Mongo + * + * Implements a mongo adapter for translations. + * + * A generic collection with a source to store the translations must be created + * and passed as a parameter. + * + * @package Phalcon\Translate\Adapter + */ +class Mongo extends Base implements AdapterInterface, \ArrayAccess +{ + protected $language; + protected $collection; + protected $formatter; + + /** + * Mongo constructor. + * + * @param array $options + * + * @throws Exception + */ + public function __construct($options) + { + if (!isset($options['collection'])) { + throw new Exception("Parameter 'collection' is required"); + } + + $this->setCollection($options['collection']); + + if (!isset($options['language'])) { + throw new Exception("Parameter 'language' is required"); + } + + $this->setLanguage($options['language']); + + if (isset($options['formatter'])) { + $this->setFormatter($options['formatter']); + } + } + + /** + * Sets the collection object. + * + * @param CollectionInterface|string $collection Translations collection class to use. + * Can be an instance of CollectionInterface or a string. + */ + protected function setCollection($collection) + { + $this->collection = $collection; + } + + /** + * Sets the language to use. + * + * @param string $language + */ + protected function setLanguage($language) + { + $this->language = $language; + } + + /** + * Sets the formatter to use if necessary. + * + * @param \MessageFormatter $formatter Message formatter. + */ + protected function setFormatter(\MessageFormatter $formatter) + { + $this->formatter = $formatter; + } + + /** + * Gets the translations set. + * + * @param string $translateKey + * Key of the collection set. + * + * @return mixed + */ + protected function getTranslations($translateKey) + { + /** @var CollectionInterface $collection */ + $collection = $this->collection; + + return $collection::findFirst([['key' => $translateKey]]); + } + + /** + * {@inheritDoc} + */ + public function _($translateKey, $placeholders = null) + { + return $this->query($translateKey, $placeholders); + } + + /** + * {@inheritDoc} + */ + public function query($translateKey, $placeholders = null) + { + $translations = $this->getTranslations($translateKey); + $translation = $translateKey; + + if (isset($translations->{$this->language})) { + $translation = $translations->{$this->language}; + } + + if (!empty($placeholders)) { + return $this->format($translation, $placeholders); + } + + return $translation; + } + + /** + * Formats a translation. + * + * @param string $translation Translated text. + * @param array $placeholders Placeholders to apply. + * + * @return string + */ + protected function format($translation, $placeholders = []) + { + if ($this->formatter) { + $formatter = $this->formatter; + + return $formatter::formatMessage($this->language, $translation, $placeholders); + } + + foreach ($placeholders as $key => $value) { + $translation = str_replace("%$key%", $value, $translation); + } + + return $translation; + } + + /** + * {@inheritDoc} + */ + public function exists($translateKey) + { + $translations = $this->getTranslations($translateKey); + + return isset($translations->{$this->language}); + } + + /** + * {@inheritDoc} + */ + public function offsetExists($translateKey) + { + return $this->exists($translateKey); + } + + /** + * {@inheritDoc} + */ + public function offsetSet($translateKey, $message) + { + $translations = $this->getTranslations($translateKey); + $translations->{$this->language} = $message; + + return $translations->save(); + } + + /** + * {@inheritDoc} + */ + public function offsetGet($translateKey) + { + $translations = $this->getTranslations($translateKey); + + if (isset($translations->{$this->language})) { + return $translations->{$this->language}; + } + + return ''; + } + + /** + * {@inheritDoc} + */ + public function offsetUnset($translateKey) + { + $translations = $this->getTranslations($translateKey); + unset($translations->{$this->language}); + + return $translations->save(); + } +} diff --git a/Library/Phalcon/Translate/Adapter/README.md b/Library/Phalcon/Translate/Adapter/README.md index 55679fc7d..83c3609d0 100644 --- a/Library/Phalcon/Translate/Adapter/README.md +++ b/Library/Phalcon/Translate/Adapter/README.md @@ -9,28 +9,28 @@ You can use your database to store the translations, too. First of all, you need to up your database. To do this, use [DI][1] (in `/public/index.php`). Take a look: ```php -// ... +use Phalcon\Db\Adapter\Pdo\Mysql; $di->set('db', function() { - return new \Phalcon\Db\Adapter\Pdo\Mysql([ + return new Mysql([ 'host' => 'localhost', 'username' => 'root', 'password' => 123456, 'dbname' => 'application' ]); }); - -// ... ``` Then, you should get the translation through your `controller`. Put this on it: ```php +use Phalcon\Translate\Adapter\Database; + class IndexController extends \Phalcon\Mvc\Controller { protected function _getTranslation() { - return new Phalcon\Translate\Adapter\Database([ + return new Database([ 'db' => $this->di->get('db'), // Here we're getting the database from DI 'table' => 'translations', // The table that is storing the translations 'language' => $this->request->getBestLanguage(), // Now we're getting the best language for the user @@ -82,7 +82,7 @@ class IndexController extends \Phalcon\Mvc\Controller Then, just output the`phrase/sentence/word` in your view: -```html+php +```php @@ -94,7 +94,7 @@ Then, just output the`phrase/sentence/word` in your view: ``` Or, if you wish you can use [Volt][2]: -```html+php +```php

{{ expression._("IndexPage_Hello_World") }}

``` @@ -106,6 +106,32 @@ ICU MessageFormatter Example $this->_getTranslation()->_('cats', ['nbCats' => rand(0, 10)]); ``` +## Mongo + +Implements a Mongo adapter for translations. + +A generic collection with a source to store the translations must be created and passed as a parameter. + +```php +use MessageFormatter; +use Phalcon\Translate\Adapter\Mongo; +use My\Application\Collections\Translate; + +$fmt = new MessageFormatter( + "en_US", + "{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree" +); + +$translate = new Mongo([ + 'collection' => Translate::class, + 'language' => 'en', + 'formatter' => $fmt, +]); + +echo $translate->t('application.title'); +``` + + ## ResourceBundle This adapter uses ResourceBundle as translation frontend. @@ -113,7 +139,9 @@ This adapter uses ResourceBundle as translation frontend. The extension [intl][3] must be installed in PHP. ```php -$translate = new Phalcon\Translate\Adapter\ResourceBundle([ +use Phalcon\Translate\Adapter\ResourceBundle; + +$translate = new ResourceBundle([ 'bundle' => '/path/to/bundle', // required 'locale' => 'en', // required 'fallback' => false // optional, default - true diff --git a/README.md b/README.md index 6423fe0a1..98188212f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ +# Phalcon Incubator + [![Build Status](https://img.shields.io/travis/phalcon/incubator/master.svg?style=flat-square)](https://travis-ci.org/phalcon/incubator) [![Latest Version](https://img.shields.io/packagist/v/phalcon/incubator.svg?style=flat-square)](https://github.com/phalcon/incubator/releases) -[![Software License](https://img.shields.io/badge/license-BSD--3-brightgreen.svg?style=flat-square)](docs/LICENSE.md) +[![Software License](https://img.shields.io/badge/license-BSD--3-brightgreen.svg?style=flat-square)](https://github.com/phalcon/incubator/blob/master/LICENSE.txt) [![Total Downloads](https://img.shields.io/packagist/dt/phalcon/incubator.svg?style=flat-square)](https://packagist.org/packages/phalcon/incubator) [![Daily Downloads](https://img.shields.io/packagist/dd/phalcon/incubator.svg?style=flat-square)](https://packagist.org/packages/phalcon/incubator) -# Phalcon Incubator - Phalcon is a web framework delivered as a C extension providing high performance and lower resource consumption. This is a repository to publish/share/experiment with new adapters, prototypes or functionality that can potentially be incorporated into the framework. @@ -29,7 +29,7 @@ Then create the `composer.json` file as follows: ```json { "require": { - "phalcon/incubator": "~3.0" + "phalcon/incubator": "^3.0" } } ``` @@ -81,10 +81,6 @@ $loader->registerNamespaces([ $loader->register(); ``` -## Testing - -See [TESTING.md](TESTING.md) - # Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) @@ -101,6 +97,9 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) * [Phalcon\Annotations\Adapter\Memcached](Library/Phalcon/Annotations/Adapter) - Memcached adapter for storing annotations (@igusev) * [Phalcon\Annotations\Adapter\Redis](Library/Phalcon/Annotations/Adapter) - Redis adapter for storing annotations (@sergeyklay) * [Phalcon\Annotations\Adapter\Aerospike](Library/Phalcon/Annotations/Adapter) - Aerospike adapter for storing annotations (@sergeyklay) +* [Phalcon\Annotations\Extended\Adapter\Apc](Library/Phalcon/Annotations/Extended/Adapter) - Extended Apc adapter for storing annotations in the APC(u) (@sergeyklay) +* [Phalcon\Annotations\Extended\Adapter\Memory](Library/Phalcon/Annotations/Extended/Adapter) - Extended Memory adapter for storing annotations in the memory (@sergeyklay) +* [Phalcon\Annotations\Extended\Adapter\Files](Library/Phalcon/Annotations/Extended/Adapter) - Extended Files adapter for storing annotations in files (@sergeyklay) ### Behaviors * [Phalcon\Mvc\Model\Behavior\Blameable](Library/Phalcon/Mvc/Model/Behavior) - logs with every created or updated row in your database who created and who updated it (@phalcon) @@ -171,6 +170,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) ### Translate * [Phalcon\Translate\Adapter\Database](Library/Phalcon/Translate/Adapter) - Translation adapter using relational databases (@phalcon) +* [Phalcon\Translate\Adapter\Mongo](Library/Phalcon/Translate/Adapter) - Implements a Mongo adapter for translations (@gguridi) * [Phalcon\Translate\Adapter\ResourceBundle](Library/Phalcon/Translate/Adapter) - Translation adapter using ResourceBundle (@phalcon) ### Session @@ -191,7 +191,11 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) * [Phalcon\Validation\Validator\MongoId](Library/Phalcon/Validation/Validator) - Validate MongoId value (@Kachit) * [Phalcon\Validation\Validator\PasswordStrength](Library/Phalcon/Validation/Validator) - Validates password strength (@davihu) +### Traits + +* [Phalcon\Traits\ConfigurableTrait](Library/Phalcon/Traits) - Allows to define parameters which can be set by passing them to the class constructor (@sergeyklay) + ## License -Incubator is open-sourced software licensed under the [New BSD License](LICENSE.txt).
+Incubator is open-sourced software licensed under the [New BSD License](https://github.com/phalcon/incubator/blob/master/LICENSE.txt).
© 2011-2016, Phalcon Framework Team diff --git a/TESTING.md b/TESTING.md deleted file mode 100644 index 280f72351..000000000 --- a/TESTING.md +++ /dev/null @@ -1,63 +0,0 @@ -# Phalcon Incubator Testing - -Thanks for reading this page, [test](tests) folder includes all the unit tests -we used to be sure that Phalcon Incubator will run properly and have a stable state. - -For testing Incubator you don't need take care of any dependencies. You don't need to install any -additional software which is used in Incubator, compile Phalcon, install Zephir, etc. -You don't need keep in mind database credentials, all necessary extensions, versions, environment variables, -and so on any more. - -You can easily test Incubator on any PC. Aiming to be on edge, we reworked the testing process and -decided to introduce only two dependencies, [Docker][1] and [Docker Compose][2], instead of a vast number of them. - -All you need for testing is: - -* [Docker][1] >= 1.10 -* [Docker Compose][2] >= 1.6.2 - -Phalcon Incubator uses [Codeception][3] which can be installed using Composer: - -```sh -# run this command from project root -$ composer install --dev --prefer-source -``` - -You have to export few variables: -```sh -export TRAVIS_PHP_VERSION=5.6 # PHP version you want to use -export PHALCON_SRC_PATH=/home/user/src/phalcon # Path to the cphalcon source -``` - -After you have installed all necessary dependencies use these two commands: - -```sh -# Create and run containers in background -docker-compose -p incubator up -d - -# run test -bash tests/build.sh - -# run particular test -bash tests/build.sh tests/unit/Annotations/Adapter/RedisTest.php -``` - -In addition to the obvious advantage related to reduction in the number of dependencies, this approach allows you to -run tests immediately by using the service [Travis CI][4]. - -## The testing process - -Incubator is built under [Travis CI][4] service. -Every commit pushed to this repository will queue a build into the continuous integration service and will run all tests -to ensure that everything is going well and the project is stable. - -## MongoDB - -Tests for the new MongoCollection include the functions `save()` `delete()` `find()` `findFirst()` `findById()` and `aggregate()` functions. - -Tests still need to be written to incorporate the Validation, Behaviours and Events functionality. - -[1]: https://docs.docker.com/ -[2]: https://docs.docker.com/compose/ -[3]: http://codeception.com/ -[4]: https://travis-ci.org/ diff --git a/codeception.yml b/codeception.yml index b5aaae614..dcf1bbf3d 100644 --- a/codeception.yml +++ b/codeception.yml @@ -30,3 +30,9 @@ coverage: extensions: enabled: - Codeception\Extension\RunFailed + +# Get params from .env file +params: + - tests/.env + +error_level: "E_ALL" diff --git a/composer.json b/composer.json index c2cb125a6..88dd39715 100644 --- a/composer.json +++ b/composer.json @@ -27,14 +27,16 @@ "swiftmailer/swiftmailer": "~5.2" }, "require-dev": { - "phpdocumentor/reflection-docblock": "^2.0.4", - "phpunit/phpunit": "4.8.*", - "squizlabs/php_codesniffer": "~2.6", - "codeception/codeception": "~2.2", - "codeception/mockery-module": "~0.2", - "codeception/aerospike-module": "~1.0", - "codeception/specify": "~0.4", - "codeception/verify": "~0.3" + "phpdocumentor/reflection-docblock": "2.0.4", + "phpunit/phpunit": "^4.8", + "squizlabs/php_codesniffer": "^2.7", + "codeception/codeception": "^2.2", + "codeception/mockery-module": "^0.2", + "codeception/aerospike-module": "^1.0", + "codeception/specify": "^0.4", + "codeception/verify": "^0.3", + "vlucas/phpdotenv": "^2.4", + "phalcongelist/dd": "^1.0" }, "suggest": { "ext-aerospike": "*", @@ -50,6 +52,9 @@ "psr-4": { "Phalcon\\Test\\": "tests/unit/", "Phalcon\\Test\\Collections\\": "tests/_data/collections" - } + }, + "files": [ + "tests/_support/functions.php" + ] } } diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 41906bfe0..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -version: '2' - -services: - redis: - restart: always - image: redis:3.2 - container_name: incubator_redis - expose: - - "6379" - ports: - - "6379:6379" - - mysql: - restart: always - image: mysql:5.7 - container_name: incubator_mysql - expose: - - "3306" - ports: - - "3306:3306" - environment: - MYSQL_DATABASE: incubator_tests - MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' - - memcached: - restart: always - image: memcached:1.4 - container_name: incubator_memcached - ports: - - "11211:11211" - - queue: - restart: always - image: phalconphp/beanstalkd:1.10 - container_name: incubator_beanstalkd - ports: - - "11302:11302" - - aerospike: - restart: always - image: aerospike:3.10.1 - container_name: incubator_aerospike - expose: - - "3000" - - "3001" - - "3002" - - "3003" - ports: - - "3000:3000" - - "3001:3001" - - "3002:3002" - - "3003:3003" - - mongodb: - restart: always - image: mongo:latest - container_name: incubator_mongo - expose: - - "27017" - ports: - - "27017:27017" diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 000000000..f7582ce68 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,31 @@ + + + + + + Phalcon Incubator Coding Standards + + + + + + + + + + + + Library + diff --git a/tests/.env b/tests/.env new file mode 100644 index 000000000..74d9c0b65 --- /dev/null +++ b/tests/.env @@ -0,0 +1,25 @@ +TEST_MC_HOST=127.0.0.1 +TEST_MC_PORT=11211 + +TEST_RS_HOST=127.0.0.1 +TEST_RS_PORT=6379 + +TEST_BT_HOST=127.0.0.1 +TEST_BT_PORT=11300 + +TEST_AS_HOST=127.0.0.1 +TEST_AS_PORT=3000 +TEST_AS_SET=cache +TEST_AS_NS=test + +TEST_DB_DSN=mysql:dbname=incubator;host=127.0.0.1;port=3306 +TEST_DB_HOST=127.0.0.1 +TEST_DB_PORT=3306 +TEST_DB_USER=incubator +TEST_DB_PASSWD=secret +TEST_DB_NAME=incubator +TEST_DB_CHARSET=utf8 + +TEST_MONGODB_HOST=127.0.0.1 +TEST_MONGODB_PORT=27017 +TEST_MONGODB_NAME=incubator diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index bc4c4e981..6f68e8997 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -1,19 +1,18 @@ load(); + +require_once '_support/functions.php'; + error_reporting(-1); + ini_set('display_errors', 1); ini_set('display_startup_errors', 1); setlocale(LC_ALL, 'en_US.utf-8'); -if (function_exists('mb_internal_encoding')) { - mb_internal_encoding('utf-8'); -} - -if (function_exists('mb_substitute_character')) { - mb_substitute_character('none'); -} - if (extension_loaded('xdebug')) { ini_set('xdebug.cli_color', 1); ini_set('xdebug.collect_params', 0); @@ -27,37 +26,11 @@ $root = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR; -defined('TESTS_PATH') || define('TESTS_PATH', $root); -defined('PROJECT_PATH') || define('PROJECT_PATH', dirname(TESTS_PATH) . DIRECTORY_SEPARATOR); -defined('PATH_DATA') || define('PATH_DATA', $root . '_data' . DIRECTORY_SEPARATOR); -defined('PATH_CACHE') || define('PATH_CACHE', $root . '_cache' . DIRECTORY_SEPARATOR); -defined('PATH_OUTPUT') || define('PATH_OUTPUT', $root . '_output' . DIRECTORY_SEPARATOR); -defined('INCUBATOR_FIXTURES') || define('INCUBATOR_FIXTURES', $root . '_fixtures' . DIRECTORY_SEPARATOR); - -// Memcached -define('TEST_MC_HOST', getenv('TEST_MC_HOST') ?: 'memcached'); -define('TEST_MC_PORT', getenv('TEST_MC_PORT') ?: 11211); - -// Redis -define('TEST_RS_HOST', getenv('TEST_RS_HOST') ?: 'redis'); -define('TEST_RS_PORT', getenv('TEST_RS_PORT') ?: 6379); - -// Beanstalk -define('TEST_BT_HOST', getenv('TEST_BT_HOST') ?: 'queue'); -define('TEST_BT_PORT', getenv('TEST_BT_PORT') ?: 11300); - -// Aerospike -define('TEST_AS_HOST', getenv('TEST_AS_HOST') ?: 'aerospike'); -define('TEST_AS_PORT', getenv('TEST_AS_PORT') ?: 3000); - -// MySQL -define('TEST_DB_HOST', getenv('TEST_DB_HOST') ?: 'mysql'); -define('TEST_DB_PORT', getenv('TEST_DB_PORT') ?: 3306); -define('TEST_DB_USER', getenv('TEST_DB_USER') ?: 'root'); -define('TEST_DB_PASSWD', getenv('TEST_DB_PASSWD') ?: ''); -define('TEST_DB_NAME', getenv('TEST_DB_NAME') ?: 'incubator_tests'); -define('TEST_DB_CHARSET', getenv('TEST_DB_CHARSET') ?: 'utf8'); - -// MongoDB -define('TEST_MONGODB_HOST', getenv('TEST_MONGODB_HOST') ?: 'mongodb' ); -define('TEST_MONGODB_PORT', getenv('TEST_MONGODB_PORT') ?: '27017' ); \ No newline at end of file +define('TESTS_PATH', $root); +define('PROJECT_PATH', dirname(TESTS_PATH) . DIRECTORY_SEPARATOR); +define('PATH_DATA', $root . '_data' . DIRECTORY_SEPARATOR); +define('PATH_CACHE', $root . '_cache' . DIRECTORY_SEPARATOR); +define('PATH_OUTPUT', $root . '_output' . DIRECTORY_SEPARATOR); +define('INCUBATOR_FIXTURES', $root . '_fixtures' . DIRECTORY_SEPARATOR); + +unset($root); diff --git a/tests/_ci/.gitignore b/tests/_ci/.gitignore deleted file mode 100644 index b6fe20009..000000000 --- a/tests/_ci/.gitignore +++ /dev/null @@ -1 +0,0 @@ -phalcon.so diff --git a/tests/_ci/aerospike.ini b/tests/_ci/aerospike.ini new file mode 100644 index 000000000..d3fa7aafd --- /dev/null +++ b/tests/_ci/aerospike.ini @@ -0,0 +1,3 @@ +extension=aerospike.so +aerospike.udf.lua_system_path=/usr/local/aerospike/lua +aerospike.udf.lua_user_path=/usr/local/aerospike/usr-lua diff --git a/tests/_ci/apc_bc.ini b/tests/_ci/apc_bc.ini new file mode 100644 index 000000000..6f0dcf505 --- /dev/null +++ b/tests/_ci/apc_bc.ini @@ -0,0 +1,15 @@ +; See https://pear.php.net/bugs/bug.php?id=21007 + +[APCu] +extension=apcu.so + +[APC] +extension=apc.so +apc.enabled=1 +apc.enable_cli=1 + +; If the system is flooded with i/o and some update procedures are taking longer than 2 seconds, +; this setting should be increased to enable the protection on those slower update operations. +apc.file_update_protection=0 + +; apc.cache_by_default=0 diff --git a/tests/_ci/entrypoint.sh b/tests/_ci/entrypoint.sh deleted file mode 100755 index fa506f3dd..000000000 --- a/tests/_ci/entrypoint.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -# -# Phalcon Framework -# -# Copyright (c) 2016 Phalcon Team (http://www.phalconphp.com) -# -# This source file is subject to the New BSD License that is bundled -# with this package in the file LICENSE.txt. -# -# If you did not receive a copy of the license and are unable to -# obtain it through the world-wide-web, please send an email -# to license@phalconphp.com so we can send you a copy immediately. -# -# Authors: Serghei Iakovlev - -PURPLE="\e[0;35m" -GREEN="\033[0;32m" -YELLOW="\e[1;33m" -NC="\033[0m" - -echo -e "\nWelcome to the Docker testing container." - -PHP_EXTENSION_DIR=`php-config --extension-dir` -echo -e "PHP extension path: ${PURPLE}${PHP_EXTENSION_DIR}${NC}\n" - -ln -sf /ext/phalcon.so ${PHP_EXTENSION_DIR}/phalcon.so - -rm -f /etc/php/${TRAVIS_PHP_VERSION}/cli/conf.d/50-phalcon.ini -rm -f /etc/php/${TRAVIS_PHP_VERSION}/cli/conf.d/20-phalcon.ini - -ln -s /app/tests/_ci/phalcon.ini /etc/php/${TRAVIS_PHP_VERSION}/cli/conf.d/50-phalcon.ini - -PHP_FULL_VERSION=`php -r 'echo phpversion();'` -PHALCON_VERSION=`php --ri phalcon | grep "Version =" | awk '{print $3}'` - -echo -e "${GREEN}PHP${NC} version ${YELLOW}${TRAVIS_PHP_VERSION}${NC} (${PHP_FULL_VERSION})" -echo -e "${GREEN}Phalcon${NC} version ${YELLOW}${PHALCON_VERSION}${NC}" -/app/vendor/bin/codecept --version - -/app/vendor/bin/codecept build &> /dev/null - -echo -e "" -/app/vendor/bin/phpcs --standard=PSR2 --colors --extensions=php --encoding=utf-8 Library/ -result_phpcs=$? - -/app/vendor/bin/codecept run -- "${RUN_ARGS}" -result_codecept=$? - -if [ ${result_codecept} -ne 0 -o ${result_phpcs} -ne 0 ]; -then - exit 1; -fi - -exit 0 - diff --git a/tests/_ci/install_aerospike.sh b/tests/_ci/install_aerospike.sh new file mode 100755 index 000000000..3f06ac18b --- /dev/null +++ b/tests/_ci/install_aerospike.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" +PHP_CONFIG_OUTPUT=$(php-config) +DOWNLOAD_PHP_UNIT= + +mkdir -p /tmp/aerospike-ext + +sudo mkdir -p /usr/local/aerospike/{lua,usr-lua} +sudo chmod -R ugoa+rwx /usr/local/aerospike + +ln -sf /usr/lib/x86_64-linux-gnu/libcrypto.so /usr/local/lib/libcrypto.so +ln -sf /usr/lib/x86_64-linux-gnu/libcrypto.a /usr/local/lib/libcrypto.a + +cd /tmp/aerospike-ext +wget -O aerospike.zip https://github.com/aerospike/aerospike-client-php/archive/master.zip +unzip aerospike.zip -x "aerospike-client-php-master/doc/*" -x "aerospike-client-php-master/examples/*" -x "aerospike-client-php-master/src/aerospike/tests/*" + +mkdir -p aerospike-client-php-master/src/aerospike/tests/ +cd aerospike-client-php-master/src/aerospike + +./build.sh --loglevel OFF > /dev/null 2>&1 +make --silent install + +find . -type f -name aerospike.so | xargs sudo cp -t $(php-config --extension-dir) +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/aerospike.ini + +cd ${TRAVIS_BUILD_DIR} diff --git a/tests/_ci/install_aserver.sh b/tests/_ci/install_aserver.sh new file mode 100755 index 000000000..eba92ff6d --- /dev/null +++ b/tests/_ci/install_aserver.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" + +wget -O aerospike.tgz "http://aerospike.com/download/server/latest/artifact/ubuntu12" +tar -xvf aerospike.tgz +cd aerospike-server-community-*-ubuntu12* + +sudo ./asinstall > /dev/null 2>&1 +sudo service aerospike start > /dev/null 2>&1 & + +mv ${TRAVIS_BUILD_DIR}/tests/unit.suite.5.yml ${TRAVIS_BUILD_DIR}/tests/unit.suite.yml + +cd ${TRAVIS_BUILD_DIR} diff --git a/tests/_ci/install_prereqs_5.5.sh b/tests/_ci/install_prereqs_5.5.sh new file mode 100755 index 000000000..7976782e9 --- /dev/null +++ b/tests/_ci/install_prereqs_5.5.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" + +pecl channel-update pecl.php.net + +printf "\n" | pecl install apcu-4.0.11 &> /dev/null + +echo "apc.enable_cli=On" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + +printf "\n" | pecl install yaml > /dev/null 2>&1 + +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/redis.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/mongo.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/mongodb.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/memcached.ini diff --git a/tests/_ci/install_prereqs_5.6.sh b/tests/_ci/install_prereqs_5.6.sh new file mode 100755 index 000000000..7976782e9 --- /dev/null +++ b/tests/_ci/install_prereqs_5.6.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" + +pecl channel-update pecl.php.net + +printf "\n" | pecl install apcu-4.0.11 &> /dev/null + +echo "apc.enable_cli=On" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + +printf "\n" | pecl install yaml > /dev/null 2>&1 + +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/redis.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/mongo.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/mongodb.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/memcached.ini diff --git a/tests/_ci/install_prereqs_7.0.sh b/tests/_ci/install_prereqs_7.0.sh new file mode 100755 index 000000000..d604e41a1 --- /dev/null +++ b/tests/_ci/install_prereqs_7.0.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" + +CFLAGS="-O2 -g3 -fno-strict-aliasing -std=gnu90"; + +pecl channel-update pecl.php.net + +install_apcu() { + # See https://github.com/krakjoe/apcu/issues/203 + git clone -q https://github.com/krakjoe/apcu -b v5.1.7 /tmp/apcu + cd /tmp/apcu + + phpize &> /dev/null + ./configure &> /dev/null + + make --silent -j4 &> /dev/null + make --silent install +} + +install_apcu_bc() { + git clone -q https://github.com/krakjoe/apcu-bc /tmp/apcu-bc + cd /tmp/apcu-bc + + phpize &> /dev/null + ./configure &> /dev/null + + make --silent -j4 &> /dev/null + make --silent install +} + +install_apcu +install_apcu_bc + +phpenv config-add "${TRAVIS_BUILD_DIR}/tests/_ci/apc_bc.ini" + +printf "\n" | pecl install yaml-2.0.0 >/dev/null 2>&1 + +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/redis.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/mongodb.ini +phpenv config-add ${TRAVIS_BUILD_DIR}/tests/_ci/memcached.ini diff --git a/tests/_ci/install_zephir.sh b/tests/_ci/install_zephir.sh new file mode 100755 index 000000000..960fcc6a0 --- /dev/null +++ b/tests/_ci/install_zephir.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Phalcon Framework +# +# Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +# +# This source file is subject to the New BSD License that is bundled +# with this package in the file LICENSE.txt. +# +# If you did not receive a copy of the license and are unable to +# obtain it through the world-wide-web, please send an email +# to license@phalconphp.com so we can send you a copy immediately. + +# trace ERR through pipes +set -o pipefail + +# trace ERR through 'time command' and other functions +set -o errtrace + +# set -u : exit the script if you try to use an uninitialised variable +set -o nounset + +# set -e : exit the script if any statement returns a non-true return value +set -o errexit + +CURRENT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +TRAVIS_BUILD_DIR="${TRAVIS_BUILD_DIR:-$(dirname $(dirname $CURRENT_DIR))}" +ZEPHIRDIR=${TRAVIS_BUILD_DIR}/vendor/phalcon/zephir + +if [ ! -d "${ZEPHIRDIR}" ]; then + echo -e "The ${ZEPHIRDIR} directory does not exists. First run 'composer install --dev'" + exit 1; +fi + +cd ${ZEPHIRDIR} + +sed "s#%ZEPHIRDIR%#$ZEPHIRDIR#g" bin/zephir > bin/zephir-cmd +chmod 755 bin/zephir-cmd + +mkdir -p ~/bin + +cp bin/zephir-cmd ~/bin/zephir +rm bin/zephir-cmd + +cd ${TRAVIS_BUILD_DIR} diff --git a/tests/_ci/memcached.ini b/tests/_ci/memcached.ini new file mode 100644 index 000000000..7d09664ee --- /dev/null +++ b/tests/_ci/memcached.ini @@ -0,0 +1 @@ +extension=memcached.so diff --git a/tests/_ci/mongo.ini b/tests/_ci/mongo.ini new file mode 100644 index 000000000..5998f9264 --- /dev/null +++ b/tests/_ci/mongo.ini @@ -0,0 +1 @@ +extension=mongo.so diff --git a/tests/_ci/mongodb.ini b/tests/_ci/mongodb.ini new file mode 100644 index 000000000..45969d065 --- /dev/null +++ b/tests/_ci/mongodb.ini @@ -0,0 +1 @@ +extension=mongodb.so diff --git a/tests/_ci/phalcon.ini b/tests/_ci/phalcon.ini index d611c5365..2cd8583cd 100644 --- a/tests/_ci/phalcon.ini +++ b/tests/_ci/phalcon.ini @@ -1 +1,27 @@ -extension=phalcon.so +; Phalcon Framework +; +; Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) +; +; This source file is subject to the New BSD License that is bundled +; with this package in the file LICENSE.txt +; +; If you did not receive a copy of the license and are unable to +; obtain it through the world-wide-web, please send an email +; to license@phalconphp.com so we can send you a copy immediately. + +[phalcon] +extension = phalcon.so + +; phalcon.db.escape_identifiers = On +; phalcon.db.force_casting = Off + +; phalcon.orm.events = On +; phalcon.orm.virtual_foreign_keys = On +; phalcon.orm.column_renaming = On +; phalcon.orm.not_null_validations = On +; phalcon.orm.exception_on_failed_save = Off +; phalcon.orm.enable_literals = On +; phalcon.orm.late_state_binding = Off +; phalcon.orm.enable_implicit_joins = On +; phalcon.orm.cast_on_hydrate = Off +; phalcon.orm.ignore_unknown_columns = Off diff --git a/tests/_ci/redis.ini b/tests/_ci/redis.ini new file mode 100644 index 000000000..6aecae489 --- /dev/null +++ b/tests/_ci/redis.ini @@ -0,0 +1 @@ +extension=redis.so diff --git a/tests/_ci/yaml.ini b/tests/_ci/yaml.ini new file mode 100644 index 000000000..17ca0f24b --- /dev/null +++ b/tests/_ci/yaml.ini @@ -0,0 +1 @@ +extension=yaml.ini diff --git a/tests/_data/collections/Cars.php b/tests/_data/collections/Cars.php index f3138a2ce..862f3773c 100644 --- a/tests/_data/collections/Cars.php +++ b/tests/_data/collections/Cars.php @@ -1,6 +1,25 @@ - -docker_bin="$(which docker 2> /dev/null)" - -if [ -z "${TEST_BT_HOST}" ]; then - TEST_BT_HOST="incubator_beanstalkd" -fi - -if [ -z "${TRAVIS_BUILD_DIR}" ]; then - export TRAVIS_BUILD_DIR=$(cd $(dirname "$1") && pwd -P)/$(basename "$1") -fi - -if [ -z "${TRAVIS_PHP_VERSION}" ]; then - export TRAVIS_PHP_VERSION=7.0 -fi - -if [ -z "${PHALCON_SRC_PATH}" ]; then - export PHALCON_SRC_PATH=$(cd $(dirname "$TRAVIS_BUILD_DIR") && pwd -P)/cphalcon -fi - -RUN_ARGS="$@" -shift - -function zephir() { - ${docker_bin} run -it --rm \ - --privileged=true \ - -e ZEND_DONT_UNLOAD_MODULES=1 \ - -v $(pwd):/zephir \ - phalconphp/zephir:${TRAVIS_PHP_VERSION} "$1" -} - -if [ ! -f ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.so ]; then - echo "Phalcon extension not loaded, compiling it..." - cd ${PHALCON_SRC_PATH} - - zephir "fullclean" - - [[ "${TRAVIS_PHP_VERSION}" == "7.0" ]] || zephir "builddev"; - [[ "${TRAVIS_PHP_VERSION}" != "7.0" ]] || zephir "builddev --backend=ZendEngine3"; - - if [ ! -f $(pwd)/ext/modules/phalcon.so ]; then - echo "Unable to compile Phalcon." - exit 1; - fi - - cp $(pwd)/ext/modules/phalcon.so ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.so - - cd ${TRAVIS_BUILD_DIR} -fi - -if [ ! -f ${TRAVIS_BUILD_DIR}/tests/_ci/entrypoint.sh ]; then - echo "Unable locate docker entrypoint.sh" - exit 1; -fi - -chmod +x ${TRAVIS_BUILD_DIR}/tests/_ci/entrypoint.sh - -if [ -z ${TRAVIS} ]; then - ${docker_bin} restart ${TEST_BT_HOST}; -fi - -${docker_bin} run -it --rm \ - --entrypoint /entrypoint.sh \ - --privileged=true \ - --net=incubator_default \ - -e RUN_ARGS="${RUN_ARGS}" \ - -e TEST_BT_HOST="${TEST_BT_HOST}" \ - -e TRAVIS_PHP_VERSION="${TRAVIS_PHP_VERSION}" \ - --name test-incubator-${TRAVIS_PHP_VERSION} \ - -v ${TRAVIS_BUILD_DIR}/tests/_ci/entrypoint.sh:/entrypoint.sh \ - -v ${TRAVIS_BUILD_DIR}/vendor:/app/vendor \ - -v ${TRAVIS_BUILD_DIR}/codeception.yml:/app/codeception.yml \ - -v ${TRAVIS_BUILD_DIR}/tests:/app/tests \ - -v ${TRAVIS_BUILD_DIR}/Library:/app/Library \ - -v ${TRAVIS_BUILD_DIR}/tests/_ci/phalcon.so:/ext/phalcon.so \ - phalconphp/php:${TRAVIS_PHP_VERSION} bash diff --git a/tests/unit.suite.5.yml b/tests/unit.suite.5.yml new file mode 100644 index 000000000..07d369f7f --- /dev/null +++ b/tests/unit.suite.5.yml @@ -0,0 +1,28 @@ +# Codeception Test Suite Configuration +# +# Suite for unit (internal) tests. + +class_name: UnitTester +modules: + # enabled modules and helpers + enabled: + - Helper\Unit + - Filesystem + - Aerospike + - Asserts + - Mockery + - Apc + - Db + config: + Db: + dsn: "%TEST_DB_DSN%" + user: "%TEST_DB_USER%" + password: "%TEST_DB_PASSWD%" + dump: tests/_data/dump.sql + populate: false + cleanup: false + Aerospike: + addr: "%TEST_AS_HOST%" + port: "%TEST_AS_PORT%" + set: "%TEST_AS_SET%" + namespace: "%TEST_AS_NS%" diff --git a/tests/unit.suite.yml b/tests/unit.suite.yml index 5bce2ddd4..60320e213 100644 --- a/tests/unit.suite.yml +++ b/tests/unit.suite.yml @@ -6,21 +6,17 @@ class_name: UnitTester modules: # enabled modules and helpers enabled: + - Helper\Unit + - Filesystem - Asserts - - Db - Mockery - - Helper\Unit - - Aerospike + - Apc + - Db config: Db: - dsn: 'mysql:host=mysql;dbname=incubator_tests' - user: 'root' - password: '' + dsn: "%TEST_DB_DSN%" + user: "%TEST_DB_USER%" + password: "%TEST_DB_PASSWD%" dump: tests/_data/dump.sql - populate: true + populate: false cleanup: false - Aerospike: - addr: 'aerospike' - port: 3000 - set: 'cache' - namespace: 'test' diff --git a/tests/unit/Annotations/Adapter/AerospikeTest.php b/tests/unit/Annotations/Adapter/AerospikeTest.php index 5a9dd9d65..05397a12c 100644 --- a/tests/unit/Annotations/Adapter/AerospikeTest.php +++ b/tests/unit/Annotations/Adapter/AerospikeTest.php @@ -6,6 +6,7 @@ use ReflectionMethod; use ReflectionProperty; use Codeception\TestCase\Test; +use Phalcon\Annotations\Exception; use Phalcon\Annotations\Adapter\Aerospike; use Phalcon\Cache\Backend\Aerospike as CacheBackend; @@ -66,7 +67,7 @@ public function testHasSetProperty() */ public function testShouldReadAndWriteToAerospikeWithoutPrefix($key, $data) { - $object = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]]]); + $object = new Aerospike(['hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]]]); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -79,7 +80,7 @@ public function testShouldReadAndWriteToAerospikeWithoutPrefix($key, $data) */ public function testShouldReadAndWriteToAerospikeWithPrefix($key, $data) { - $object = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], 'prefix' => 'test_']); + $object = new Aerospike(['hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'prefix' => 'test_']); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -87,7 +88,7 @@ public function testShouldReadAndWriteToAerospikeWithPrefix($key, $data) public function testShouldGetCacheBackendThroughGetter() { - $object = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]]]); + $object = new Aerospike(['hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]]]); $reflectedMethod = new ReflectionMethod(get_class($object), 'getCacheBackend'); $reflectedMethod->setAccessible(true); @@ -96,7 +97,7 @@ public function testShouldGetCacheBackendThroughGetter() public function testShouldGetCacheBackendThroughReflectionSetter() { - $object = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]]]); + $object = new Aerospike(['hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]]]); $mock = $this->getMock(CacheBackend::class, [], [], '', false); $reflectedProperty = new ReflectionProperty(get_class($object), 'aerospike'); @@ -114,7 +115,7 @@ public function testShouldGetCacheBackendThroughReflectionSetter() */ public function testShouldPrepareKey($key) { - $object = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]]]); + $object = new Aerospike(['hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]]]); $reflectedMethod = new ReflectionMethod(get_class($object), 'prepareKey'); $reflectedMethod->setAccessible(true); @@ -126,7 +127,7 @@ public function testShouldPrepareKey($key) * @param array $options * @param array $expected */ - public function testShouldCreateRedisAdapterInstanceAndSetOptions($options, $expected) + public function testShouldCreateAerospikeAdapterInstanceAndSetOptions($options, $expected) { $object = new Aerospike($options); $reflectedProperty = new ReflectionProperty(get_class($object), 'options'); @@ -138,12 +139,10 @@ public function testShouldCreateRedisAdapterInstanceAndSetOptions($options, $exp /** * @dataProvider providerInvalidConstructor * @param array $options - * @param string $exceptionName - * @param string $exceptionMessage */ - public function testShouldCatchExceptionWhenInvalidParamsPassed($options, $exceptionName, $exceptionMessage) + public function testShouldCatchExceptionWhenInvalidParamsPassed($options) { - $this->setExpectedException($exceptionName, $exceptionMessage); + $this->setExpectedException(Exception::class, 'No hosts given in options'); new Aerospike($options); } @@ -178,23 +177,15 @@ public function providerInvalidConstructor() return [ [ [], - 'Phalcon\Annotations\Exception', - 'No hosts given in options' ], [ ['hosts' => null], - 'Phalcon\Annotations\Exception', - 'No hosts given in options' ], [ ['hosts' => []], - 'Phalcon\Annotations\Exception', - 'No hosts given in options' ], [ ['hosts' => [[]]], - 'Phalcon\Cache\Exception', - 'Aerospike failed to connect [-2]: Unable to find host parameter' ] ]; } @@ -204,11 +195,11 @@ public function providerConstructor() return [ [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23 ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23, 'prefix' => '', 'persistent' => false, @@ -217,7 +208,7 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23, 'options' => [ 1 => 1250, @@ -225,7 +216,7 @@ public function providerConstructor() ] ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23, 'prefix' => '', 'persistent' => false, @@ -237,12 +228,12 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23, 'persistent' => true ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 23, 'prefix' => '', 'persistent' => true, @@ -251,11 +242,11 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'prefix' => 'test_' ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 8600, 'prefix' => 'test_', 'persistent' => false, @@ -264,11 +255,11 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'randomValue' => 'test_' ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'randomValue' => 'test_', 'lifetime' => 8600, 'prefix' => '', @@ -278,11 +269,11 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 123 => 'test_' ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 123 => 'test_', 'lifetime' => 8600, 'prefix' => '', @@ -292,12 +283,12 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 24, 'prefix' => 'test_', ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 24, 'prefix' => 'test_', 'persistent' => false, @@ -306,10 +297,10 @@ public function providerConstructor() ], [ [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], ], [ - 'hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]], + 'hosts' => [['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)]], 'lifetime' => 8600, 'prefix' => '', 'persistent' => false, diff --git a/tests/unit/Annotations/Adapter/MemcachedTest.php b/tests/unit/Annotations/Adapter/MemcachedTest.php index 2962d1b9f..3a0a7c469 100644 --- a/tests/unit/Annotations/Adapter/MemcachedTest.php +++ b/tests/unit/Annotations/Adapter/MemcachedTest.php @@ -75,7 +75,7 @@ public function testHasMemcached() */ public function testShouldReadAndWriteToMemcachedWithoutPrefix($key, $data) { - $object = new Memcached(['host' => TEST_MC_HOST]); + $object = new Memcached(['host' => env('TEST_MC_HOST', '127.0.0.1')]); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -88,7 +88,7 @@ public function testShouldReadAndWriteToMemcachedWithoutPrefix($key, $data) */ public function testShouldReadAndWriteToMemcachedWithPrefix($key, $data) { - $object = new Memcached(['host' => TEST_MC_HOST, 'prefix' => 'test_']); + $object = new Memcached(['host' => env('TEST_MC_HOST', '127.0.0.1'), 'prefix' => 'test_']); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -96,7 +96,7 @@ public function testShouldReadAndWriteToMemcachedWithPrefix($key, $data) public function testShouldGetCacheBackendThroughGetter() { - $object = new Memcached(['host' => TEST_MC_HOST]); + $object = new Memcached(['host' => env('TEST_MC_HOST', '127.0.0.1')]); $reflectedMethod = new ReflectionMethod(get_class($object), 'getCacheBackend'); $reflectedMethod->setAccessible(true); @@ -105,7 +105,7 @@ public function testShouldGetCacheBackendThroughGetter() public function testShouldGetCacheBackendThroughReflectionSetter() { - $object = new Memcached(['host' => TEST_MC_HOST]); + $object = new Memcached(['host' => env('TEST_MC_HOST', '127.0.0.1')]); $mock = $this->getMockBuilder(Libmemcached::class) ->disableOriginalConstructor() ->getMock(); @@ -123,7 +123,7 @@ public function testShouldGetCacheBackendThroughReflectionSetter() */ public function testShouldPrepareKey($key) { - $object = new Memcached(['host' => TEST_MC_HOST]); + $object = new Memcached(['host' => env('TEST_MC_HOST', '127.0.0.1')]); $reflectedMethod = new ReflectionMethod(get_class($object), 'prepareKey'); $reflectedMethod->setAccessible(true); @@ -170,14 +170,14 @@ public function providerConstructor() return [ [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 23 ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 23, 'prefix' => '' @@ -185,14 +185,14 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'prefix' => 'test_' ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 8600, 'prefix' => 'test_' @@ -200,14 +200,14 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'randomValue' => 'test_' ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'randomValue' => 'test_', 'lifetime' => 8600, @@ -216,14 +216,14 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 123 => 'test_' ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 123 => 'test_', 'lifetime' => 8600, @@ -232,15 +232,15 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 24, 'prefix' => 'test_' ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 24, 'prefix' => 'test_' @@ -248,13 +248,13 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1 ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 8600, 'prefix' => '' @@ -262,12 +262,12 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), 'weight' => 1 ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 8600, 'prefix' => '' @@ -275,12 +275,12 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 8600, 'prefix' => '' @@ -288,11 +288,11 @@ public function providerConstructor() ], [ [ - 'host' => TEST_MC_HOST, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), ], [ - 'host' => TEST_MC_HOST, - 'port' => TEST_MC_PORT, + 'host' => env('TEST_MC_HOST', '127.0.0.1'), + 'port' => env('TEST_MC_PORT', 11211), 'weight' => 1, 'lifetime' => 8600, 'prefix' => '' diff --git a/tests/unit/Annotations/Adapter/RedisTest.php b/tests/unit/Annotations/Adapter/RedisTest.php index eaf8001c7..7759f797b 100644 --- a/tests/unit/Annotations/Adapter/RedisTest.php +++ b/tests/unit/Annotations/Adapter/RedisTest.php @@ -63,7 +63,7 @@ public function testHasRedis() */ public function testShouldReadAndWriteToRedisWithoutPrefix($key, $data) { - $object = new Redis(['host' => TEST_RS_HOST]); + $object = new Redis(['host' => env('TEST_RS_HOST', 11211)]); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -76,7 +76,7 @@ public function testShouldReadAndWriteToRedisWithoutPrefix($key, $data) */ public function testShouldReadAndWriteToRedisWithPrefix($key, $data) { - $object = new Redis(['host' => TEST_RS_HOST, 'prefix' => 'test_']); + $object = new Redis(['host' => env('TEST_RS_HOST', 11211), 'prefix' => 'test_']); $object->write($key, $data); $this->assertEquals($data, $object->read($key)); @@ -84,7 +84,7 @@ public function testShouldReadAndWriteToRedisWithPrefix($key, $data) public function testShouldGetCacheBackendThroughGetter() { - $object = new Redis(['host' => TEST_RS_HOST]); + $object = new Redis(['host' => env('TEST_RS_HOST', 11211)]); $reflectedMethod = new ReflectionMethod(get_class($object), 'getCacheBackend'); $reflectedMethod->setAccessible(true); @@ -93,7 +93,7 @@ public function testShouldGetCacheBackendThroughGetter() public function testShouldGetCacheBackendThroughReflectionSetter() { - $object = new Redis(['host' => TEST_RS_HOST]); + $object = new Redis(['host' => env('TEST_RS_HOST', 11211)]); $mock = $this->getMock(CacheBackend::class, [], [], '', false); $reflectedProperty = new ReflectionProperty(get_class($object), 'redis'); @@ -111,7 +111,7 @@ public function testShouldGetCacheBackendThroughReflectionSetter() */ public function testShouldPrepareKey($key) { - $object = new Redis(['host' => TEST_RS_HOST]); + $object = new Redis(['host' => env('TEST_RS_HOST', 11211)]); $reflectedMethod = new ReflectionMethod(get_class($object), 'prepareKey'); $reflectedMethod->setAccessible(true); @@ -162,13 +162,13 @@ public function providerConstructor() return [ [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 23 ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 23, 'prefix' => '', 'persistent' => false @@ -176,14 +176,14 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 23, 'persistent' => true ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 23, 'prefix' => '', 'persistent' => true @@ -191,13 +191,13 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'prefix' => 'test_' ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 8600, 'prefix' => 'test_', 'persistent' => false @@ -205,13 +205,13 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'randomValue' => 'test_' ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'randomValue' => 'test_', 'lifetime' => 8600, 'prefix' => '', @@ -220,13 +220,13 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 123 => 'test_' ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 123 => 'test_', 'lifetime' => 8600, 'prefix' => '', @@ -235,14 +235,14 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 24, 'prefix' => 'test_', ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 24, 'prefix' => 'test_', 'persistent' => false @@ -250,12 +250,12 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 8600, 'prefix' => '', 'persistent' => false @@ -263,11 +263,11 @@ public function providerConstructor() ], [ [ - 'host' => TEST_RS_HOST, + 'host' => env('TEST_RS_HOST', 11211), ], [ - 'host' => TEST_RS_HOST, - 'port' => TEST_RS_PORT, + 'host' => env('TEST_RS_HOST', 11211), + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 8600, 'prefix' => '', 'persistent' => false @@ -278,7 +278,7 @@ public function providerConstructor() ], [ 'host' => '127.0.0.1', - 'port' => TEST_RS_PORT, + 'port' => env('TEST_RS_PORT', 6379), 'lifetime' => 8600, 'prefix' => '', 'persistent' => false diff --git a/tests/unit/Annotations/Extended/Adapter/ApcTest.php b/tests/unit/Annotations/Extended/Adapter/ApcTest.php new file mode 100644 index 000000000..c0b3bb056 --- /dev/null +++ b/tests/unit/Annotations/Extended/Adapter/ApcTest.php @@ -0,0 +1,176 @@ +markTestSkipped('Warning: apc extension is not loaded'); + } + + if (!ini_get('apc.enabled') || (PHP_SAPI === 'cli' && !ini_get('apc.enable_cli'))) { + $this->markTestSkipped('Warning: apc.enable_cli must be set to "On"'); + } + + if (extension_loaded('apcu') && version_compare(phpversion('apcu'), '5.1.6', '=')) { + $this->markTestSkipped('Warning: APCu v5.1.6 was broken. See: https://github.com/krakjoe/apcu/issues/203'); + } + } + + /** @test */ + public function shouldReadFromApcWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Apc(); + + $this->tester->haveInApc('_PHAN' . 'read-1', $reflection); + $this->assertEquals($reflection, $annotations->read('read-1')); + } + + /** @test */ + public function shouldReadFromApcWithPrefix() + { + $reflection = $this->getReflection(); + $annotations = new Apc(['prefix' => 'prefix-']); + + $this->tester->haveInApc('_PHAN' . 'prefix-read-2', $reflection); + $this->assertEquals($reflection, $annotations->read('read-2')); + } + + /** @test */ + public function shouldWriteToTheApcWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Apc(); + + $this->assertTrue($annotations->write('write-1', $reflection)); + $this->assertEquals($reflection, $this->tester->grabValueFromApc('_PHAN' . 'write-1')); + } + + /** @test */ + public function shouldWriteToTheApcWithPrefix() + { + $reflection = $this->getReflection(); + $annotations = new Apc(['prefix' => 'prefix-']); + + $this->assertTrue($annotations->write('write-2', $reflection)); + $this->assertEquals($reflection, $this->tester->grabValueFromApc('_PHAN' . 'prefix-write-2')); + } + + /** @test */ + public function shouldFlushTheApcStorageWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Apc(); + + $this->tester->haveInApc('_PHAN' . 'flush-1', $reflection); + $this->tester->haveInApc('_ANOTHER' . 'flush-1', $reflection); + + $this->assertTrue($annotations->flush()); + $this->tester->dontSeeInApc('_PHAN' . 'flush-1'); + $this->tester->seeInApc('_ANOTHER' . 'flush-1', $reflection); + } + + /** @test */ + public function shouldFlushTheApcStorageWithPrefix() + { + $reflection = $this->getReflection(); + $annotations = new Apc(['prefix' => 'prefix-']); + + $this->tester->haveInApc('_PHAN' . 'prefix-flush-2', $reflection); + $this->tester->haveInApc('_ANOTHER' . 'prefix-flush-2', $reflection); + + $this->assertTrue($annotations->flush()); + $this->tester->dontSeeInApc('_PHAN' . 'prefix-flush-2'); + $this->tester->seeInApc('_ANOTHER' . 'prefix-flush-2', $reflection); + } + + /** @test */ + public function shouldReadAndWriteFromApcWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Apc(); + + $this->assertTrue($annotations->write('read-write-1', $reflection)); + $this->assertEquals($reflection, $annotations->read('read-write-1')); + $this->assertEquals($reflection, $this->tester->grabValueFromApc('_PHAN' . 'read-write-1')); + } + + /** @test */ + public function shouldReadAndWriteFromApcWithPrefix() + { + $reflection = $this->getReflection(); + $annotations = new Apc(['prefix' => 'prefix-']); + + $this->assertTrue($annotations->write('read-write-2', $reflection)); + $this->assertEquals($reflection, $annotations->read('read-write-2')); + $this->assertEquals($reflection, $this->tester->grabValueFromApc('_PHAN' . 'prefix-read-write-2')); + } + + /** + * @test + * @dataProvider providerKey + * @param mixed $key + * @param string $prefix + * @param string|null $statsKey + * @param string $expected + */ + public function shouldGetValueFromApcByUsingPrefixedIdentifier($key, $prefix, $statsKey, $expected) + { + if ($statsKey === null) { + $options = ['prefix' => $prefix]; + } else { + $options = ['prefix' => $prefix, 'statsKey' => $statsKey]; + } + + $annotations = new Apc($options); + $reflectedMethod = new ReflectionMethod(get_class($annotations), 'getPrefixedIdentifier'); + $reflectedMethod->setAccessible(true); + + $this->assertEquals($expected, $reflectedMethod->invoke($annotations, $key)); + } + + public function providerKey() + { + return [ + ['key1', '', null, '_PHANkey1' ], + ['key1', '-some-', '_PHAN', '_PHAN-some-key1'], + [1, '', null, '_PHAN1' ], + [1, 2, '_PHAN', '_PHAN21' ], + ['_key1', '', null, '_PHAN_key1' ], + ['_key1', '/', '_PHAN', '_PHAN/_key1' ], + ['key1', '#', null, '_PHAN#key1' ], + ['key1', '', '', 'key1' ], + ['key1', '', '_XXX', '_XXXkey1' ], + ['key1', 'xxx-', '', 'xxx-key1' ], + ]; + } + + protected function getReflection() + { + return Reflection::__set_state([ + '_reflectionData' => [ + 'class' => [], + 'methods' => [], + 'properties' => [], + ] + ]); + } +} diff --git a/tests/unit/Annotations/Extended/Adapter/FilesTest.php b/tests/unit/Annotations/Extended/Adapter/FilesTest.php new file mode 100644 index 000000000..8195a790e --- /dev/null +++ b/tests/unit/Annotations/Extended/Adapter/FilesTest.php @@ -0,0 +1,147 @@ +getReflection(); + $annotations = new Files(); + + $this->tester->amInPath(sys_get_temp_dir()); + $this->tester->writeToFile('read-1.php', 'assertEquals($reflection, $annotations->read('read-1')); + + $this->tester->deleteFile('read-1.php'); + } + + /** @test */ + public function shouldReadFromFileDirectoryWithAnnotationsDir() + { + $reflection = $this->getReflection(); + $annotations = new Files(['annotationsDir' => codecept_output_dir()]); + + $this->tester->amInPath(codecept_output_dir()); + $this->tester->writeToFile('read-2.php', 'assertEquals($reflection, $annotations->read('read-2')); + + $this->tester->deleteFile('read-2.php'); + } + + /** @test */ + public function shouldWriteToTheFileDirectoryWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Files(); + + $this->assertTrue($annotations->write('write-1', $reflection)); + + $this->tester->amInPath(sys_get_temp_dir()); + $this->tester->seeFileFound('write-1.php'); + $this->tester->seeFileContentsEqual('tester->deleteFile('write-1.php'); + } + + /** @test */ + public function shouldWriteToTheFileDirectoryWithAnnotationsDir() + { + $reflection = $this->getReflection(); + $annotations = new Files(['annotationsDir' => codecept_output_dir()]); + + $this->assertTrue($annotations->write('write-2', $reflection)); + + $this->tester->amInPath(codecept_output_dir()); + $this->tester->seeFileFound('write-2.php'); + $this->tester->seeFileContentsEqual('tester->deleteFile('write-2.php'); + } + + /** @test */ + public function shouldFlushTheFileDirectoryStorageWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Files(); + + $this->tester->amInPath(sys_get_temp_dir()); + $this->tester->writeToFile('flush-1.php', 'tester->writeToFile('flush-2.php', 'assertTrue($annotations->flush()); + + $this->tester->dontSeeFileFound('flush-1.php'); + $this->tester->dontSeeFileFound('flush-2.php'); + } + + /** @test */ + public function shouldFlushTheFileDirectoryStorageWithAnnotationsDir() + { + $reflection = $this->getReflection(); + $annotations = new Files(['annotationsDir' => codecept_output_dir()]); + + $this->tester->amInPath(codecept_output_dir()); + $this->tester->writeToFile('flush-3.php', 'tester->writeToFile('flush-4.php', 'assertTrue($annotations->flush()); + + $this->tester->dontSeeFileFound('flush-3.php'); + $this->tester->dontSeeFileFound('flush-4.php'); + } + + /** @test */ + public function shouldReadAndWriteFromFileDirectoryWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Files(); + + $this->assertTrue($annotations->write('read-write-1', $reflection)); + $this->assertEquals($reflection, $annotations->read('read-write-1')); + + $this->tester->amInPath(sys_get_temp_dir()); + $this->tester->seeFileContentsEqual('tester->deleteFile('read-write-1.php'); + } + + /** @test */ + public function shouldReadAndWriteFromFileDirectoryWithAnnotationsDir() + { + $reflection = $this->getReflection(); + $annotations = new Files(['annotationsDir' => codecept_output_dir()]); + + $this->assertTrue($annotations->write('read-write-2', $reflection)); + $this->assertEquals($reflection, $annotations->read('read-write-2')); + + $this->tester->amInPath(codecept_output_dir()); + $this->tester->seeFileContentsEqual('tester->deleteFile('read-write-2.php'); + } + + + protected function getReflection() + { + return Reflection::__set_state([ + '_reflectionData' => [ + 'class' => [], + 'methods' => [], + 'properties' => [], + ] + ]); + } +} diff --git a/tests/unit/Annotations/Extended/Adapter/MemoryTest.php b/tests/unit/Annotations/Extended/Adapter/MemoryTest.php new file mode 100644 index 000000000..e247c72cb --- /dev/null +++ b/tests/unit/Annotations/Extended/Adapter/MemoryTest.php @@ -0,0 +1,133 @@ +getReflection(); + $annotations = new Memory(); + + $this->haveInMemory($annotations, 'read-1', $reflection); + $this->assertEquals($reflection, $annotations->read('read-1')); + } + + /** @test */ + public function shouldWriteToTheMemoryWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Memory(); + + $this->assertTrue($annotations->write('write-1', $reflection)); + $this->assertEquals($reflection, $this->grabValueFromMemory($annotations, 'write-1')); + } + + /** @test */ + public function shouldFlushTheMemoryStorageWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Memory(); + + $this->haveInMemory($annotations, 'flush-1', $reflection); + + $this->assertTrue($annotations->flush()); + $this->dontSeeInMemory($annotations, 'flush-1'); + } + + /** @test */ + public function shouldReadAndWriteFromMemoryWithoutAnyAdditionalParameter() + { + $reflection = $this->getReflection(); + $annotations = new Memory(); + + $this->assertTrue($annotations->write('read-write-1', $reflection)); + $this->assertEquals($reflection, $annotations->read('read-write-1')); + $this->assertEquals($reflection, $this->grabValueFromMemory($annotations, 'read-write-1')); + } + + /** + * @test + * @dataProvider providerKey + * @param mixed $key + * @param string $expected + */ + public function shouldGetValueFromMemoryByUsingPrefixedIdentifier($key, $expected) + { + $annotations = new Memory(); + $reflectedMethod = new ReflectionMethod(get_class($annotations), 'getPrefixedIdentifier'); + $reflectedMethod->setAccessible(true); + + $this->assertEquals($expected, $reflectedMethod->invoke($annotations, $key)); + } + + public function providerKey() + { + return [ + ['Key1', 'key1'], + ['KEY', 'key' ], + [1, '1' ], + ['____', '____'], + ]; + } + + protected function getReflection() + { + return Reflection::__set_state([ + '_reflectionData' => [ + 'class' => [], + 'methods' => [], + 'properties' => [], + ] + ]); + } + + protected function haveInMemory($object, $key, $value) + { + $reflectedProperty = new ReflectionProperty(get_class($object), 'data'); + $reflectedProperty->setAccessible(true); + + $data = $reflectedProperty->getValue($object); + $data[$key] = $value; + + $reflectedProperty->setValue($object, $data); + } + + protected function grabValueFromMemory($object, $key) + { + $reflectedProperty = new ReflectionProperty(get_class($object), 'data'); + $reflectedProperty->setAccessible(true); + + $data = $reflectedProperty->getValue($object); + + return $data[$key]; + } + + protected function dontSeeInMemory($object, $key, $value = false) + { + $reflectedProperty = new ReflectionProperty(get_class($object), 'data'); + $reflectedProperty->setAccessible(true); + + $data = $reflectedProperty->getValue($object); + + if ($value === false) { + $this->assertArrayNotHasKey($key, $data); + } else { + $this->assertSame($value, $data[$key]); + } + } +} diff --git a/tests/unit/Cache/Backend/AerospikeTest.php b/tests/unit/Cache/Backend/AerospikeTest.php index 4a9df515b..3f730ca89 100644 --- a/tests/unit/Cache/Backend/AerospikeTest.php +++ b/tests/unit/Cache/Backend/AerospikeTest.php @@ -34,8 +34,6 @@ class AerospikeTest extends Test */ protected $tester; - protected $keys = []; - /** * executed before each test */ @@ -48,17 +46,9 @@ protected function _before() $this->getModule('Aerospike')->_reconfigure(['set' => 'cache']); } - /** - * executed after each test - */ - protected function _after() - { - $this->cleanup(); - } - public function testShouldGetAerospikeInstance() { - $this->assertInstanceOf('\Aerospike', $this->getAdapter()->getDb()); + $this->assertInstanceOf(\Aerospike::class, $this->getAdapter()->getDb()); } /** @@ -78,8 +68,6 @@ public function testShouldIncrementValue() $this->assertEquals(2, $cache->increment('increment')); $this->assertEquals(4, $cache->increment('increment', 2)); $this->assertEquals(14, $cache->increment('increment', 10)); - - $cache->delete('increment'); } public function testShouldDecrementValue() @@ -90,8 +78,6 @@ public function testShouldDecrementValue() $this->assertEquals(99, $cache->decrement('decrement')); $this->assertEquals(97, $cache->decrement('decrement', 2)); $this->assertEquals(87, $cache->decrement('decrement', 10)); - - $cache->delete('decrement'); } public function testShouldGetKeys() @@ -103,10 +89,6 @@ public function testShouldGetKeys() $cache->save('long-key', 'long-val', 10); $cache->save('bcd', 3, 10); - $this->keys[] = 'a'; - $this->keys[] = 'long-key'; - $this->keys[] = 'bcd'; - $keys = $cache->queryKeys(); sort($keys); @@ -114,10 +96,23 @@ public function testShouldGetKeys() $this->assertEquals(['long-key'], $cache->queryKeys('long')); } + public function testShouldFlushAllData() + { + $cache = $this->getAdapter(); + + $data = "sure, nothing interesting"; + $cache->save('test-data-flush', $data); + $cache->save('test-data-flush2', $data); + + $cache->flush(); + + $this->tester->dontSeeInAerospike('test-data-flush'); + $this->tester->dontSeeInAerospike('test-data-flush2'); + } + public function testShouldSaveData() { $cache = $this->getAdapter(); - $this->keys[] = 'test-data'; $data = [1, 2, 3, 4, 5]; $cache->save('test-data', $data); @@ -130,13 +125,13 @@ public function testShouldSaveData() public function testShouldDeleteData() { - $cache = $this->getAdapter(); - $this->keys[] = 'test-data'; + $cache = $this->getAdapter(20); $data = rand(0, 99); $this->tester->haveInAerospike('test-data', $data); $this->assertTrue($cache->delete('test-data')); + $this->tester->dontSeeInAerospike('test-data'); } @@ -150,7 +145,6 @@ public function testShouldUseOutputFrontend() ob_start(); $content = $cache->start('test-output'); - $this->keys[] = 'test-output'; $this->assertNull($content); echo $time; @@ -177,7 +171,7 @@ private function getAdapter($lifetime = 20) if ($lifetime) { $frontCache = new CacheData(['lifetime' => $lifetime]); } else { - $frontCache = new CacheData; + $frontCache = new CacheData(); } $cache = new CacheAerospike($frontCache, $this->getConfig()); @@ -189,30 +183,11 @@ private function getConfig() { return [ 'hosts' => [ - ['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT] + ['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)] ], 'persistent' => false, // important 'namespace' => 'test', 'prefix' => '' ]; } - - private function cleanup() - { - $aerospike = new Aerospike(['hosts' => [['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT]]], false); - - foreach ($this->keys as $i => $key) { - $aerospike->remove($this->buildKey($aerospike, $key)); - unset($this->keys[$i]); - } - } - - private function buildKey(Aerospike $aerospike, $key) - { - return $aerospike->initKey( - 'test', - 'cache', - $key - ); - } } diff --git a/tests/unit/Cache/Backend/DatabaseTest.php b/tests/unit/Cache/Backend/DatabaseTest.php index 9d827294d..54301d881 100644 --- a/tests/unit/Cache/Backend/DatabaseTest.php +++ b/tests/unit/Cache/Backend/DatabaseTest.php @@ -96,12 +96,12 @@ protected function getBackend($prefix = '') $frontend = new CacheFrontend(['lifetime' => 10]); $connection = new DbAdapter( [ - 'host' => TEST_DB_HOST, - 'username' => TEST_DB_USER, - 'password' => TEST_DB_PASSWD, - 'dbname' => TEST_DB_NAME, - 'charset' => TEST_DB_CHARSET, - 'port' => TEST_DB_PORT, + 'host' => env('TEST_DB_HOST', '127.0.0.1'), + 'username' => env('TEST_DB_USER', 'incubator'), + 'password' => env('TEST_DB_PASSWD', 'secret'), + 'dbname' => env('TEST_DB_NAME', 'incubator'), + 'charset' => env('TEST_DB_CHARSET', 'utf8'), + 'port' => env('TEST_DB_PORT', 3306), ] ); diff --git a/tests/unit/Db/Adapter/FactoryTest.php b/tests/unit/Db/Adapter/FactoryTest.php index 512d9e951..334dda4fa 100644 --- a/tests/unit/Db/Adapter/FactoryTest.php +++ b/tests/unit/Db/Adapter/FactoryTest.php @@ -43,11 +43,11 @@ protected function _before() { $this->testable = [ 'adapter' => null, - 'host' => TEST_DB_HOST, - 'username' => TEST_DB_USER, - 'password' => TEST_DB_PASSWD, - 'dbname' => TEST_DB_NAME, - 'charset' => TEST_DB_CHARSET, + 'host' => env('TEST_DB_HOST', '127.0.0.1'), + 'username' => env('TEST_DB_USER', 'incubator'), + 'password' => env('TEST_DB_PASSWD', 'secret'), + 'dbname' => env('TEST_DB_NAME', 'incubator'), + 'charset' => env('TEST_DB_CHARSET', 'utf8'), ]; } diff --git a/tests/unit/Mvc/Model/Behavior/Helper.php b/tests/unit/Mvc/Model/Behavior/Helper.php index d9183fe4c..595369e7c 100644 --- a/tests/unit/Mvc/Model/Behavior/Helper.php +++ b/tests/unit/Mvc/Model/Behavior/Helper.php @@ -61,12 +61,12 @@ protected function _before() $di->setShared('modelsManager', new Manager()); $di->setShared('db', function () { return new Mysql([ - 'host' => TEST_DB_HOST, - 'port' => TEST_DB_PORT, - 'username' => TEST_DB_USER, - 'password' => TEST_DB_PASSWD, - 'dbname' => TEST_DB_NAME, - 'charset' => TEST_DB_CHARSET, + 'host' => env('TEST_DB_HOST', '127.0.0.1'), + 'username' => env('TEST_DB_USER', 'incubator'), + 'password' => env('TEST_DB_PASSWD', 'secret'), + 'dbname' => env('TEST_DB_NAME', 'incubator'), + 'charset' => env('TEST_DB_CHARSET', 'utf8'), + 'port' => env('TEST_DB_PORT', 3306), ]); }); diff --git a/tests/unit/Mvc/Model/EagerLoading/EagerLoadingTest.php b/tests/unit/Mvc/Model/EagerLoading/EagerLoadingTest.php index 564a63469..ce526e567 100644 --- a/tests/unit/Mvc/Model/EagerLoading/EagerLoadingTest.php +++ b/tests/unit/Mvc/Model/EagerLoading/EagerLoadingTest.php @@ -60,12 +60,12 @@ protected function _before() $di->setShared('modelsManager', new Manager()); $di->setShared('db', function () { return new Mysql([ - 'host' => TEST_DB_HOST, - 'port' => TEST_DB_PORT, - 'username' => TEST_DB_USER, - 'password' => TEST_DB_PASSWD, - 'dbname' => TEST_DB_NAME, - 'charset' => TEST_DB_CHARSET, + 'host' => env('TEST_DB_HOST', '127.0.0.1'), + 'username' => env('TEST_DB_USER', 'incubator'), + 'password' => env('TEST_DB_PASSWD', 'secret'), + 'dbname' => env('TEST_DB_NAME', 'incubator'), + 'charset' => env('TEST_DB_CHARSET', 'utf8'), + 'port' => env('TEST_DB_PORT', 3306), ]); }); diff --git a/tests/unit/Mvc/MongoCollectionTest.php b/tests/unit/Mvc/MongoCollectionTest.php index 688bc2894..304f2ae6b 100644 --- a/tests/unit/Mvc/MongoCollectionTest.php +++ b/tests/unit/Mvc/MongoCollectionTest.php @@ -1,95 +1,72 @@ + * @package Phalcon\Test\Mvc + * @group Db + * + * The contents of this file are subject to the New BSD License that is + * bundled with this package in the file LICENSE.txt + * + * If you did not receive a copy of the license and are unable to obtain it + * through the world-wide-web, please send an email to license@phalconphp.com + * so that we can send you a copy immediately. + */ class CollectionsTest extends Test { - + /** + * Executed before each test + */ protected function _before() { + parent::_before(); - if (!extension_loaded('MongoDB')) { - $this->markTestSkipped("MongoDB extension not loaded, test skipped"); - return; + if (!extension_loaded('mongodb')) { + $this->markTestSkipped('mongodb extension not loaded'); } Di::reset(); - $di = new DI(); - $di->set('mongo', function(){ - $mongo = new MongoClient( 'mongodb://' . TEST_MONGODB_HOST . ':' . TEST_MONGODB_PORT ); - return $mongo->selectDatabase( 'phalcon_test' ); - }); - $di->set('collectionManager', function(){ - return new Manager(); - }); - - } - public function loadData() - { + $di = new Di(); + $di->set('mongo', function() { + $dsn = 'mongodb://' . env('TEST_MONGODB_HOST', '127.0.0.1') . ':' . env('TEST_MONGODB_PORT', 27017); + $mongo = new Client($dsn); - $car = new Cars(); - $car->manufacturer = 'Mclaren'; - $car->model = '650S'; - $car->rank = 1; - $car->value = 500000; - $car->save(); - - $car = new Cars(); - $car->manufacturer = 'Porsche'; - $car->model = '911 GT3'; - $car->rank = 2; - $car->value = 450000; - $car->save(); - - $car = new Cars(); - $car->manufacturer = 'Ferrari'; - $car->model = '488 GTB'; - $car->rank = 3; - $car->value = 400000; - $car->save(); - - $car = new Cars(); - $car->manufacturer = 'Porsche'; - $car->model = '918 Spyder'; - $car->rank = 4; - $car->value = 350000; - $car->save(); - - $car = new Cars(); - $car->manufacturer = 'Ferrari'; - $car->model = 'LaFerrari'; - $car->rank = 5; - $car->value = 300000; - $car->save(); + return $mongo->selectDatabase(env('TEST_MONGODB_NAME', 'incubator')); + }); + $di->set('collectionManager', Manager::class); } - public function clearData() + /** + * Executed after each test + */ + protected function _after() { - $count = Cars::count(); - - if( $count > 0 ){ - $cars = Cars::find(); - foreach( $cars as $car ){ - $car->delete(); - } - } + parent::_after(); Di::reset(); - } public function testCollectionsSave() { - $car = new Cars(); $car->manufacturer = 'Mclaren'; $car->model = '650S'; @@ -99,7 +76,6 @@ public function testCollectionsSave() $this->assertTrue($success); $this->clearData(); - } /** @@ -107,61 +83,58 @@ public function testCollectionsSave() */ public function testCollectionsDelete() { - $this->loadData(); + /** @var Cars[] $cars */ $cars = Cars::find(); - foreach($cars as $car){ + foreach ($cars as $car) { $this->assertTrue($car->delete()); } - } - /** * @depends testCollectionsSave * @depends testCollectionsDelete */ public function testCollectionsFind() { - $this->loadData(); - //Without Params + // Without Params $cars = Cars::find(); $this->assertTrue(is_array($cars)); - $this->assertInstanceOf( 'Phalcon\Mvc\MongoCollection', $cars[0] ); + $this->assertInstanceOf(MongoCollection::class, $cars[0]); $this->assertCount(5, $cars); - //With Params + // With Params $ferraris = Cars::find([ ['manufacturer' => 'Ferrari'] ]); $this->assertCount(2, $ferraris); - //Limit + // Limit $ferraris = Cars::find([ ['manufacturer' => 'Ferrari'], 'limit' => 1 ]); $this->assertCount(1, $ferraris); - $this->assertEquals( '488 GTB', $ferraris[0]->model ); + $this->assertEquals('488 GTB', $ferraris[0]->model); - //Skip + // Skip $ferraris = Cars::find([ ['manufacturer' => 'Ferrari'], 'limit' => 1, 'skip' => 1 ]); $this->assertCount(1, $ferraris); - $this->assertEquals( 'LaFerrari', $ferraris[0]->model ); + $this->assertEquals('LaFerrari', $ferraris[0]->model); - //Sort ASC + // Sort ASC $ferraris = Cars::find([ ['manufacturer' => 'Ferrari'], 'sort' => [ @@ -169,9 +142,9 @@ public function testCollectionsFind() ], ]); $this->assertCount(2, $ferraris); - $this->assertEquals( '488 GTB', $ferraris[0]->model ); + $this->assertEquals('488 GTB', $ferraris[0]->model); - //Sort DESC + // Sort DESC $ferraris = Cars::find([ ['manufacturer' => 'Ferrari'], 'sort' => [ @@ -179,9 +152,9 @@ public function testCollectionsFind() ], ]); $this->assertCount(2, $ferraris); - $this->assertEquals( 'LaFerrari', $ferraris[0]->model ); + $this->assertEquals('LaFerrari', $ferraris[0]->model); - //Fields + // Fields $cars = Cars::find([ 'fields' => [ 'manufacturer' => true, @@ -189,27 +162,27 @@ public function testCollectionsFind() ] ]); $this->assertCount(5, $cars); - $this->assertObjectNotHasAttribute( 'rank', $cars[0] ); + $this->assertObjectNotHasAttribute('rank', $cars[0]); - //$gt + // $gt $cars = Cars::find([ [ 'rank' => [ '$gt' => 2 ] ] ]); $this->assertCount(3, $cars); - $this->assertEquals( '488 GTB', $cars[0]->model ); + $this->assertEquals('488 GTB', $cars[0]->model); - //$lt + // $lt $cars = Cars::find([ [ 'rank' => [ '$lt' => 3 ] ] ]); $this->assertCount(2, $cars); - $this->assertEquals( '650S', $cars[0]->model ); + $this->assertEquals('650S', $cars[0]->model); - //More Complex Query + // More Complex Query $cars = Cars::find([ [ 'rank' => [ '$lt' => 3 ] @@ -223,11 +196,10 @@ public function testCollectionsFind() ] ]); $this->assertCount(2, $cars); - $this->assertEquals( '911 GT3', $cars[0]->model ); - $this->assertObjectNotHasAttribute( 'manufacturer', $cars[0] ); + $this->assertEquals('911 GT3', $cars[0]->model); + $this->assertObjectNotHasAttribute('manufacturer', $cars[0]); $this->clearData(); - } /** @@ -236,38 +208,36 @@ public function testCollectionsFind() */ public function testCollectionsFindFirst() { - $this->loadData(); $car = Cars::findFirst(); - $this->assertInstanceOf( '\Phalcon\Mvc\MongoCollection', $car ); - $this->assertEquals( '650S', $car->model ); + $this->assertInstanceOf(MongoCollection::class, $car); + $this->assertEquals('650S', $car->model); $car = Cars::findFirst([ [ 'manufacturer' => 'Ferrari' ] ]); - $this->assertEquals( '488 GTB', $car->model ); + $this->assertEquals('488 GTB', $car->model); return $car; - } /** * @depends testCollectionsFindFirst * @depends testCollectionsSave * @depends testCollectionsDelete + * @param Cars $car */ - public function testCollectionsFindById( $car ) + public function testCollectionsFindById($car) { - $id = $car->getId(); - $this->assertInstanceOf( 'MongoDB\BSON\ObjectID', $id ); + $this->assertInstanceOf(ObjectID::class, $id); - $car = Cars::findById( $id ); - $this->assertEquals( '488 GTB', $car->model ); + /** @var Cars $car */ + $car = Cars::findById($id); + $this->assertEquals('488 GTB', $car->model); $this->clearData(); - } /** @@ -276,7 +246,6 @@ public function testCollectionsFindById( $car ) */ public function testCollectionsCount() { - $this->loadData(); $count = Cars::count(); @@ -290,14 +259,13 @@ public function testCollectionsCount() $this->assertEquals(2, $count2); $this->clearData(); - } public function testCollectionsAggregate() { - $this->loadData(); + /** @var Cursor $data */ $data = Cars::aggregate([ [ '$match' => [ 'manufacturer' => 'Ferrari' ] @@ -310,15 +278,79 @@ public function testCollectionsAggregate() ] ]); - $this->assertInstanceOf( 'MongoDB\Driver\Cursor', $data ); + $this->assertInstanceOf(Cursor::class, $data); $results = $data->toArray(); - $this->assertEquals( 'Ferrari', $results[0]['_id'] ); - $this->assertEquals( 700000, $results[0]['total'] ); + $this->assertEquals('Ferrari', $results[0]['_id']); + $this->assertEquals(700000, $results[0]['total']); $this->clearData(); + } + + /** + * @test + * @issue 696 + */ + public function shouldInsertNewDocument() + { + $hero = new Heroes(); + $hero->name = 'Phalcon contributor'; + $this->assertTrue($hero->create()); + $this->assertInstanceOf(MongoCollection::class, $hero); + $this->assertInstanceOf(ObjectID::class, $hero->getId()); + $this->assertSame('Phalcon contributor', $hero->name); } -} \ No newline at end of file + protected function loadData() + { + $car = new Cars(); + $car->manufacturer = 'Mclaren'; + $car->model = '650S'; + $car->rank = 1; + $car->value = 500000; + $car->save(); + + $car = new Cars(); + $car->manufacturer = 'Porsche'; + $car->model = '911 GT3'; + $car->rank = 2; + $car->value = 450000; + $car->save(); + + $car = new Cars(); + $car->manufacturer = 'Ferrari'; + $car->model = '488 GTB'; + $car->rank = 3; + $car->value = 400000; + $car->save(); + + $car = new Cars(); + $car->manufacturer = 'Porsche'; + $car->model = '918 Spyder'; + $car->rank = 4; + $car->value = 350000; + $car->save(); + + $car = new Cars(); + $car->manufacturer = 'Ferrari'; + $car->model = 'LaFerrari'; + $car->rank = 5; + $car->value = 300000; + $car->save(); + } + + protected function clearData() + { + $count = Cars::count(); + + if ($count > 0) { + /** @var Cars[] $cars */ + $cars = Cars::find(); + foreach ($cars as $car) { + $car->delete(); + } + } + } +} diff --git a/tests/unit/Queue/Beanstalk/ExtendedTest.php b/tests/unit/Queue/Beanstalk/ExtendedTest.php index cd4a4d065..a088ce510 100644 --- a/tests/unit/Queue/Beanstalk/ExtendedTest.php +++ b/tests/unit/Queue/Beanstalk/ExtendedTest.php @@ -48,21 +48,17 @@ class ExtendedTest extends Test */ protected function _before() { - if (!defined('TEST_BT_HOST') || !defined('TEST_BT_PORT')) { - $this->markTestSkipped('TEST_BT_HOST and/or TEST_BT_PORT env variables are not defined'); - } - $this->client = new Extended([ - 'host' => TEST_BT_HOST, - 'port' => TEST_BT_PORT, + 'host' => env('TEST_BT_HOST', 6379), + 'port' => env('TEST_BT_PORT', 11300), 'prefix' => 'PHPUnit_', ]); if (!$this->client->connect()) { $this->markTestSkipped(sprintf( 'Need a running beanstalkd server at %s:%d', - TEST_BT_HOST, - TEST_BT_PORT + env('TEST_BT_HOST', 6379), + env('TEST_BT_PORT', 11300) )); } @@ -144,7 +140,7 @@ public function testShouldDoWork() 'test-tube-2' => '2', ]; - # Check if we are using Fork1.0 (php < 7) + // Check if we are using Fork1.0 (php < 7) if (class_exists('duncan3dc\Helpers\Fork')) { $fork = new \duncan3dc\Helpers\Fork; } else { diff --git a/tests/unit/Session/Adapter/AerospikeTest.php b/tests/unit/Session/Adapter/AerospikeTest.php index 4eebc6551..a588c463a 100644 --- a/tests/unit/Session/Adapter/AerospikeTest.php +++ b/tests/unit/Session/Adapter/AerospikeTest.php @@ -47,8 +47,8 @@ protected function _before() $this->getModule('Aerospike')->_reconfigure([ 'set' => $this->set, - 'addr' => TEST_AS_HOST, - 'port' => TEST_AS_PORT + 'addr' => env('TEST_AS_HOST', '127.0.0.1'), + 'port' => env('TEST_AS_PORT', 3000) ]); } @@ -113,7 +113,7 @@ private function cleanup() $aerospike = new Aerospike( [ 'hosts' => [ - ['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT] + ['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)] ] ], false @@ -138,7 +138,7 @@ private function getConfig() { return [ 'hosts' => [ - ['addr' => TEST_AS_HOST, 'port' => TEST_AS_PORT] + ['addr' => env('TEST_AS_HOST', '127.0.0.1'), 'port' => env('TEST_AS_PORT', 3000)] ], 'persistent' => false, 'namespace' => $this->ns, diff --git a/tests/unit/Validation/Validator/PasswordStrengthTest.php b/tests/unit/Validation/Validator/PasswordStrengthTest.php index 0be5bbf34..83dcc050c 100644 --- a/tests/unit/Validation/Validator/PasswordStrengthTest.php +++ b/tests/unit/Validation/Validator/PasswordStrengthTest.php @@ -4,10 +4,10 @@ +------------------------------------------------------------------------+ | Phalcon Framework | +------------------------------------------------------------------------+ - | Copyright (c) 2011-2016 Phalcon Team (http://www.phalconphp.com) | + | Copyright (c) 2011-2016 Phalcon Team (https://www.phalconphp.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | - | with this package in the file docs/LICENSE.txt. | + | with this package in the file LICENSE.txt. | | | | If you did not receive a copy of the license and are unable to | | obtain it through the world-wide-web, please send an email | @@ -19,93 +19,144 @@ namespace Phalcon\Test\Validation\Validator; +use Phalcon\Validation; use Codeception\TestCase\Test; -use Codeception\Util\Stub; use Phalcon\Validation\Validator\PasswordStrength; class PasswordStrengthTest extends Test { - - protected function _before() + public function testValidateWeakOnDefaultScore() { - } + $validation = $this->getValidationMock(); - protected function _after() - { - } + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('Weak1'); - public function testValidateWeakOnDefaultScore() - { - $validation = Stub::make('Phalcon\Validation', array('getValue' => 'Weak1')); $validator = new PasswordStrength(); $this->assertTrue($validator->validate($validation, 'password')); } public function testValidateVeryWeakOnDefaultScore() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => '12345', 'appendMessage' => true)); + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('12345'); + + $validation->expects($this->any()) + ->method('appendMessage') + ->willReturn(true); + $validator = new PasswordStrength(); $this->assertFalse($validator->validate($validation, 'password')); } public function testValidateMediumOnScore3() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => 'Medium99')); - $validator = new PasswordStrength(array( - 'minScore' => 3 - )); + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('Medium99'); + + $validator = new PasswordStrength(['minScore' => 3]); $this->assertTrue($validator->validate($validation, 'password')); } public function testValidateWeakOnScore3() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => 'Weak1', 'appendMessage' => true)); - $validator = new PasswordStrength(array( - 'minScore' => 3 - )); - $this->assertFalse($validator->validate($validation, 'password')); - } + $validation = $this->getValidationMock(); - public function testValidateStrongOnScore4() - { - $validation = Stub::make('Phalcon\Validation', array('getValue' => 'Strong-9')); - $validator = new PasswordStrength(array( - 'minScore' => 4 - )); - $this->assertTrue($validator->validate($validation, 'password')); - } + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('Weak1'); - public function testValidateMediumOnScore4() - { - $validation = Stub::make('Phalcon\Validation', array('getValue' => 'Medium99', 'appendMessage' => true)); - $validator = new PasswordStrength(array( - 'minScore' => 4 - )); + $validation->expects($this->any()) + ->method('appendMessage') + ->willReturn(true); + + $validator = new PasswordStrength(['minScore' => 3]); $this->assertFalse($validator->validate($validation, 'password')); } public function testValidateAllowEmpty() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => '')); - $validator = new PasswordStrength(array( - 'allowEmpty' => true - )); + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn(''); + + $validator = new PasswordStrength(['allowEmpty' => true]); $this->assertTrue($validator->validate($validation, 'password')); } public function testValidateNotAllowEmpty() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => '', 'appendMessage' => true)); - $validator = new PasswordStrength(array( - 'allowEmpty' => false - )); + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn(''); + + $validation->expects($this->any()) + ->method('appendMessage') + ->willReturn(true); + + $validator = new PasswordStrength(['allowEmpty' => false]); $this->assertFalse($validator->validate($validation, 'password')); } public function testValidateInvalidValue() { - $validation = Stub::make('Phalcon\Validation', array('getValue' => array('value', 'value'), 'appendMessage' => true)); + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn(['value', 'value']); + + $validation->expects($this->any()) + ->method('appendMessage') + ->willReturn(true); + $validator = new PasswordStrength(); $this->assertFalse($validator->validate($validation, 'password')); } + + public function testValidateMediumOnScore4() + { + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('Medium99'); + + $validation->expects($this->any()) + ->method('appendMessage') + ->willReturn(true); + + $validator = new PasswordStrength(['minScore' => 4]); + $this->assertFalse($validator->validate($validation, 'password')); + } + + public function testValidateStrongOnScore4() + { + $validation = $this->getValidationMock(); + + $validation->expects($this->any()) + ->method('getValue') + ->willReturn('Strong-9'); + + $validator = new PasswordStrength(['minScore' => 4]); + $this->assertTrue($validator->validate($validation, 'password')); + } + + protected function getValidationMock() + { + return $this->getMockBuilder(Validation::class) + ->disableOriginalConstructor() + ->getMock(); + } }