From 1c2d184679e2bc9999ec4772fdbb5d1d66cf3e44 Mon Sep 17 00:00:00 2001 From: will Date: Wed, 3 May 2017 15:57:21 -0400 Subject: [PATCH 01/26] Merging Develop into Master (#1730) * Fixing markdown field size bug * Set up Ushahidi\App namespace and move the simple classes Migrating the easy, non kohana related stuff into a namespace * Format for PSR2 * Disable slack notifications from travis * Adding survey editor update (#1662) * Adding survey editor update * Field locking fully working, next fix broken tests * Fixing tests * Update Vagrantfile * Remove extra files * Updating counts * Adding entity fields * Removing unneeded include, simplifying function * Adding task restriction * Adding form stage and attribute restriction * Fixed stage tests * Updated attribute filitering and added tests * Fixed linting * Fixing base data set * Fixing tests * removing extraneous char * Docs: Add more details on use case internals * 1511 field level locking (#1690) * Adding survey editor update * Field locking fully working, next fix broken tests * Fixing tests * Update Vagrantfile * Remove extra files * Updating counts * Adding entity fields * Removing unneeded include, simplifying function * Adding task restriction * Adding form stage and attribute restriction * Fixed stage tests * Updated attribute filitering and added tests * Fixed linting * Fixing base data set * Fixing tests * removing extraneous char * Fixing access permissions * Fixing test * Improve categories (#1670) * adding forms-tags-table #1397 * adding helper-functions for updating forms-tags-relations #1397 * updating forms_tags-table when updating a tag #1397 * updating forms_tags-table when updating/creating an attribute #1397 * adding search-fields for tags #1397 * adding tags to form #1397 * updating forms_tags-table when adding a new survey #1397 * changing naming to tags #1397 * removing updating form_tags when saving an attribute, had got the relation wrong #1397 * lint * not returning all posts when search->tags is empty #1397 * updating form_attributes when tag is deleted #1397 * updating forms-tags relation when form is updated #1397 * removing old forgotten debug-logging * resetting post-category-filtering to normal #1397 * adding child-tag-ids to tag #1397 * adding migrations for tags #1397 * fixing failing test #1397 * linting + fix comment from review #1397 * adding migration to move post-tag-values to post_varchar #1397 * Adds language to user (#1659) * adding language to user #1651 * fixing linting and removing comment #1651 * lint #1651 * Fix from QA (#1705) * adding forms-tags-table #1397 * adding helper-functions for updating forms-tags-relations #1397 * updating forms_tags-table when updating a tag #1397 * updating forms_tags-table when updating/creating an attribute #1397 * adding search-fields for tags #1397 * adding tags to form #1397 * updating forms_tags-table when adding a new survey #1397 * changing naming to tags #1397 * removing updating form_tags when saving an attribute, had got the relation wrong #1397 * lint * not returning all posts when search->tags is empty #1397 * updating form_attributes when tag is deleted #1397 * updating forms-tags relation when form is updated #1397 * removing old forgotten debug-logging * resetting post-category-filtering to normal #1397 * adding child-tag-ids to tag #1397 * adding migrations for tags #1397 * fixing failing test #1397 * linting + fix comment from review #1397 * adding migration to move post-tag-values to post_varchar #1397 * fixing id-error when updating a survey #1397 * Update composer dependencies (#1666) * Rearranging tests out of application/ into tests/ * Update composer packages to recent versions - Update PHPUnit - Update Behat - Update PHPSpec - Update aura/di to remove custom fork - Switch flysystem to 1.0 not 1.1 dev - Update phinx - Update phpunit tests for new version - Update behat tests for new version * Fix DI to work without auto resolving enabled * Run codeship builds on PHP 5.6 * Fix travis builds * Remove bin/tests * Fix phpunit tests failing while trying to backup globals Tests were failing with "Serialization of 'Closure' is not allowed" * Ignore tests/ for linting * fixup lint * Fix PHPUnit code coverage, and fix some bugs too * Don't inject Signer into webhook command Signer is just overwritten anyway, no need to inject it. Injection was broken because we didn't pass an auth token * Fix bin/ushahidi for new symfony/console version * Fixup coverage reporting from travis * Try to fix sending files to coveralls * Add PHP 7.1 to travis builds * Exclude php 7.1+coverage build * Add laravel/homestead box and remove puppet scripts * Update ohanzee/database to our fork, and select only aggregates when counting Mysql 5.7 doesn't like selecting both grouped and non grouped info in the same query. So we're not resetting the select fields before adding aggregates (ie. count) to the query * Remove posts?current_stage filter as its not working, and fails hard in mysql 5.7 * Set mysql strict mode in travis * Reset order by clause when fetching count queries too * Fix posts stats to work with mysql only_full_group_by mode * Output mysql version from travis builds * Use MAX() instead of ANY_VALUE() in queries ANY_VALUE only exists in mysql 5.7+ --- .env.travis | 5 + .travis.yml | 20 +- Homestead.yaml | 27 + Puppetfile | 6 - Vagrantfile | 76 +- application/classes/ORM.php | 22 - .../classes/Unittest/Database/TestCase.php | 60 - .../classes/Ushahidi/Console/Webhook.php | 6 - application/classes/Ushahidi/Core.php | 2 +- application/classes/Ushahidi/Repository.php | 5 +- .../classes/Ushahidi/Repository/Post.php | 80 +- .../classes/Ushahidi/Repository/Tag.php | 16 +- application/kohana.php | 6 +- .../features/bootstrap/FeatureContext.php | 163 - behat.yml.dist | 50 +- bin/tests | 297 -- composer.json | 61 +- composer.lock | 4149 +++++++++-------- docker/build.Dockerfile | 4 +- docker/test.Dockerfile | 4 +- httpdocs/coverage.php | 9 +- phpspec.yml.dist | 1 + phpunit.xml.dist | 14 +- puppet/platform/environment.conf | 1 - puppet/platform/manifests/site.pp | 173 - .../modules/platform/templates/env.erb | 5 - .../modules/platform/templates/htaccess.erb | 22 - .../platform/templates/php-defaults.erb | 4 - src/App/FilesystemAdapter/Rackspace.php | 4 +- src/Console/Command.php | 5 +- src/Core/Usecase/Post/StatsPostRepository.php | 2 +- src/Init.php | 9 +- {application/tests => tests}/bootstrap.php | 4 +- .../datasets/ushahidi/Base.yml | 0 .../datasets/ushahidi/sample-large.png | Bin .../datasets/ushahidi/sample.csv | 0 .../datasets/ushahidi/sample.png | Bin .../integration/acl.feature | 0 .../integration/bootstrap/FeatureContext.php | 85 + .../bootstrap/MinkExtendedContext.php | 14 +- .../bootstrap/PHPUnitFixtureContext.php | 56 +- .../integration}/bootstrap/RestContext.php | 40 +- .../integration/collections.feature | 0 .../integration/collections/posts.feature | 0 .../integration/config.feature | 0 .../integration/contacts.feature | 0 .../integration/csv.feature | 0 .../data-provider/frontlinesms.feature | 0 .../data-provider/smssync.feature | 0 .../integration/dataproviders.feature | 0 .../integration/forms.feature | 0 .../integration/forms/attributes.feature | 0 .../integration/forms/stages.feature | 0 .../integration/layers.feature | 0 .../integration/media.feature | 4 +- .../integration/messages.feature | 0 .../integration/migration.feature | 0 .../integration/notifications.feature | 0 .../integration/oauth.feature | 0 .../integration/permissions.feature | 0 .../integration/posts.feature | 28 - .../integration/posts/geojson.feature | 0 .../integration/posts/revisions.feature | 0 .../integration/posts/translations.feature | 0 .../integration/posts/updates.feature | 0 .../integration/roles.feature | 0 .../integration/savedsearch.feature | 0 .../integration/stats.feature | 0 .../integration/tags.feature | 0 .../integration/users.feature | 0 .../integration/users/users.me.feature | 0 .../integration/webhooks.feature | 0 {spec => tests/spec}/Core/Tool/DateSpec.php | 0 .../spec}/Core/Tool/UploaderSpec.php | 0 .../spec}/Core/Usecase/CreateUsecaseSpec.php | 0 .../spec}/Core/Usecase/DeleteUsecaseSpec.php | 0 .../Usecase/Message/ReceiveMessageSpec.php | 0 .../spec}/Core/Usecase/ReadUsecaseSpec.php | 0 .../spec}/Core/Usecase/SearchUsecaseSpec.php | 0 .../spec}/Core/Usecase/UpdateUsecaseSpec.php | 0 .../spec}/Core/Usecase/User/LoginUserSpec.php | 0 {spec => tests/spec}/ruleset.xml | 0 .../unit}/Core/Traits/DataTranformerTest.php | 6 +- .../unit}/Ushahidi/PostValueTest.php | 10 +- .../unit}/Util/BoundingBoxTest.php | 18 +- .../classes => tests/unit}/Util/TileTest.php | 20 +- 86 files changed, 2727 insertions(+), 2866 deletions(-) create mode 100644 .env.travis create mode 100644 Homestead.yaml delete mode 100644 Puppetfile delete mode 100755 application/classes/ORM.php delete mode 100644 application/classes/Unittest/Database/TestCase.php delete mode 100644 application/tests/features/bootstrap/FeatureContext.php delete mode 100755 bin/tests delete mode 100644 puppet/platform/environment.conf delete mode 100644 puppet/platform/manifests/site.pp delete mode 100644 puppet/platform/modules/platform/templates/env.erb delete mode 100644 puppet/platform/modules/platform/templates/htaccess.erb delete mode 100644 puppet/platform/modules/platform/templates/php-defaults.erb rename {application/tests => tests}/bootstrap.php (76%) rename {application/tests => tests}/datasets/ushahidi/Base.yml (100%) rename {application/tests => tests}/datasets/ushahidi/sample-large.png (100%) rename {application/tests => tests}/datasets/ushahidi/sample.csv (100%) rename {application/tests => tests}/datasets/ushahidi/sample.png (100%) rename application/tests/features/api.acl.feature => tests/integration/acl.feature (100%) create mode 100644 tests/integration/bootstrap/FeatureContext.php rename {application/tests/features => tests/integration}/bootstrap/MinkExtendedContext.php (99%) rename {application/tests/features => tests/integration}/bootstrap/PHPUnitFixtureContext.php (64%) rename {application/tests/features => tests/integration}/bootstrap/RestContext.php (95%) rename application/tests/features/api.collections.feature => tests/integration/collections.feature (100%) rename application/tests/features/collections/api.posts.feature => tests/integration/collections/posts.feature (100%) rename application/tests/features/api.config.feature => tests/integration/config.feature (100%) rename application/tests/features/api.contacts.feature => tests/integration/contacts.feature (100%) rename application/tests/features/api.csv.feature => tests/integration/csv.feature (100%) rename {application/tests/features => tests/integration}/data-provider/frontlinesms.feature (100%) rename {application/tests/features => tests/integration}/data-provider/smssync.feature (100%) rename application/tests/features/api.dataproviders.feature => tests/integration/dataproviders.feature (100%) rename application/tests/features/api.forms.feature => tests/integration/forms.feature (100%) rename application/tests/features/forms/api.attributes.feature => tests/integration/forms/attributes.feature (100%) rename application/tests/features/forms/api.stages.feature => tests/integration/forms/stages.feature (100%) rename application/tests/features/api.layers.feature => tests/integration/layers.feature (100%) rename application/tests/features/api.media.feature => tests/integration/media.feature (97%) rename application/tests/features/api.messages.feature => tests/integration/messages.feature (100%) rename application/tests/features/api.migration.feature => tests/integration/migration.feature (100%) rename application/tests/features/api.notifications.feature => tests/integration/notifications.feature (100%) rename application/tests/features/api.oauth.feature => tests/integration/oauth.feature (100%) rename application/tests/features/api.permissions.feature => tests/integration/permissions.feature (100%) rename application/tests/features/api.posts.feature => tests/integration/posts.feature (98%) rename application/tests/features/posts/api.geojson.feature => tests/integration/posts/geojson.feature (100%) rename application/tests/features/posts/api.revisions.feature => tests/integration/posts/revisions.feature (100%) rename application/tests/features/posts/api.translations.feature => tests/integration/posts/translations.feature (100%) rename application/tests/features/posts/api.updates.feature => tests/integration/posts/updates.feature (100%) rename application/tests/features/api.roles.feature => tests/integration/roles.feature (100%) rename application/tests/features/api.savedsearch.feature => tests/integration/savedsearch.feature (100%) rename application/tests/features/api.stats.feature => tests/integration/stats.feature (100%) rename application/tests/features/api.tags.feature => tests/integration/tags.feature (100%) rename application/tests/features/api.users.feature => tests/integration/users.feature (100%) rename application/tests/features/users/api.users.me.feature => tests/integration/users/users.me.feature (100%) rename application/tests/features/api.webhooks.feature => tests/integration/webhooks.feature (100%) rename {spec => tests/spec}/Core/Tool/DateSpec.php (100%) rename {spec => tests/spec}/Core/Tool/UploaderSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/CreateUsecaseSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/DeleteUsecaseSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/Message/ReceiveMessageSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/ReadUsecaseSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/SearchUsecaseSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/UpdateUsecaseSpec.php (100%) rename {spec => tests/spec}/Core/Usecase/User/LoginUserSpec.php (100%) rename {spec => tests/spec}/ruleset.xml (100%) rename {application/tests/classes => tests/unit}/Core/Traits/DataTranformerTest.php (92%) rename {application/tests/classes => tests/unit}/Ushahidi/PostValueTest.php (88%) rename {application/tests/classes => tests/unit}/Util/BoundingBoxTest.php (91%) rename {application/tests/classes => tests/unit}/Util/TileTest.php (95%) diff --git a/.env.travis b/.env.travis new file mode 100644 index 0000000000..ee2f7476ba --- /dev/null +++ b/.env.travis @@ -0,0 +1,5 @@ +DB_TYPE=MySQLi +DB_HOST=127.0.0.1 +DB_NAME=ushahidi +DB_PASS= +DB_USER=travis diff --git a/.travis.yml b/.travis.yml index 00b520b42e..f053b1ded0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,30 +4,42 @@ sudo: false # secure: NxhzhKGYnZYZiWVZM4w1PlZpTy9bbmNlvbqjL+9d4PvK4hFzPwQU12CchhBPeXNGLWBHg/ti6Scn/t5XIS3YJrkk4ydWmJBht5UId8uFZ1A7GCUnNNPTt2RG55lbJJdZSj01rOGZjEQbE5RyckEjgRzhZjdZ+HsjoPaRzWIBrvE= language: php php: -- '5.5' - '5.6' +- '7.0' +- '7.1' env: - coverage="--coverage" - coverage="" matrix: exclude: - - php: '5.5' + - php: '7.0' + env: coverage="--coverage" + - php: '7.1' env: coverage="--coverage" allow_failures: - env: coverage="--coverage" + - php: '7.1' fast_finish: true cache: directories: - "$HOME/.composer/cache" services: - mysql +before_install: +- mysql -e 'CREATE DATABASE ushahidi;' +- mysql -e "select version();" +- mysql -e "SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'" +- cp .env.travis .env install: - composer install --no-interaction before_script: -- "./bin/tests install" +- composer pre-test +- if [ "${coverage}" == "" ]; then php -S localhost:8000 -t httpdocs httpdocs/index.php & fi +- if [ "${coverage}" != "" ]; then php -S localhost:8000 -t httpdocs httpdocs/coverage.php & fi - mysql -e 'SET @@GLOBAL.wait_timeout=1800' script: -- "./bin/tests run --no-install $coverage" +- if [ "${coverage}" == "" ]; then composer test; fi +- if [ "${coverage}" != "" ]; then composer run coverage --timeout=0; fi - composer lint after_success: - if [ "${coverage}" != "" ]; then travis_retry bin/coveralls -v; fi diff --git a/Homestead.yaml b/Homestead.yaml new file mode 100644 index 0000000000..85fb500a08 --- /dev/null +++ b/Homestead.yaml @@ -0,0 +1,27 @@ +ip: 192.168.33.110 +memory: 1024 +cpus: 1 +provider: virtualbox +authorize: ~/.ssh/id_rsa.pub +keys: + - ~/.ssh/id_rsa +folders: + - + map: "./" + to: /vagrant + type: "nfs" + - + map: "./" + to: /home/vagrant/Code/platform-api + type: "nfs" +sites: + - + map: api.ushahidi.app + to: /home/vagrant/Code/platform-api/httpdocs + - + map: ushv3.dev + to: /home/vagrant/Code/platform-api/httpdocs +databases: + - ushahidi +name: platform-api +hostname: platform-api diff --git a/Puppetfile b/Puppetfile deleted file mode 100644 index 8f243c9a21..0000000000 --- a/Puppetfile +++ /dev/null @@ -1,6 +0,0 @@ -forge "https://forgeapi.puppetlabs.com" - -mod "puppetlabs/apt" -mod "puppetlabs/mysql" -mod "puppetlabs/apache" -mod "tPl0ch/composer" diff --git a/Vagrantfile b/Vagrantfile index 5069ca4f7a..25e0fd1f40 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,34 +1,44 @@ -# Basic apache dev box complete with phpunit -# ready to go for ushahidi dev -Vagrant.configure("2") do |config| - config.vm.box = "puppetlabs/ubuntu-14.04-64-puppet" # vagrantcloud - config.vm.hostname = "ushahidi-platform.dev" - config.vm.network "private_network", ip: "192.168.33.110" - config.vm.synced_folder "./", "/var/www", id: "vagrant-root", :nfs => true - config.vm.network "forwarded_port", guest: 22, host: 2210 - config.ssh.port = 2210 - - config.vm.provider :virtualbox do |virtualbox| - virtualbox.customize ["modifyvm", :id, "--name", "ushahidi-platform"] - virtualbox.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] - virtualbox.customize ["modifyvm", :id, "--memory", "512"] - virtualbox.customize ["setextradata", :id, "--VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"] - end - - config.vm.provision :shell do |shell| - # upgrade all packages (including puppet) before using the puppet provisioner. - # this excludes grub-pc since the hard drive id changes between VMs and will cause - # an interactive prompt to appear and then error out, breaking the provisioning step. - shell.inline = "DEBIAN_FRONTEND=noninteractive apt-mark hold grub-pc && apt-get update -y && apt-get upgrade -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'" - end - - config.vm.provision :puppet do |puppet| - puppet.environment_path = "puppet/" - puppet.environment = "platform" - puppet.options = ["--verbose"] - puppet.facter = { - # Optionally pass in a github oauth token through an environment variable - "github_token" => ENV.fetch('github_token', '') - } - end +# -*- mode: ruby -*- +# vi: set ft=ruby : + +require 'json' +require 'yaml' + +VAGRANTFILE_API_VERSION ||= "2" +confDir = $confDir ||= File.expand_path("vendor/laravel/homestead", File.dirname(__FILE__)) + +homesteadYamlPath = File.expand_path("Homestead.yaml", File.dirname(__FILE__)) +homesteadJsonPath = File.expand_path("Homestead.json", File.dirname(__FILE__)) +afterScriptPath = "after.sh" +aliasesPath = "aliases" + +require File.expand_path(confDir + '/scripts/homestead.rb') + +Vagrant.require_version '>= 1.9.0' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + if File.exist? aliasesPath then + config.vm.provision "file", source: aliasesPath, destination: "/tmp/bash_aliases" + config.vm.provision "shell" do |s| + s.inline = "awk '{ sub(\"\r$\", \"\"); print }' /tmp/bash_aliases > /home/vagrant/.bash_aliases" + end + end + + if File.exist? homesteadYamlPath then + settings = YAML::load(File.read(homesteadYamlPath)) + elsif File.exist? homesteadJsonPath then + settings = JSON.parse(File.read(homesteadJsonPath)) + else + abort "Homestead settings file not found in #{confDir}" + end + + Homestead.configure(config, settings) + + if File.exist? afterScriptPath then + config.vm.provision "shell", path: afterScriptPath, privileged: false + end + + if defined? VagrantPlugins::HostsUpdater + config.hostsupdater.aliases = settings['sites'].map { |site| site['map'] } + end end diff --git a/application/classes/ORM.php b/application/classes/ORM.php deleted file mode 100755 index 357cde9c57..0000000000 --- a/application/classes/ORM.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @package Ushahidi\Application\Models - * @copyright 2013 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -class ORM extends Kohana_ORM { - - /** - * Callback function to check if fk exists - */ - public function fk_exists($model_name, $field, $value) - { - return ORM::factory($model_name, $value)->loaded(); - } - -} diff --git a/application/classes/Unittest/Database/TestCase.php b/application/classes/Unittest/Database/TestCase.php deleted file mode 100644 index e333c48540..0000000000 --- a/application/classes/Unittest/Database/TestCase.php +++ /dev/null @@ -1,60 +0,0 @@ - - * @package Ushahidi\Unittest - * @copyright 2013 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -abstract class Unittest_Database_TestCase extends Kohana_Unittest_Database_TestCase { - - /** - * Creates a connection to the unittesting database - * Overriding to fix database type in DSN - must be lowercase - * - * @return PDO - */ - public function getConnection() - { - // Get the unittesting db connection - $config = Kohana::$config->load('database.'.$this->_database_connection); - - if($config['type'] !== 'pdo') - { - // Replace MySQLi with MySQL since MySQLi isn't valid for a DSN - $type = $config['type'] === 'MySQLi' ? 'MySQL' : $config['type']; - - $config['connection']['dsn'] = strtolower($type).':'. - 'host='.$config['connection']['hostname'].';'. - 'dbname='.$config['connection']['database']; - } - - $pdo = new PDO( - $config['connection']['dsn'], - $config['connection']['username'], - $config['connection']['password'] - ); - - return $this->createDefaultDBConnection($pdo, $config['connection']['database']); - } - - /** - * Returns the database operation executed in test setup. - * Overriding to fix Mysql 5.5 truncate errors - * - * @return PHPUnit_Extensions_Database_Operation_DatabaseOperation - */ - protected function getSetUpOperation() - { - //return PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT(); - $cascadeTruncates = TRUE; - return new PHPUnit_Extensions_Database_Operation_Composite(array( - new Unittest_Database_Operation_MySQL55Truncate($cascadeTruncates), - PHPUnit_Extensions_Database_Operation_Factory::INSERT() - )); - } - -} diff --git a/application/classes/Ushahidi/Console/Webhook.php b/application/classes/Ushahidi/Console/Webhook.php index 98f8f27be5..9386ff2e30 100644 --- a/application/classes/Ushahidi/Console/Webhook.php +++ b/application/classes/Ushahidi/Console/Webhook.php @@ -30,7 +30,6 @@ class Ushahidi_Console_Webhook extends Command private $postRepository; private $webhookRepository; private $webhookJobRepository; - private $signer; private $client; public function setDatabase(Database $db) @@ -48,11 +47,6 @@ public function setPostRepo(PostRepository $repo) $this->postRepository = $repo; } - public function setSigner(Signer $signer) - { - $this->signer = $signer; - } - public function setWebhookJobRepo(WebhookJobRepository $repo) { $this->webhookJobRepository = $repo; diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 4774fbf91c..578281d77f 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -149,7 +149,6 @@ public static function init() $di->setter['Ushahidi\Console\Application']['injectCommands'][] = $di->lazyNew('Ushahidi_Console_Webhook'); $di->setter['Ushahidi_Console_Webhook']['setDatabase'] = $di->lazyGet('kohana.db'); $di->setter['Ushahidi_Console_Webhook']['setPostRepo'] = $di->lazyGet('repository.post'); - $di->setter['Ushahidi_Console_Webhook']['setSigner'] = $di->lazyGet('tool.signer'); $di->setter['Ushahidi_Console_Webhook']['setWebhookRepo'] = $di->lazyGet('repository.webhook'); $di->setter['Ushahidi_Console_Webhook']['setWebhookJobRepo'] = $di->lazyGet('repository.webhook.job'); @@ -289,6 +288,7 @@ public static function init() // Validation Trait $di->setter['Ushahidi\Core\Tool\ValidationEngineTrait']['setValidation'] = $di->newFactory('Ushahidi_ValidationEngine'); + $di->params['Ushahidi_ValidationEngine']['array'] = []; // Formatter mapping $di->params['Ushahidi\Factory\FormatterFactory']['map'] = [ diff --git a/application/classes/Ushahidi/Repository.php b/application/classes/Ushahidi/Repository.php index 992a3a8830..04646d3fdc 100644 --- a/application/classes/Ushahidi/Repository.php +++ b/application/classes/Ushahidi/Repository.php @@ -128,6 +128,7 @@ public function getSearchTotal() { // Assume we can simply count the results to get a total $query = $this->getSearchQuery(true) + ->resetSelect() ->select([DB::expr('COUNT(*)'), 'total']); // Fetch the result and... @@ -170,7 +171,8 @@ protected function getSearchQuery($countable = false) if ($countable) { $query ->limit(null) - ->offset(null); + ->offset(null) + ->resetOrderBy(); } return $query; @@ -197,6 +199,7 @@ protected function selectOne(Array $where = []) protected function selectCount(Array $where = []) { $result = $this->selectQuery($where) + ->resetSelect() ->select([DB::expr('COUNT(*)'), 'total']) ->execute($this->db); return $result->get('total') ?: 0; diff --git a/application/classes/Ushahidi/Repository/Post.php b/application/classes/Ushahidi/Repository/Post.php index e875ee555f..1c0cc7671f 100644 --- a/application/classes/Ushahidi/Repository/Post.php +++ b/application/classes/Ushahidi/Repository/Post.php @@ -224,7 +224,7 @@ public function getSearchFields() 'created_before', 'created_after', 'updated_before', 'updated_after', 'date_before', 'date_after', - 'bbox', 'tags', 'values', 'current_stage', + 'bbox', 'tags', 'values', 'center_point', 'within_km', 'published_to', 'include_types', 'include_attributes', // Specify values to include @@ -415,75 +415,6 @@ protected function setSearchConditions(SearchData $search) ->from('post_point')); } - if ($search->current_stage) { - $stages = $search->current_stage; - if (!is_array($stages)) { - $stages = explode(',', $stages); - } - - /** - * Here be dragons - * The purpose of this query is to return the set of posts which - * have current stage X. In this case, current stage X is actually the - * the stage the post has NOT yet completed - which is the stage with. - * the lowest priority. - * For example: - * If I have 3 stages for a given Post Type, I am on stage 1 if - * I have completed no stages and I am on stage 3 if I have completed - * stages 1 and 2. - * If I have completed stages 1 and 3, I am on stage 2 as stages are considered - * to be sequential - */ - - /** - * This query is responsible for returning all the - * stages for a given post id, where the stage has been completed. - * This is used to check which stages the Post has not yet completed - */ - - $stages_posts = DB::select('form_stage_id') - ->from('form_stages_posts') - ->where('post_id', '=', DB::expr('posts.id')) - ->and_where('completed', '=', '1'); - - /** - * This query returns the IDs for the stages that we are filtering by - */ - $forms_sub = DB::select('form_stages.form_id') - ->from('form_stages') - ->where('form_stages.id', 'IN', $stages); - - /** - * This is the master query, it collects all the posts - * missing stages that we are filtering by. - */ - $sub = DB::select(array('posts.id','p_id'), array('form_stages.id', 'fs_id'), 'priority', 'posts.form_id', 'forms.id') - ->from('posts') - ->join('forms') - // Here we join to the forms table based on the set of stage ids we are filtering by - ->on('posts.form_id', '=', 'forms.id') - ->on('forms.id', 'IN', $forms_sub) - ->join('form_stages') - // Here we join to the form_stages table based on the form id - // and a check that the current post has not already completed this stage - ->on('form_stages.form_id', 'IN', $forms_sub) - ->on('form_stages.id', 'NOT IN', $stages_posts) - // We group the results by post id - ->group_by('p_id') - // We reduce the list to ensure that only results missing the stages to filter by are returned - ->having('form_stages.id', 'IN', $stages) - // Finally we order the results by priority to ensure that if, for example, - // a post is missing multiple stages we only consider the first uncompleted stage - ->order_by('priority'); - - //This step wraps the query and returns only the posts ids without the extra data such as form, stage or priority - $posts_sub = DB::select('p_id') - ->from(array($sub, 'sub')); - - $query - ->where('posts.id', 'IN', $posts_sub); - } - // Filter by tag if (!empty($search->tags)) { @@ -579,6 +510,7 @@ public function getSearchTotal() { // Assume we can simply count the results to get a total $query = $this->getSearchQuery(true) + ->resetSelect() ->select([DB::expr('COUNT(DISTINCT posts.id)'), 'total']); // Fetch the result and... @@ -686,9 +618,10 @@ public function getGroupedTotals(SearchData $search) { $this->search_query ->join('forms', 'LEFT')->on('posts.form_id', '=', 'forms.id') - ->select(['forms.name', 'label']) + // This should really use ANY_VALUE(forms.name) but that only exists in mysql5.7 + ->select([DB::expr('MAX(forms.name)'), 'label']) ->select(['forms.id', 'id']) - ->group_by('posts.form_id'); + ->group_by('forms.id'); } // Group by tags elseif ($search->group_by === 'tags') @@ -714,7 +647,8 @@ public function getGroupedTotals(SearchData $search) ->join(['tags', 'parents']) // Slight hack to avoid kohana db forcing multiple ON clauses to use AND not OR. ->on(DB::expr("`parents`.`id` = `tags`.`parent_id` OR `parents`.`id` = `posts_tags`.`tag_id`"), '', DB::expr("")) - ->select(['parents.tag', 'label']) + // This should really use ANY_VALUE(forms.name) but that only exists in mysql5.7 + ->select([DB::expr('MAX(parents.tag)'), 'label']) ->select(['parents.id', 'id']) ->group_by('parents.id'); diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 8aa1de1bc5..76421eb19e 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -40,13 +40,13 @@ protected function getTable() // ReadRepository public function getEntity(Array $data = null) { - if (!empty($data['id'])) + if (!empty($data['id'])) { $data['forms'] = $this->getFormsForTag($data['id']); - + if(empty($data['parent_id'])) { - - $data['children'] = + + $data['children'] = DB::select('id') ->from('tags') ->where('parent_id','=',$data['id']) @@ -84,7 +84,7 @@ protected function setSearchConditions(SearchData $search) $query->where('tag', 'LIKE', "%{$search->q}%"); } if($search->level) { - //searching for top-level-tags + //searching for top-level-tags if($search->level === 'parent') { $query->where('parent_id', '=', null); } @@ -94,7 +94,8 @@ protected function setSearchConditions(SearchData $search) ->on('tags.id', '=', 'forms_tags.tag_id') ->where('form_id','=', $search->formId); } - } + } + // SearchRepository public function getSearchResults() { @@ -120,7 +121,7 @@ public function create(Entity $entity) return $id; } - + public function update(Entity $entity) { $tag = $entity->getChanged(); @@ -147,6 +148,7 @@ public function getByTag($tag) public function doesTagExist($tag_or_id) { $query = $this->selectQuery() + ->resetSelect() ->select([DB::expr('COUNT(*)'), 'total']) ->where('id', '=', $tag_or_id) ->or_where('tag', '=', $tag_or_id) diff --git a/application/kohana.php b/application/kohana.php index 920c4dc628..6818534d34 100644 --- a/application/kohana.php +++ b/application/kohana.php @@ -101,7 +101,11 @@ // Load dotenv if (is_file(APPPATH.'../.env')) { - Dotenv::load(APPPATH.'../'); + try { + (new Dotenv\Dotenv(APPPATH.'/../'))->load(); + } catch (Dotenv\Exception\InvalidPathException $e) { + // + } } // Bootstrap the application diff --git a/application/tests/features/bootstrap/FeatureContext.php b/application/tests/features/bootstrap/FeatureContext.php deleted file mode 100644 index 787b7400f6..0000000000 --- a/application/tests/features/bootstrap/FeatureContext.php +++ /dev/null @@ -1,163 +0,0 @@ - - * @package Ushahidi\Application\Tests - * @copyright 2013 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -// Load bootstrap to hook into Kohana -require_once __DIR__.'/../../bootstrap.php'; - -use Behat\Behat\Context\ClosuredContextInterface, - Behat\Behat\Context\TranslatedContextInterface, - Behat\Behat\Context\BehatContext, - Behat\Behat\Exception\PendingException; -use Behat\Gherkin\Node\PyStringNode, - Behat\Gherkin\Node\TableNode; -use Behat\Behat\Event\FeatureEvent; - -/** - * Features context. - */ -class FeatureContext extends BehatContext -{ - /** - * Initializes context. - * Every scenario gets it's own context object. - * - * @param array $parameters context parameters (set them up through behat.yml) - */ - public function __construct(array $parameters) - { - // Initialize your context here - $this->useContext('RestContext', new RestContext($parameters)); - $this->useContext('PHPUnitFixtureContext', new PHPUnitFixtureContext($parameters)); - $this->useContext('MinkContext', $minkContext = new MinkExtendedContext); - } - - /** @BeforeFeature */ - public static function featureSetup(FeatureEvent $event) - { - $fixtureContext = new PHPUnitFixtureContext($event->getParameters()); - $fixtureContext->setUpDBTester('ushahidi/Base'); - - $pdo_connection = $fixtureContext->getConnection()->getConnection(); - self::insertGeometryFixtures($pdo_connection); - } - - /** @AfterFeature */ - public static function featureTearDown(FeatureEvent $event) - { - $fixtureContext = new PHPUnitFixtureContext($event->getParameters()); - $fixtureContext->tearDownDBTester('ushahidi/Base'); - } - - /** @BeforeScenario @resetFixture */ - public function scenarioSetup() - { - $this->getSubcontext('PHPUnitFixtureContext')->setUpDBTester('ushahidi/Base'); - - $pdo_connection = $this->getSubcontext('PHPUnitFixtureContext')->getConnection()->getConnection(); - self::insertGeometryFixtures($pdo_connection); - } - - /** @BeforeScenario @private */ - public function makePrivate() - { - $config = Kohana::$config->load('site'); - $config->set('private', true); - - $config = Kohana::$config->load('features'); - $config->set('private.enabled', true); - } - - /** @AfterScenario @private */ - public function makePublic() - { - $config = Kohana::$config->load('site'); - $config->set('private', false); - - $config = Kohana::$config->load('features'); - $config->set('private.enabled', false); - } - - /** @BeforeScenario @rolesEnabled */ - public function enableRoles() - { - $config = Kohana::$config->load('features'); - $config->set('roles.enabled', true); - } - - /** @AfterScenario @rolesEnabled */ - public function disableRoles() - { - $config = Kohana::$config->load('features'); - $config->set('roles.enabled', false); - } - - /** @BeforeScenario @webhooksEnabled */ - public function enableWebhooks() - { - $config = Kohana::$config->load('features'); - $config->set('webhooks.enabled', true); - } - - /** @AfterScenario @webhooksEnabled */ - public function disableWebhooks() - { - $config = Kohana::$config->load('features'); - $config->set('webhooks.enabled', false); - } - - /** @BeforeScenario @dataImportEnabled */ - public function enableDataImport() - { - $config = Kohana::$config->load('features'); - $config->set('data-import.enabled', true); - } - - /** @AfterScenario @dataImportEnabled */ - public function disableDataImport() - { - $config = Kohana::$config->load('features'); - $config->set('data-import.enabled', false); - } - - protected static function insertGeometryFixtures($pdo_connection) - { - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (1, 1, 8, POINT(12.123, 21.213));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (7, 1, 8, POINT(12.223, 21.313));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (2, 99, 8, POINT(11.123, 24.213));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (3, 9999, 8, POINT(10.123, 26.213));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (4, 95, 8, POINT(1, 1));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (5, 95, 12, POINT(1.2, 0.5));"); - $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (6, 97, 8, POINT(1, 1));"); - - $pdo_connection->query("INSERT INTO `post_geometry` (`id`, `post_id`, `form_attribute_id`, `value`) - VALUES (1, 1, 9, - GeomFromText('MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), - ((20 35, 45 20, 30 5, 10 10, 10 30, 20 35), - (30 20, 20 25, 20 15, 30 20)))'));"); - } - - /** - * Automatically set bearer token so you can forget about it - * @BeforeScenario @oauth2Skip - */ - public function setDefaultBearerAuth() - { - $this->getSubcontext('RestContext')->thatTheRequestHeaderIs('Authorization', 'Bearer defaulttoken'); - } - -} diff --git a/behat.yml.dist b/behat.yml.dist index 768aa19e68..aea9ad7b4f 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -2,25 +2,33 @@ ## Replace base_url values with the url of your dev site ## default: - paths: - features: application/tests/features - bootstrap: application/tests/features/bootstrap - formatter: - name: progress - filters: - tags: "~@dataproviders" - context: - parameters: - base_url: http://localhost:8000 -# proxy_url: localhost:8888 - extensions: - Behat\MinkExtension\Extension: - base_url: http://localhost:8000 - goutte: - guzzle_parameters: - curl.options: - 3 : 8000 #CURLOPT_PORT=3 -# 10004: localhost:8888 #CURLOPT_PROXY=10004 + formatters: + progress: true + suites: + default: + paths: + - %paths.base%/tests/integration + contexts: + - FeatureContext + - RestContext: + baseUrl: http://localhost:8000 + # proxyUrl: localhost:8888 + - PHPUnitFixtureContext + - MinkExtendedContext + filters: + tags: ~@dataproviders + extensions: + Behat\MinkExtension: + base_url: http://localhost:8000 + sessions: + default: + goutte: ~ + goutte: + guzzle_parameters: + curl.options: + 3 : 8000 #CURLOPT_PORT=3 + # 10004: localhost:8888 #CURLOPT_PROXY=10004 ci: - filters: - tags: + suites: + default: + filters: ~ diff --git a/bin/tests b/bin/tests deleted file mode 100755 index bec1be5063..0000000000 --- a/bin/tests +++ /dev/null @@ -1,297 +0,0 @@ -#!/usr/bin/env php - 'testing', - 'DB_TYPE' => 'MySQLi', - 'DB_HOST' => '127.0.0.1', - 'DB_NAME' => 'platform_test', - 'DB_PASS' => '', - 'DB_USER' => 'root' - ]; - - public function __construct() - { - parent::__construct(); - $this->dir = realpath(__DIR__ . '/../'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - $this->addOutputFormatting(); - } - - protected function install() - { - // change permissions - foreach ([ - "{$this->dir}/application/cache", - "{$this->dir}/application/logs", - ] as $file) { - chmod($file, 0777); - } - - // configure mysql, set up testing databases - $this->output->writeln("Configuring databases"); - $this->mysqlCommand('SET GLOBAL sql_mode = "STRICT_ALL_TABLES"'); - $this->mysqlCommand('DROP DATABASE IF EXISTS platform_test'); - $this->mysqlCommand('CREATE DATABASE platform_test'); - $this->mysqlCommand('DROP DATABASE IF EXISTS zombie2x'); - $this->mysqlCommand('CREATE DATABASE zombie2x'); - - // apply database migrations - $this->output->writeln("Migrating databases..."); - $this->execEnv("{$this->dir}/bin/phinx migrate -c {$this->dir}/application/phinx.php"); - - // if zombie2x.sql does not exist, download it - $zombie_sql_file = '/tmp/ushahidi-zombie2x.sql'; - if (!file_exists($zombie_sql_file)) - { - $this->downloadFile($this->test_database_sql_url, $zombie_sql_file); - } - - // import the zombies - $this->output->writeln("Importing test data"); - shell_exec("mysql -u root zombie2x < $zombie_sql_file"); - } - - protected function downloadFile($remote_file, $local_file) - { - $this->output->writeln("Downloading $remote_file"); - - $outfile = fopen($local_file, 'wb'); - - $progress = new ProgressBar($this->output, 100); - $progress->setFormat('[%bar%] %percent:3s%% (%elapsed% / %estimated:-6s%)'); - - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_FILE, $outfile); - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_URL, $remote_file); - curl_setopt($ch, CURLOPT_NOPROGRESS, false); - curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function() use ($progress) { - // curl versions 7.32 and below do not pass the - // $ch handler as the first argument to this function - $args = func_get_args(); - if (count($args) >= 5) { array_shift($args); } - - $total_down = $args[0]; - $current_down = $args[1]; - - if ($total_down === 0) { return; } - $progress->setCurrent(intval(($current_down / $total_down) * 100)); - }); - - curl_exec($ch); - $progress->finish(); - $this->output->writeln(''); - curl_close($ch); - fclose($outfile); - } - - protected function testServer($state, $coverage = FALSE) - { - if ($state === 'up' && !$this->test_server_pid) - { - $index = $coverage ? 'coverage' : 'index'; - $command = "php -S localhost:8000 -t {$this->dir}/httpdocs" - . " {$this->dir}/httpdocs/{$index}.php" - . " > /dev/null 2>&1 & echo $!;" - ; - - $this->test_server_pid = $this->execEnv($command); - $this->output->writeln("PHP server started (pid: {$this->test_server_pid})"); - sleep(3); - } - else if ($state === 'down' && $this->test_server_pid) - { - $this->output->writeln("Terminating PHP Server (pid: {$this->test_server_pid})"); - // Hack: hard coded fallback signal because OSX php is weird and doesn't have SIGTERM - $sigterm = defined('SIGTERM') ? SIGTERM : 15; - posix_kill($this->test_server_pid, $sigterm); - $this->test_server_pid = null; - } - } - - protected function execEnv($command, $return_exit_code = false, $env_vars = array()) - { - $env_vars = $env_vars ?: $this->env_variables; - array_walk($env_vars, function(&$value, $key) { - $value = "export $key=$value"; - }); - - $command = implode(';', $env_vars) . ";$command"; - - if ($return_exit_code) - { - passthru($command, $exit_code); - return $exit_code; - } - else - { - return exec($command); - } - } - - protected function mysqlCommand($command) - { - $command = escapeshellarg($command); - shell_exec("mysql -u root -e $command;"); - } - - protected function addOutputFormatting() - { - foreach ([ // custom output formatting - 'pass' => new OutputFormatterStyle('white', 'green', ['bold']), - 'fail' => new OutputFormatterStyle('white', 'red', ['bold']), - 'info' => new OutputFormatterStyle('white', 'blue', ['bold']), - ] as $tag => $style) { - $this->output->getFormatter()->setStyle($tag, $style); - } - } -} - -class UshahidiTestsRunCommand extends UshahidiTestsCommand -{ - protected function configure() - { - $this - ->setName('run') - ->setDescription('Runs all the tests and returns a single pass/fail result & exit code (default command)') - ->addOption( - 'no-install', - null, - InputOption::VALUE_NONE, - 'Don\'t install the prerequisites' - )->addOption( - 'coverage', - null, - InputOption::VALUE_NONE, - 'Enable code coverage' - ) - - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - parent::execute($input, $output); - - $this->output->writeln( - "\n Ushahidi Platform Tests \n" - ); - - $no_install = $input->getOption('no-install'); - if (!$no_install) { $this->install(); } - - $coverage = $input->getOption('coverage'); - if ($coverage) { - $coverage_dir = $this->dir . 'coverage'; - system('rm -rf ' . escapeshellarg($coverage_dir) . '/*'); // clear coverage - } - - // start the local test server - $this->testServer('up', $coverage); - - // we're optimistic - $tests_pass = true; - $test_start_time = time(); - - // run phpspec - chdir($this->dir); // phpspec won't find tests otherwise - $output->writeln("\n - Running Phpspec tests - "); - $phpspec_command = "{$this->dir}/bin/phpspec run --no-code-generation" - . ($coverage ? " -c phpspec.yml.dist" : " -c phpspec.yml.coverage"); - $tests_pass = ($this->execEnv($phpspec_command, true) === 0) && $tests_pass; - - // run behat - $output->writeln("\n - Running Behat tests - \n"); - $behat_cache = '/tmp/behat.cache'; - $behat_command = "{$this->dir}/bin/behat" - . " --config {$this->dir}/behat.yml.dist" - . " --cache $behat_cache" - . " --format progress" - . " --profile ci" - . " --strict" - ; - $tests_pass = ($this->execEnv($behat_command, true) === 0) && $tests_pass; - system('rm -rf ' . escapeshellarg($behat_cache)); // clear cache - - // run phpunit - $output->writeln("\n - Running PHPUnit tests - \n"); - $phpunit_command = "{$this->dir}/bin/phpunit" - . " -c {$this->dir}/phpunit.xml.dist" - . ($coverage ? "" : " --no-coverage") - ; - $tests_pass = ($this->execEnv($phpunit_command, true) === 0) && $tests_pass; - - // bring down the test server - $this->testServer('down'); - - $elapsed_time = time() - $test_start_time; - - // output a single pass/fail message - if ($tests_pass) - { - $output->writeln( - "\n All tests ran successfully! ($elapsed_time seconds)\n" - ); - } - else - { - $output->writeln( - "\n Some tests failed! \n" - ); - } - - // return a single exit code from the tests above - exit($tests_pass ? 0 : 1); - } -} - -class UshahidiTestsInstallCommand extends UshahidiTestsCommand -{ - protected function configure() - { - $this - ->setName('install') - ->setDescription('Install necessary prerequisites for running tests') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - parent::execute($input, $output); - $this->install(); - } -} - -$test_runner = new Application(); -$test_runner->add(new UshahidiTestsRunCommand); -$test_runner->add(new UshahidiTestsInstallCommand); -$test_runner->setDefaultCommand('run'); -$test_runner->run(); diff --git a/composer.json b/composer.json index 7f91d34a20..4928458de2 100644 --- a/composer.json +++ b/composer.json @@ -7,29 +7,29 @@ "repositories": [ { "type": "vcs", - "url": "https://github.com/ushahidi/Aura.Di" + "url": "https://github.com/ushahidi/ohanzee-db" } ], "require": { - "php": ">=5.4", - "aura/di": "dev-develop-2", + "php": ">=5.6.4", + "aura/di": "2.2", "bodom78/kohana-imagefly": "dev-master", "league/oauth2-server": "~3.2.4", - "league/flysystem-aws-s3-v3": "1.0.4", - "league/flysystem-rackspace": "1.0.1", - "league/flysystem": "1.1.*", + "league/flysystem-aws-s3-v3": "~1.0", + "league/flysystem-rackspace": "~1.0", + "league/flysystem": "~1.0", "ircmaxell/password-compat": "^1.0.4", "abraham/twitteroauth": "^0.5.3", "kohana/core" : "3.3.3.1@dev", "kohana/cache" : "3.3.*@dev", "kohana/image" : "3.3.*@dev", "kohana/minion" : "3.3.*@dev", - "ohanzee/database": "~0.1.2", - "robmorgan/phinx": "~0.4.1", + "ohanzee/database": "dev-master", + "robmorgan/phinx": "~0.8.0", "ushahidi/shadowhand-email": "dev-master", "symm/gisconverter": "~1.0.5", "twilio/sdk": "3.12.*", - "vlucas/phpdotenv": "~1.0@dev", + "vlucas/phpdotenv": "~2.2", "zeelot/kohana-media": "1.3.*@dev", "ext-curl": "*", "ext-gd": "*", @@ -44,26 +44,24 @@ "league/url": "~3.0", "beheh/flaps": "dev-master", "doctrine/cache": "^1.5@dev", - "satooshi/php-coveralls": "^2.0@dev", - "henrikbjorn/phpspec-code-coverage": "~2.0", "ramsey/uuid": "^3.4.1", "sentry/sentry": "~1.5" }, "require-dev": { - "behat/behat": "~2.5.2", - "behat/mink-extension": "~1.3", - "behat/mink-goutte-driver": "~1.0", - "fabpot/goutte": "~1.0", + "fzaninotto/faker": "~1.4", "guzzle/guzzle": "~3.9.1", - "kohana/unittest": "3.3.*@dev", - "phpunit/phpunit": "~4.8", + "phpunit/phpunit": "^5.7", "phpunit/dbunit": "~1.4", - "phpspec/phpspec": "~2.4", - "symfony/console": "2.6.*", + "phpspec/phpspec": "~3.0", "squizlabs/php_codesniffer": "1.5.*", - "heroku/heroku-buildpack-php": "dev-master" + "heroku/heroku-buildpack-php": "dev-master", + "behat/behat": "^3.3", + "behat/mink-extension": "^2.2", + "behat/mink-goutte-driver": "^1.2", + "satooshi/php-coveralls": "^2.0@dev", + "leanphp/phpspec-code-coverage": "~3.1", + "laravel/homestead": "^5.2" }, - "minimum-stability": "dev", "config": { "bin-dir": "bin/", "github-protocols": [ @@ -78,26 +76,35 @@ "Ushahidi\\": "src/" } }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true, "scripts": { "compile" : [ - "phinx migrate -c application/phinx.php" + "@migrate" ], "lint" : [ - "phpcs --ignore=vendor/*,application/*,modules/*,plugins/*,httpdocs/*,spec/*,migrations/*,bin/* --standard=PSR2 --tab-width=4 ./", - "phpcs --standard=spec/ruleset.xml --tab-width=4 ./spec/", + "phpcs --ignore=vendor/*,application/*,modules/*,plugins/*,httpdocs/*,tests/*,migrations/*,bin/* --standard=PSR2 --tab-width=4 ./", + "phpcs --standard=tests/spec/ruleset.xml --tab-width=4 ./tests/spec/", "phpcs --standard=migrations/ruleset.xml --tab-width=4 ./migrations/" ], "pre-coverage" : [ - "rm -rf coverage/", - "php -S localhost:8000 -t httpdocs httpdocs/coverage.php; echo $! > /tmp/platform.pid" + "rm -rf coverage/" ], "coverage" : [ "phpunit", "phpspec run --no-code-generation", "behat --strict --profile ci" ], + "migrate" : [ + "bin/phinx migrate -c application/phinx.php" + ], "pre-test" : [ - "php -S localhost:8000 -t httpdocs httpdocs/index.php &" + "@migrate" ], "test" : [ "phpunit --no-coverage", diff --git a/composer.lock b/composer.lock index 9851498716..f30f4cc48f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "80f5f2a629f10179d208c5f39defbb63", - "content-hash": "e9a0d55e5c7248704ae10e2ea6c99774", + "hash": "1986271af658ed65402813a01a5c1b2f", + "content-hash": "9a1bd95d142d72367d81fd19848ab737", "packages": [ { "name": "abraham/twitteroauth", @@ -63,16 +63,16 @@ }, { "name": "aura/di", - "version": "dev-develop-2", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/ushahidi/Aura.Di.git", - "reference": "1ce70099c1f1460d57a38611d20d2b6a9a4e0356" + "url": "https://github.com/auraphp/Aura.Di.git", + "reference": "8e167c9faca11a8fde3594e2e6e4a967aaad9bd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ushahidi/Aura.Di/zipball/1ce70099c1f1460d57a38611d20d2b6a9a4e0356", - "reference": "1ce70099c1f1460d57a38611d20d2b6a9a4e0356", + "url": "https://api.github.com/repos/auraphp/Aura.Di/zipball/8e167c9faca11a8fde3594e2e6e4a967aaad9bd1", + "reference": "8e167c9faca11a8fde3594e2e6e4a967aaad9bd1", "shasum": "" }, "require": { @@ -92,6 +92,7 @@ "Aura\\Di\\": "src/" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-2-Clause" ], @@ -110,29 +111,26 @@ "di", "di container" ], - "support": { - "source": "https://github.com/ushahidi/Aura.Di/tree/develop-2" - }, - "time": "2014-11-30 17:41:20" + "time": "2015-03-16 00:22:17" }, { "name": "aws/aws-sdk-php", - "version": "3.18.20", + "version": "3.25.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "e5a901dd3a42d0c46a90ee37a174938cd0ce55bf" + "reference": "8fc5e41cd5d4b965c552f52ac0efa726838c6f89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e5a901dd3a42d0c46a90ee37a174938cd0ce55bf", - "reference": "e5a901dd3a42d0c46a90ee37a174938cd0ce55bf", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8fc5e41cd5d4b965c552f52ac0efa726838c6f89", + "reference": "8fc5e41cd5d4b965c552f52ac0efa726838c6f89", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "~5.3|~6.0.1|~6.1", + "guzzlehttp/guzzle": "^5.3.1|^6.2.1", "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.0", + "guzzlehttp/psr7": "^1.4.1", "mtdowling/jmespath.php": "~2.2", "php": ">=5.5" }, @@ -193,7 +191,7 @@ "s3", "sdk" ], - "time": "2016-06-23 23:17:52" + "time": "2017-03-31 00:04:32" }, { "name": "beheh/flaps", @@ -201,12 +199,12 @@ "source": { "type": "git", "url": "https://github.com/beheh/flaps.git", - "reference": "9a7089d1d46e8450c1bea92474d9b512077e61af" + "reference": "f9b86524ed1c9bf12f5cb99da2d77f62a22f4d01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beheh/flaps/zipball/9a7089d1d46e8450c1bea92474d9b512077e61af", - "reference": "9a7089d1d46e8450c1bea92474d9b512077e61af", + "url": "https://api.github.com/repos/beheh/flaps/zipball/f9b86524ed1c9bf12f5cb99da2d77f62a22f4d01", + "reference": "f9b86524ed1c9bf12f5cb99da2d77f62a22f4d01", "shasum": "" }, "require": { @@ -246,7 +244,7 @@ "rate limit", "throttle" ], - "time": "2015-06-11 09:37:09" + "time": "2017-02-01 11:01:27" }, { "name": "bodom78/kohana-imagefly", @@ -291,16 +289,16 @@ }, { "name": "composer/installers", - "version": "dev-master", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/composer/installers.git", - "reference": "3c90d491bafa3d0a1bd57a7d001da839a08d2f88" + "reference": "d78064c68299743e0161004f2de3a0204e33b804" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/3c90d491bafa3d0a1bd57a7d001da839a08d2f88", - "reference": "3c90d491bafa3d0a1bd57a7d001da839a08d2f88", + "url": "https://api.github.com/repos/composer/installers/zipball/d78064c68299743e0161004f2de3a0204e33b804", + "reference": "d78064c68299743e0161004f2de3a0204e33b804", "shasum": "" }, "require": { @@ -347,6 +345,7 @@ "MODX Evo", "Mautic", "OXID", + "Plentymarkets", "RadPHP", "SMF", "Thelia", @@ -354,9 +353,11 @@ "agl", "aimeos", "annotatecms", + "attogram", "bitrix", "cakephp", "chef", + "cockpit", "codeigniter", "concrete5", "croogo", @@ -380,16 +381,18 @@ "piwik", "ppi", "puppet", + "reindex", "roundcube", "shopware", "silverstripe", "symfony", "typo3", "wordpress", + "yawik", "zend", "zikula" ], - "time": "2016-06-24 07:03:15" + "time": "2016-08-13 20:53:52" }, { "name": "ddeboer/data-import", @@ -397,12 +400,12 @@ "source": { "type": "git", "url": "https://github.com/ddeboer/data-import.git", - "reference": "8fe7e731bb52df0298707eb8fb8b9b8098395437" + "reference": "2107895beae45cffb19a5084b9d117f79d288d73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ddeboer/data-import/zipball/8fe7e731bb52df0298707eb8fb8b9b8098395437", - "reference": "8fe7e731bb52df0298707eb8fb8b9b8098395437", + "url": "https://api.github.com/repos/ddeboer/data-import/zipball/2107895beae45cffb19a5084b9d117f79d288d73", + "reference": "2107895beae45cffb19a5084b9d117f79d288d73", "shasum": "" }, "require": { @@ -461,20 +464,20 @@ "export", "import" ], - "time": "2016-06-23 06:26:02" + "time": "2017-01-22 10:07:40" }, { "name": "doctrine/cache", - "version": "dev-master", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "ce7c366e335378e8a11ef602820a8e12626f12d7" + "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/ce7c366e335378e8a11ef602820a8e12626f12d7", - "reference": "ce7c366e335378e8a11ef602820a8e12626f12d7", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3", + "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3", "shasum": "" }, "require": { @@ -485,12 +488,13 @@ }, "require-dev": { "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0" + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -530,74 +534,20 @@ "cache", "caching" ], - "time": "2016-06-21 12:14:15" - }, - { - "name": "doctrine/instantiator", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "416fb8ad1d095a87f1d21bc40711843cd122fd4a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/416fb8ad1d095a87f1d21bc40711843cd122fd4a", - "reference": "416fb8ad1d095a87f1d21bc40711843cd122fd4a", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2016-03-31 10:24:22" + "time": "2016-10-29 11:16:17" }, { "name": "guzzle/guzzle", - "version": "dev-master", + "version": "v3.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle3.git", - "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02" + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/b3f5050cb6270c7a728a0b74ac2de50a262b3e02", - "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", "shasum": "" }, "require": { @@ -680,31 +630,31 @@ "web service" ], "abandoned": "guzzlehttp/guzzle", - "time": "2015-04-29 17:06:53" + "time": "2015-03-18 18:23:50" }, { "name": "guzzlehttp/guzzle", - "version": "dev-master", + "version": "6.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "79c6fbef131eed51ab82bf813e9694419931bc8b" + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/79c6fbef131eed51ab82bf813e9694419931bc8b", - "reference": "79c6fbef131eed51ab82bf813e9694419931bc8b", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", "shasum": "" }, "require": { - "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.1", - "php": ">=5.5.0" + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" }, "type": "library", "extra": { @@ -742,32 +692,32 @@ "rest", "web service" ], - "time": "2016-06-20 07:37:14" + "time": "2017-02-28 22:50:30" }, { "name": "guzzlehttp/promises", - "version": "1.2.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "shasum": "" }, "require": { "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -793,20 +743,20 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-12-20 10:07:11" }, { "name": "guzzlehttp/psr7", - "version": "dev-master", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -842,72 +792,36 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" } ], - "description": "PSR-7 message implementation", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "request", + "response", "stream", - "uri" - ], - "time": "2016-06-24 23:00:38" - }, - { - "name": "henrikbjorn/phpspec-code-coverage", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/henrikbjorn/PhpSpecCodeCoverageExtension.git", - "reference": "528a0c69a524f8acba5f66bc59ae8dc9bc409045" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/henrikbjorn/PhpSpecCodeCoverageExtension/zipball/528a0c69a524f8acba5f66bc59ae8dc9bc409045", - "reference": "528a0c69a524f8acba5f66bc59ae8dc9bc409045", - "shasum": "" - }, - "require": { - "php": "^5.3.3|^5.4|^5.5|^5.6|^7.0", - "phpspec/phpspec": "^2.0", - "phpunit/php-code-coverage": "^2.2.4|^3" - }, - "require-dev": { - "bossa/phpspec2-expect": "^1.0" - }, - "suggest": { - "ext-xdebug": "To allow coverage generation when not using a recent version of phpdbg" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpSpec\\Extension\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" + "uri", + "url" ], - "description": "Integrates CodeCoverage with PhpSpec", - "time": "2016-05-05 18:25:12" + "time": "2017-03-20 17:10:46" }, { "name": "ircmaxell/password-compat", - "version": "1.0.x-dev", + "version": "v1.0.4", "source": { "type": "git", "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "9b99377557a33a4129c9194e60a97a685fab21e0" + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/9b99377557a33a4129c9194e60a97a685fab21e0", - "reference": "9b99377557a33a4129c9194e60a97a685fab21e0", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", "shasum": "" }, "require-dev": { @@ -936,11 +850,11 @@ "hashing", "password" ], - "time": "2014-11-20 19:18:42" + "time": "2014-11-20 16:49:30" }, { "name": "kohana/cache", - "version": "dev-3.3/develop", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/kohana/cache.git", @@ -1055,7 +969,7 @@ }, { "name": "kohana/image", - "version": "dev-3.3/develop", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/kohana/image.git", @@ -1115,7 +1029,7 @@ }, { "name": "kohana/minion", - "version": "dev-3.3/develop", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/kohana/minion.git", @@ -1233,12 +1147,12 @@ "source": { "type": "git", "url": "https://github.com/thephpleague/event.git", - "reference": "ebc612ba587ab9411ffefa276d72398c57517c50" + "reference": "0bfa3954c93a7b596168b4fd32d0e6631fd175e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/event/zipball/ebc612ba587ab9411ffefa276d72398c57517c50", - "reference": "ebc612ba587ab9411ffefa276d72398c57517c50", + "url": "https://api.github.com/repos/thephpleague/event/zipball/0bfa3954c93a7b596168b4fd32d0e6631fd175e2", + "reference": "0bfa3954c93a7b596168b4fd32d0e6631fd175e2", "shasum": "" }, "require": { @@ -1275,24 +1189,24 @@ "event", "listener" ], - "time": "2016-03-21 09:16:39" + "time": "2016-07-23 09:33:29" }, { "name": "league/flysystem", - "version": "dev-master", + "version": "1.0.37", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "b75910a746d1f3ae4b347bd95e86553b4d2e81cc" + "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b75910a746d1f3ae4b347bd95e86553b4d2e81cc", - "reference": "b75910a746d1f3ae4b347bd95e86553b4d2e81cc", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", + "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=5.5.9" }, "conflict": { "league/flysystem-sftp": "<1.0.6" @@ -1358,20 +1272,20 @@ "sftp", "storage" ], - "time": "2016-06-09 08:23:13" + "time": "2017-03-22 15:43:14" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.4", + "version": "1.0.13", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "e8e27d07bba47d29ca064b5f9dd06273fbaf7f62" + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/e8e27d07bba47d29ca064b5f9dd06273fbaf7f62", - "reference": "e8e27d07bba47d29ca064b5f9dd06273fbaf7f62", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c", + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c", "shasum": "" }, "require": { @@ -1405,26 +1319,26 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2015-07-07 20:11:47" + "time": "2016-06-21 21:34:35" }, { "name": "league/flysystem-rackspace", - "version": "1.0.1", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-rackspace.git", - "reference": "c44e4072cf93c9e1b6ee9a125ad84c827e13adca" + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-rackspace/zipball/c44e4072cf93c9e1b6ee9a125ad84c827e13adca", - "reference": "c44e4072cf93c9e1b6ee9a125ad84c827e13adca", + "url": "https://api.github.com/repos/thephpleague/flysystem-rackspace/zipball/ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", + "reference": "ba877e837f5dce60e78a0555de37eb9bfc7dd6b9", "shasum": "" }, "require": { "league/flysystem": "~1.0", "php": ">=5.4.0", - "rackspace/php-opencloud": "~1.12" + "rackspace/php-opencloud": "~1.16" }, "require-dev": { "mockery/mockery": "0.9.*", @@ -1452,7 +1366,7 @@ } ], "description": "Flysystem adapter for Rackspace", - "time": "2015-04-02 07:47:54" + "time": "2016-03-11 12:13:42" }, { "name": "league/oauth2-server", @@ -1518,16 +1432,16 @@ }, { "name": "league/url", - "version": "3.x-dev", + "version": "3.3.5", "source": { "type": "git", "url": "https://github.com/thephpleague/url.git", - "reference": "45f5529ea879ffc166cc4e4ffa478a212c183628" + "reference": "1ae2c3ce29a7c5438339ff6388225844e6479da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/url/zipball/45f5529ea879ffc166cc4e4ffa478a212c183628", - "reference": "45f5529ea879ffc166cc4e4ffa478a212c183628", + "url": "https://api.github.com/repos/thephpleague/url/zipball/1ae2c3ce29a7c5438339ff6388225844e6479da8", + "reference": "1ae2c3ce29a7c5438339ff6388225844e6479da8", "shasum": "" }, "require": { @@ -1569,7 +1483,7 @@ "url" ], "abandoned": "league/uri", - "time": "2015-09-24 10:19:47" + "time": "2015-07-15 08:24:12" }, { "name": "mikemccabe/json-patch-php", @@ -1598,96 +1512,18 @@ "description": "Produce and apply json-patch objects", "time": "2015-01-05 21:19:54" }, - { - "name": "monolog/monolog", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/monolog.git", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037", - "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" - }, - "provide": { - "psr/log-implementation": "1.0.0" - }, - "require-dev": { - "aws/aws-sdk-php": "^2.4.9", - "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "jakub-onderka/php-parallel-lint": "0.9", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpunit/phpunit": "~4.5", - "phpunit/phpunit-mock-objects": "2.3.0", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "~5.3" - }, - "suggest": { - "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "doctrine/couchdb": "Allow sending log messages to a CouchDB server", - "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", - "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", - "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", - "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Monolog\\": "src/Monolog" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", - "keywords": [ - "log", - "logging", - "psr-3" - ], - "time": "2016-07-02 14:02:10" - }, { "name": "mtdowling/jmespath.php", - "version": "2.3.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "192f93e43c2c97acde7694993ab171b3de284093" + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/192f93e43c2c97acde7694993ab171b3de284093", - "reference": "192f93e43c2c97acde7694993ab171b3de284093", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/adcc9531682cf87dfda21e1fd5d0e7a41d292fac", + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac", "shasum": "" }, "require": { @@ -1729,25 +1565,25 @@ "json", "jsonpath" ], - "time": "2016-01-05 18:25:05" + "time": "2016-12-03 22:08:25" }, { "name": "ohanzee/database", - "version": "0.1.2", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/kohana/ohanzee-db.git", - "reference": "26dc07ed3041551258a6d5d70a01bf454d28ab32" + "url": "https://github.com/ushahidi/ohanzee-db.git", + "reference": "279a566fee8724214b37ba66a5270cfa4dc2751b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kohana/ohanzee-db/zipball/26dc07ed3041551258a6d5d70a01bf454d28ab32", - "reference": "26dc07ed3041551258a6d5d70a01bf454d28ab32", + "url": "https://api.github.com/repos/ushahidi/ohanzee-db/zipball/279a566fee8724214b37ba66a5270cfa4dc2751b", + "reference": "279a566fee8724214b37ba66a5270cfa4dc2751b", "shasum": "" }, "require": { "kohana/core": ">=3.3", - "php": ">=5.3.6" + "php": ">=5.4" }, "replace": { "kohana/database": ">=3.3" @@ -1762,7 +1598,6 @@ "": "src/" } }, - "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -1779,7 +1614,7 @@ "role": "developer" } ], - "description": "Official Ohanzee component for database SQL queries", + "description": "Ohanzee component for database SQL queries and query building", "homepage": "http://ohanzee.org/", "keywords": [ "component", @@ -1790,20 +1625,26 @@ "query builder", "sql" ], - "time": "2014-08-21 16:41:35" + "support": { + "source": "http://github.com/kohana/ohanzee-db", + "issues": "http://github.com/kohana/ohanzee-db/issues", + "forum": "http://discourse.kohanaframework.org/category/ohanzee-components", + "irc": "irc://irc.freenode.net/kohana" + }, + "time": "2017-04-28 00:10:09" }, { "name": "paragonie/random_compat", - "version": "v2.0.2", + "version": "v2.0.10", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", "shasum": "" }, "require": { @@ -1838,27 +1679,24 @@ "pseudorandom", "random" ], - "time": "2016-04-03 06:00:07" + "time": "2017-03-13 16:27:32" }, { - "name": "phpdocumentor/reflection-common", - "version": "dev-master", + "name": "psr/http-message", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" + "php": ">=5.3.0" }, "type": "library", "extra": { @@ -1868,9 +1706,7 @@ }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1879,51 +1715,48 @@ ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], - "time": "2015-12-27 11:43:31" + "time": "2016-08-06 14:39:51" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "3.1.0", + "name": "psr/log", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1932,146 +1765,188 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-06-10 09:48:41" + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10 12:19:37" }, { - "name": "phpdocumentor/type-resolver", - "version": "0.2", + "name": "rackspace/php-opencloud", + "version": "v1.16.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + "url": "https://github.com/rackspace/php-opencloud.git", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", + "reference": "d6b71feed7f9e7a4b52e0240a79f06473ba69c8c", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0" + "guzzle/guzzle": "~3.8", + "mikemccabe/json-patch-php": "~0.1", + "php": ">=5.4", + "psr/log": "~1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "apigen/apigen": "~4.0", + "fabpot/php-cs-fixer": "1.0.*@dev", + "jakub-onderka/php-parallel-lint": "0.*", + "phpspec/prophecy": "~1.4", + "phpunit/phpunit": "4.3.*", + "satooshi/php-coveralls": "0.6.*@dev" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" + "psr-0": { + "OpenCloud": [ + "lib/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Jamie Hannaford", + "email": "jamie.hannaford@rackspace.com", + "homepage": "https://github.com/jamiehannaford" } ], - "time": "2016-06-10 07:14:17" + "description": "PHP SDK for Rackspace/OpenStack APIs", + "keywords": [ + "Openstack", + "nova", + "opencloud", + "rackspace", + "swift" + ], + "time": "2016-01-29 10:34:57" }, { - "name": "phpspec/php-diff", - "version": "dev-master", + "name": "ramsey/uuid", + "version": "3.6.1", "source": { "type": "git", - "url": "https://github.com/phpspec/php-diff.git", - "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" + "url": "https://github.com/ramsey/uuid.git", + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", - "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", "shasum": "" }, + "require": { + "paragonie/random_compat": "^1.0|^2.0", + "php": "^5.4 || ^7.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "apigen/apigen": "^4.1", + "codeception/aspect-mock": "^1.0 | ^2.0", + "doctrine/annotations": "~1.2.0", + "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1", + "ircmaxell/random-lib": "^1.1", + "jakub-onderka/php-parallel-lint": "^0.9.0", + "mockery/mockery": "^0.9.4", + "moontoast/math": "^1.1", + "php-mock/php-mock-phpunit": "^0.3|^1.1", + "phpunit/phpunit": "^4.7|>=5.0 <5.4", + "satooshi/php-coveralls": "^0.6.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { - "psr-0": { - "Diff": "lib/" + "psr-4": { + "Ramsey\\Uuid\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Chris Boulton", - "homepage": "http://github.com/chrisboulton" + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" } ], - "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", - "time": "2016-04-07 12:29:16" + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2017-03-26 20:37:53" }, { - "name": "phpspec/phpspec", - "version": "2.5.x-dev", + "name": "robmorgan/phinx", + "version": "v0.8.0", "source": { "type": "git", - "url": "https://github.com/phpspec/phpspec.git", - "reference": "65ba3eaa0e96c36a4a6c47950b10859ddc179ab5" + "url": "https://github.com/robmorgan/phinx.git", + "reference": "15e43d10dd99ac818c8d65735c50191bcbeafdbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/phpspec/zipball/65ba3eaa0e96c36a4a6c47950b10859ddc179ab5", - "reference": "65ba3eaa0e96c36a4a6c47950b10859ddc179ab5", + "url": "https://api.github.com/repos/robmorgan/phinx/zipball/15e43d10dd99ac818c8d65735c50191bcbeafdbc", + "reference": "15e43d10dd99ac818c8d65735c50191bcbeafdbc", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.1", - "ext-tokenizer": "*", - "php": ">=5.3.3", - "phpspec/php-diff": "~1.0.0", - "phpspec/prophecy": "~1.4", - "sebastian/exporter": "~1.0", - "symfony/console": "~2.3|~3.0", - "symfony/event-dispatcher": "~2.1|~3.0", - "symfony/finder": "~2.1|~3.0", - "symfony/process": "^2.6|~3.0", - "symfony/yaml": "~2.1|~3.0" + "php": ">=5.4", + "symfony/config": "~2.8|~3.0", + "symfony/console": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" }, "require-dev": { - "behat/behat": "^3.0.11", - "ciaranmcnulty/versionbasedtestskipper": "^0.2.1", - "phpunit/phpunit": "~4.4", - "symfony/filesystem": "~2.1|~3.0" - }, - "suggest": { - "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" + "phpunit/phpunit": "^4.8.26|^5.0" }, "bin": [ - "bin/phpspec" + "bin/phinx" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5.x-dev" - } - }, "autoload": { - "psr-0": { - "PhpSpec": "src/" + "psr-4": { + "Phinx\\": "src/Phinx" } }, "notification-url": "https://packagist.org/downloads/", @@ -2080,52 +1955,66 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "http://shadowhand.me", + "role": "Developer" }, { - "name": "Marcello Duarte", - "homepage": "http://marcelloduarte.net/" + "name": "Rob Morgan", + "email": "robbym@gmail.com", + "homepage": "https://robmorgan.id.au", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Developer" } ], - "description": "Specification-oriented BDD framework for PHP 5.3+", - "homepage": "http://phpspec.net/", + "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", + "homepage": "https://phinx.org", "keywords": [ - "BDD", - "SpecBDD", - "TDD", - "spec", - "specification", - "testing", - "tests" + "database", + "database migrations", + "db", + "migrations", + "phinx" ], - "time": "2016-06-07 20:44:43" + "time": "2017-02-28 18:34:31" }, { - "name": "phpspec/prophecy", - "version": "dev-master", + "name": "sentry/sentry", + "version": "1.6.2", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "url": "https://github.com/getsentry/sentry-php.git", + "reference": "5bee26136ab3fc166334cd972892bf71bd361558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/5bee26136ab3fc166334cd972892bf71bd361558", + "reference": "5bee26136ab3fc166334cd972892bf71bd361558", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "ext-curl": "*", + "php": ">=5.2.4" + }, + "conflict": { + "raven/raven": "*" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "friendsofphp/php-cs-fixer": "^1.8.0", + "monolog/monolog": "*", + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "suggest": { + "monolog/monolog": "Automatically capture Monolog events as breadcrumbs" }, + "bin": [ + "bin/sentry" + ], "type": "library", "extra": { "branch-alias": { @@ -2134,262 +2023,295 @@ }, "autoload": { "psr-0": { - "Prophecy\\": "src/" + "Raven_": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "David Cramer", + "email": "dcramer@gmail.com" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "description": "A PHP client for Sentry (http://getsentry.com)", + "homepage": "http://getsentry.com", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "log", + "logging" ], - "time": "2016-06-07 08:13:47" + "time": "2017-02-03 07:32:53" }, { - "name": "phpunit/php-code-coverage", - "version": "2.2.x-dev", + "name": "swiftmailer/swiftmailer", + "version": "v4.3.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2", + "reference": "ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" + "php": ">=5.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "4.3-dev" } }, "autoload": { - "classmap": [ - "src/" + "files": [ + "lib/swift_required.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Chris Corbyn" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "http://swiftmailer.org", "keywords": [ - "coverage", - "testing", - "xunit" + "mail", + "mailer" ], - "time": "2015-10-06 15:47:00" + "time": "2013-04-11 10:22:09" }, { - "name": "phpunit/php-file-iterator", - "version": "dev-master", + "name": "symfony/config", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "url": "https://github.com/symfony/config.git", + "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/symfony/config/zipball/741d6d4cd1414d67d48eb71aba6072b46ba740c2", + "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" + }, + "require-dev": { + "symfony/yaml": "~3.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2015-06-21 13:08:43" + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2017-03-01 18:18:25" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "symfony/console", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/symfony/console.git", + "reference": "28fb243a2b5727774ca309ec2d92da240f1af0dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/symfony/console/zipball/28fb243a2b5727774ca309ec2d92da240f1af0dd", + "reference": "28fb243a2b5727774ca309ec2d92da240f1af0dd", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/filesystem": "", + "symfony/process": "" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21 13:50:34" + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2017-03-06 19:30:27" }, { - "name": "phpunit/php-token-stream", - "version": "dev-master", + "name": "symfony/debug", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644" + "url": "https://github.com/symfony/debug.git", + "reference": "b90c9f91ad8ac37d9f114e369042d3226b34dc1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/cab6c6fefee93d7b7c3a01292a0fe0884ea66644", - "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644", + "url": "https://api.github.com/repos/symfony/debug/zipball/b90c9f91ad8ac37d9f114e369042d3226b34dc1a", + "reference": "b90c9f91ad8ac37d9f114e369042d3226b34dc1a", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2015-09-23 14:46:55" + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2017-02-18 17:28:00" }, { - "name": "psr/http-message", - "version": "dev-master", + "name": "symfony/event-dispatcher", + "version": "v2.8.18", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bb4ec47e8e109c1c1172145732d0aa468d967cd0", + "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2397,48 +2319,48 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Common interface for HTTP messages", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2015-05-04 20:22:00" + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2017-02-21 08:33:48" }, { - "name": "psr/log", - "version": "dev-master", + "name": "symfony/filesystem", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e" + "url": "https://github.com/symfony/filesystem.git", + "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d8e60a5619fff77f9669da8997697443ef1a1d7e", - "reference": "d8e60a5619fff77f9669da8997697443ef1a1d7e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/bc0f17bed914df2cceb989972c3b996043c4da4a", + "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2446,132 +2368,107 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-01-06 21:40:42" + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2017-03-06 19:30:27" }, { - "name": "rackspace/php-opencloud", - "version": "dev-working", + "name": "symfony/polyfill-mbstring", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/rackspace/php-opencloud.git", - "reference": "3ffee7b90884a3c556578db8ff9ab2b20b65f18c" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/3ffee7b90884a3c556578db8ff9ab2b20b65f18c", - "reference": "3ffee7b90884a3c556578db8ff9ab2b20b65f18c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", "shasum": "" }, "require": { - "guzzle/guzzle": "~3.8", - "mikemccabe/json-patch-php": "~0.1", - "php": ">=5.4", - "psr/log": "~1.0" + "php": ">=5.3.3" }, - "require-dev": { - "apigen/apigen": "~4.0", - "fabpot/php-cs-fixer": "1.0.*@dev", - "jakub-onderka/php-parallel-lint": "0.*", - "phpspec/prophecy": "~1.4", - "phpunit/phpunit": "4.3.*", - "satooshi/php-coveralls": "0.6.*@dev" + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-working": "1.16-dev" + "dev-master": "1.3-dev" } }, "autoload": { - "psr-0": { - "OpenCloud": [ - "lib/" - ] - } + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" ], "authors": [ { - "name": "Jamie Hannaford", - "email": "jamie.hannaford@rackspace.com", - "homepage": "https://github.com/jamiehannaford" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "PHP SDK for Rackspace/OpenStack APIs", + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", "keywords": [ - "Openstack", - "nova", - "opencloud", - "rackspace", - "swift" + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" ], - "time": "2016-06-13 07:37:06" + "time": "2016-11-14 01:06:16" }, { - "name": "ramsey/uuid", - "version": "dev-master", + "name": "symfony/property-access", + "version": "v2.8.18", "source": { "type": "git", - "url": "https://github.com/ramsey/uuid.git", - "reference": "be0a40fec15740eba2e6ade85786cd7348def382" + "url": "https://github.com/symfony/property-access.git", + "reference": "820b71d9384a66f92ef968f82af871dc76debedb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/be0a40fec15740eba2e6ade85786cd7348def382", - "reference": "be0a40fec15740eba2e6ade85786cd7348def382", + "url": "https://api.github.com/repos/symfony/property-access/zipball/820b71d9384a66f92ef968f82af871dc76debedb", + "reference": "820b71d9384a66f92ef968f82af871dc76debedb", "shasum": "" }, "require": { - "paragonie/random_compat": "^1.0|^2.0", - "php": ">=5.4" - }, - "replace": { - "rhumsaa/uuid": "self.version" - }, - "require-dev": { - "apigen/apigen": "^4.1", - "codeception/aspect-mock": "1.0.0", - "goaop/framework": "1.0.0-alpha.2", - "ircmaxell/random-lib": "^1.1", - "jakub-onderka/php-parallel-lint": "^0.9.0", - "mockery/mockery": "^0.9.4", - "moontoast/math": "^1.1", - "phpunit/phpunit": "^4.7|>=5.0 <5.4", - "satooshi/php-coveralls": "^0.6.1", - "squizlabs/php_codesniffer": "^2.3" - }, - "suggest": { - "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", - "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", - "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", - "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", - "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + "php": ">=5.3.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { - "Ramsey\\Uuid\\": "src/" - } + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2579,59 +2476,432 @@ ], "authors": [ { - "name": "Marijn Huizendveld", - "email": "marijn.huizendveld@gmail.com" - }, + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2017-02-18 17:06:33" + }, + { + "name": "symfony/yaml", + "version": "v3.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2017-03-07 16:47:02" + }, + { + "name": "symm/gisconverter", + "version": "v1.0.5", + "source": { + "type": "git", + "url": "https://github.com/symm/gisconverter.git", + "reference": "21ab697b7692b891dac37c64d10c9d83d4433f80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symm/gisconverter/zipball/21ab697b7692b891dac37c64d10c9d83d4433f80", + "reference": "21ab697b7692b891dac37c64d10c9d83d4433f80", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Symm\\Gisconverter": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "A php library to convert vector geometries between different formats", + "time": "2014-08-07 13:50:52" + }, + { + "name": "true/punycode", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/true/php-punycode.git", + "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e", + "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.7", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "TrueBV\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Renan Gonçalves", + "email": "renan.saddam@gmail.com" + } + ], + "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)", + "homepage": "https://github.com/true/php-punycode", "keywords": [ - "guid", - "identifier", - "uuid" + "idna", + "punycode" ], - "time": "2016-06-24 22:24:42" + "time": "2016-11-16 10:37:54" }, { - "name": "robmorgan/phinx", - "version": "v0.4.3", + "name": "twilio/sdk", + "version": "3.12.8", "source": { "type": "git", - "url": "https://github.com/robmorgan/phinx.git", - "reference": "0d1f9cb9939f65f506a8a3f5fee356764c310fd4" + "url": "https://github.com/twilio/twilio-php.git", + "reference": "9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robmorgan/phinx/zipball/0d1f9cb9939f65f506a8a3f5fee356764c310fd4", - "reference": "0d1f9cb9939f65f506a8a3f5fee356764c310fd4", + "url": "https://api.github.com/repos/twilio/twilio-php/zipball/9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73", + "reference": "9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73", "shasum": "" }, "require": { - "php": ">=5.3.2", - "symfony/config": "~2.6.0", - "symfony/console": "~2.6.0", - "symfony/yaml": "~2.6.0" + "php": ">=5.2.1" }, "require-dev": { - "phpunit/phpunit": "3.7.*", - "squizlabs/php_codesniffer": "dev-phpcs-fixer" + "mockery/mockery": ">=0.7.2", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Services_Twilio": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Burke", + "email": "kevin@twilio.com" + }, + { + "name": "Kyle Conroy", + "email": "kyle+pear@twilio.com" + } + ], + "description": "A PHP wrapper for Twilio's API", + "homepage": "http://github.com/twilio/twilio-php", + "keywords": [ + "api", + "sms", + "twilio" + ], + "time": "2014-12-04 19:17:59" + }, + { + "name": "ushahidi/shadowhand-email", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/ushahidi/shadowhand-email.git", + "reference": "51274cdd899d0c619368c9580146bd05b461a03f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ushahidi/shadowhand-email/zipball/51274cdd899d0c619368c9580146bd05b461a03f", + "reference": "51274cdd899d0c619368c9580146bd05b461a03f", + "shasum": "" + }, + "require": { + "kohana/core": "3.3.*", + "php": ">=5.3.0", + "swiftmailer/swiftmailer": "~4.3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Shadowhand\\": "src/" + }, + "files": [ + "init.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kohana Team", + "email": "team@kohanaframework.org", + "role": "creator" + }, + { + "name": "Robbie Mackay", + "email": "robbie@ushahidi.com", + "role": "maintainer" + } + ], + "description": "Email helper class, uses Swiftmailer", + "homepage": "http://github.com/ushahidi/shadowhand-email", + "keywords": [ + "email", + "helper", + "kohana", + "library", + "module", + "ohanzee", + "swiftmailer" + ], + "time": "2017-03-22 00:35:17" + }, + { + "name": "vlucas/phpdotenv", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause-Attribution" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2016-09-01 10:05:43" + }, + { + "name": "zeelot/kohana-media", + "version": "dev-1.3/develop", + "source": { + "type": "git", + "url": "https://github.com/Zeelot/kohana-media.git", + "reference": "2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Zeelot/kohana-media/zipball/2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e", + "reference": "2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e", + "shasum": "" + }, + "require": { + "kohana/core": ">=3.3", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.3/develop": "1.3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Lorenzo Pisani", + "email": "zeelot3k@gmail.com", + "homepage": "http://zeelot3k.com", + "role": "developer" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Zeelot/kohana-media/graphs/contributors", + "role": "contributor" + } + ], + "description": "Using the Kohana cascading file system to serve media assets", + "homepage": "https://github.com/Zeelot/kohana-media", + "keywords": [ + "assets", + "caching", + "cfs", + "files", + "framework", + "kohana", + "media" + ], + "time": "2014-04-26 16:15:53" + } + ], + "packages-dev": [ + { + "name": "behat/behat", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Behat.git", + "reference": "15a3a1857457eaa29cdf41564a5e421effb09526" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Behat/zipball/15a3a1857457eaa29cdf41564a5e421effb09526", + "reference": "15a3a1857457eaa29cdf41564a5e421effb09526", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.4.4", + "behat/transliterator": "~1.0", + "container-interop/container-interop": "^1.1", + "ext-mbstring": "*", + "php": ">=5.3.3", + "symfony/class-loader": "~2.1||~3.0", + "symfony/config": "~2.3||~3.0", + "symfony/console": "~2.5||~3.0", + "symfony/dependency-injection": "~2.1||~3.0", + "symfony/event-dispatcher": "~2.1||~3.0", + "symfony/translation": "~2.3||~3.0", + "symfony/yaml": "~2.1||~3.0" + }, + "require-dev": { + "herrera-io/box": "~1.6.1", + "phpunit/phpunit": "~4.5", + "symfony/process": "~2.5|~3.0" + }, + "suggest": { + "behat/mink-extension": "for integration with Mink testing framework", + "behat/symfony2-extension": "for integration with Symfony2 web framework", + "behat/yii-extension": "for integration with Yii web framework" }, "bin": [ - "bin/phinx" + "bin/behat" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, "autoload": { - "psr-4": { - "Phinx\\": "src/Phinx" + "psr-0": { + "Behat\\Behat": "src/", + "Behat\\Testwork": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2640,69 +2910,63 @@ ], "authors": [ { - "name": "Rob Morgan", - "email": "robbym@gmail.com", - "homepage": "http://robmorgan.id.au", - "role": "Lead Developer" - }, - { - "name": "Woody Gilk", - "email": "woody.gilk@gmail.com", - "homepage": "http://shadowhand.me", - "role": "Developer" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", - "homepage": "https://phinx.org", + "description": "Scenario-oriented BDD framework for PHP 5.3", + "homepage": "http://behat.org/", "keywords": [ - "database", - "database migrations", - "db", - "migrations", - "phinx" + "Agile", + "BDD", + "ScenarioBDD", + "Scrum", + "StoryBDD", + "User story", + "business", + "development", + "documentation", + "examples", + "symfony", + "testing" ], - "time": "2015-02-23 16:38:12" + "time": "2016-12-25 13:43:52" }, { - "name": "satooshi/php-coveralls", - "version": "dev-master", + "name": "behat/gherkin", + "version": "v4.4.5", "source": { "type": "git", - "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3" + "url": "https://github.com/Behat/Gherkin.git", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/50c60bb64054974f8ed7540ae6e75fd7981a5fd3", - "reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/5c14cff4f955b17d20d088dec1bde61c0539ec74", + "reference": "5c14cff4f955b17d20d088dec1bde61c0539ec74", "shasum": "" }, "require": { - "ext-json": "*", - "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.0", - "php": ">=5.5", - "psr/log": "^1.0", - "symfony/config": "^2.1|^3.0", - "symfony/console": "^2.1|^3.0", - "symfony/stopwatch": "^2.0|^3.0", - "symfony/yaml": "^2.0|^3.0" + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3", + "symfony/yaml": "~2.3|~3" }, "suggest": { - "symfony/http-kernel": "Allows Symfony integration" + "symfony/yaml": "If you want to parse features, represented in YAML files" }, - "bin": [ - "bin/coveralls" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.4-dev" } }, "autoload": { - "psr-4": { - "Satooshi\\": "src/Satooshi/" + "psr-0": { + "Behat\\Gherkin": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2711,482 +2975,454 @@ ], "authors": [ { - "name": "Kitamura Satoshi", - "email": "with.no.parachute@gmail.com", - "homepage": "https://www.facebook.com/satooshi.jp" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "PHP client library for Coveralls API", - "homepage": "https://github.com/satooshi/php-coveralls", + "description": "Gherkin DSL parser for PHP 5.3", + "homepage": "http://behat.org/", "keywords": [ - "ci", - "coverage", - "github", - "test" + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" ], - "time": "2016-01-20 17:44:41" + "time": "2016-10-30 11:50:56" }, { - "name": "sebastian/comparator", - "version": "dev-master", + "name": "behat/mink", + "version": "v1.7.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "url": "https://github.com/minkphp/Mink.git", + "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9", + "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "php": ">=5.3.1", + "symfony/css-selector": "~2.1|~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "suggest": { + "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", + "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Behat\\Mink\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "description": "Browser controller/emulator abstraction for PHP", + "homepage": "http://mink.behat.org/", "keywords": [ - "comparator", - "compare", - "equality" + "browser", + "testing", + "web" ], - "time": "2015-07-26 15:48:44" + "time": "2016-03-05 08:26:18" }, { - "name": "sebastian/diff", - "version": "dev-master", + "name": "behat/mink-browserkit-driver", + "version": "v1.3.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", + "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", + "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", "shasum": "" }, "require": { - "php": ">=5.3.3" + "behat/mink": "^1.7.1@dev", + "php": ">=5.3.6", + "symfony/browser-kit": "~2.3|~3.0", + "symfony/dom-crawler": "~2.3|~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "silex/silex": "~1.2", + "symfony/phpunit-bridge": "~2.7|~3.0" }, - "type": "library", + "type": "mink-driver", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", + "description": "Symfony2 BrowserKit driver for Mink framework", + "homepage": "http://mink.behat.org/", "keywords": [ - "diff" + "Mink", + "Symfony2", + "browser", + "testing" ], - "time": "2015-12-08 07:14:41" + "time": "2016-03-05 08:59:47" }, { - "name": "sebastian/environment", - "version": "dev-master", + "name": "behat/mink-extension", + "version": "v2.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e7133793a8e5a5714a551a8324337374be209df" + "url": "https://github.com/Behat/MinkExtension.git", + "reference": "5b4bda64ff456104564317e212c823e45cad9d59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", - "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/5b4bda64ff456104564317e212c823e45cad9d59", + "reference": "5b4bda64ff456104564317e212c823e45cad9d59", "shasum": "" }, "require": { - "php": ">=5.3.3" + "behat/behat": "~3.0,>=3.0.5", + "behat/mink": "~1.5", + "php": ">=5.3.2", + "symfony/config": "~2.2|~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "behat/mink-goutte-driver": "~1.1", + "phpspec/phpspec": "~2.0" }, - "type": "library", + "type": "behat-extension", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "Behat\\MinkExtension": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Christophe Coevoet", + "email": "stof@notk.org" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "Mink extension for Behat", + "homepage": "http://extensions.behat.org/mink", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "browser", + "gui", + "test", + "web" ], - "time": "2015-12-02 08:37:27" + "time": "2016-02-15 07:55:18" }, { - "name": "sebastian/exporter", - "version": "dev-master", + "name": "behat/mink-goutte-driver", + "version": "v1.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "url": "https://github.com/minkphp/MinkGoutteDriver.git", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "behat/mink": "~1.6@dev", + "behat/mink-browserkit-driver": "~1.2@dev", + "fabpot/goutte": "~1.0.4|~2.0|~3.1", + "php": ">=5.3.1" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "symfony/phpunit-bridge": "~2.7|~3.0" }, - "type": "library", + "type": "mink-driver", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "description": "Goutte driver for Mink framework", + "homepage": "http://mink.behat.org/", "keywords": [ - "export", - "exporter" + "browser", + "goutte", + "headless", + "testing" ], - "time": "2016-06-17 09:04:28" + "time": "2016-03-05 09:04:22" }, { - "name": "sebastian/recursion-context", - "version": "dev-master", + "name": "behat/transliterator", + "version": "v1.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7" + "url": "https://github.com/Behat/Transliterator.git", + "reference": "868e05be3a9f25ba6424c2dd4849567f50715003" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", - "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/868e05be3a9f25ba6424c2dd4849567f50715003", + "reference": "868e05be3a9f25ba6424c2dd4849567f50715003", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "Behat\\Transliterator": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "Artistic-1.0" ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } + "description": "String transliterator", + "keywords": [ + "i18n", + "slug", + "transliterator" ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-01-28 05:39:29" + "time": "2015-09-28 16:26:35" }, { - "name": "sebastian/version", - "version": "1.0.6", + "name": "container-interop/container-interop", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "url": "https://github.com/container-interop/container-interop.git", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", "shasum": "" }, + "require": { + "psr/container": "^1.0" + }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } + "MIT" ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14 19:40:03" }, { - "name": "sentry/sentry", - "version": "dev-master", + "name": "doctrine/instantiator", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/getsentry/sentry-php.git", - "reference": "2a92076ffc6c3f193f2736c9ce75d26705bb48b7" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2a92076ffc6c3f193f2736c9ce75d26705bb48b7", - "reference": "2a92076ffc6c3f193f2736c9ce75d26705bb48b7", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "ext-curl": "*", - "monolog/monolog": "*", - "php": ">=5.2.4" - }, - "conflict": { - "raven/raven": "*" + "php": ">=5.3,<8.0-DEV" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.8.0", - "phpunit/phpunit": "^4.8 || ^5.0" + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, - "bin": [ - "bin/sentry" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Raven_": "lib/" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "David Cramer", - "email": "dcramer@gmail.com" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "A PHP client for Sentry (http://getsentry.com)", - "homepage": "http://getsentry.com", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ - "log", - "logging" + "constructor", + "instantiate" ], - "time": "2016-11-01 18:46:47" + "time": "2015-06-14 21:17:01" }, { - "name": "swiftmailer/swiftmailer", - "version": "v4.3.1", + "name": "fabpot/goutte", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2" + "url": "https://github.com/FriendsOfPHP/Goutte.git", + "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2", - "reference": "ae540bed1079c07aa12e9e62d9d8d4fc49bbdff2", + "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/db5c28f4a010b4161d507d5304e28a7ebf211638", + "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638", "shasum": "" }, "require": { - "php": ">=5.2.4" + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "symfony/browser-kit": "~2.1|~3.0", + "symfony/css-selector": "~2.1|~3.0", + "symfony/dom-crawler": "~2.1|~3.0" }, - "type": "library", + "type": "application", "extra": { "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "files": [ - "lib/swift_required.php" - ] + "psr-4": { + "Goutte\\": "Goutte" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL" + "MIT" ], "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Chris Corbyn" + "email": "fabien@symfony.com" } ], - "description": "Swiftmailer, free feature-rich PHP mailer", - "homepage": "http://swiftmailer.org", + "description": "A simple PHP Web Scraper", + "homepage": "https://github.com/FriendsOfPHP/Goutte", "keywords": [ - "mail", - "mailer" + "scraper" ], - "time": "2013-04-11 10:22:09" + "time": "2017-01-03 13:21:43" }, { - "name": "symfony/config", - "version": "2.6.x-dev", - "target-dir": "Symfony/Component/Config", + "name": "fzaninotto/faker", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b" + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0ca496cbe208fc37c4cf3415ebb3056e0963115b", - "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/filesystem": "~2.3" + "php": "^5.3.3|^7.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "ext-intl": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } + "branch-alias": [] }, "autoload": { - "psr-0": { - "Symfony\\Component\\Config\\": "" + "psr-4": { + "Faker\\": "src/Faker/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3195,56 +3431,96 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2016-04-29 12:21:54" + }, + { + "name": "heroku/heroku-buildpack-php", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/heroku/heroku-buildpack-php.git", + "reference": "727aa850a02a7af94c9225237464be8e8c8ff6db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/727aa850a02a7af94c9225237464be8e8c8ff6db", + "reference": "727aa850a02a7af94c9225237464be8e8c8ff6db", + "shasum": "" + }, + "bin": [ + "bin/heroku-hhvm-apache2", + "bin/heroku-hhvm-nginx", + "bin/heroku-php-apache2", + "bin/heroku-php-nginx" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "David Zuelke", + "email": "dz@heroku.com" } ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2015-07-08 05:59:48" + "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", + "homepage": "https://github.com/heroku/heroku-buildpack-php", + "keywords": [ + "apache", + "apache2", + "foreman", + "heroku", + "hhvm", + "nginx", + "php" + ], + "time": "2017-03-27 23:33:27" }, { - "name": "symfony/console", - "version": "2.6.x-dev", - "target-dir": "Symfony/Component/Console", + "name": "laravel/homestead", + "version": "v5.2.4", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359" + "url": "https://github.com/laravel/homestead.git", + "reference": "77f1f01f6ec504c7f3adcb220d73c831a8dcc2bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359", - "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359", + "url": "https://api.github.com/repos/laravel/homestead/zipball/77f1f01f6ec504c7f3adcb220d73c831a8dcc2bb", + "reference": "77f1f01f6ec504c7f3adcb220d73c831a8dcc2bb", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.6 || ^7.0", + "symfony/console": "~2.3|~3.0", + "symfony/process": "~2.3|~3.0", + "symfony/yaml": "~2.3|~3.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" + "phpunit/phpunit": "^5.7 || ^6.0" }, + "bin": [ + "bin/homestead" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Console\\": "" + "psr-4": { + "Laravel\\Homestead\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3253,59 +3529,43 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Taylor Otwell", + "email": "taylorotwell@gmail.com" } ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2015-07-26 09:08:40" + "description": "A virtual machine for web artisans.", + "time": "2017-04-26 15:43:12" }, { - "name": "symfony/event-dispatcher", - "version": "2.8.x-dev", + "name": "leanphp/phpspec-code-coverage", + "version": "v3.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "2a6b8713f8bdb582058cfda463527f195b066110" + "url": "https://github.com/leanphp/phpspec-code-coverage.git", + "reference": "2f66eb6fbca15761e6029ded9dbe3e277c7093d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110", - "reference": "2a6b8713f8bdb582058cfda463527f195b066110", + "url": "https://api.github.com/repos/leanphp/phpspec-code-coverage/zipball/2f66eb6fbca15761e6029ded9dbe3e277c7093d6", + "reference": "2f66eb6fbca15761e6029ded9dbe3e277c7093d6", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": "~5.6||~7.0", + "phpspec/phpspec": "~3.0", + "phpunit/php-code-coverage": "~4.0||~5.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", - "symfony/dependency-injection": "~2.6|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/stopwatch": "~2.3|~3.0.0" + "bossa/phpspec2-expect": "~2.0" }, "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "ext-xdebug": "Install Xdebug to generate phpspec code coverage if you are not using phpdbg" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "LeanPHP\\PhpSpec\\CodeCoverage\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3313,97 +3573,107 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "ek9", + "email": "dev@ek9.co", + "homepage": "https://ek9.co" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Henrik Bjornskov" } ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "description": "Generate Code Coverage reports for PhpSpec tests", + "homepage": "https://github.com/leanphp/phpspec-code-coverage", + "keywords": [ + "build", + "clover", + "code", + "code-coverage", + "coverage", + "generate", + "generation", + "phpspec", + "report", + "reports", + "spec", + "test", + "tests" + ], + "time": "2017-02-21 02:54:14" }, { - "name": "symfony/filesystem", - "version": "2.8.x-dev", + "name": "myclabs/deep-copy", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "dee379131dceed90a429e951546b33edfe7dccbb" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/dee379131dceed90a429e951546b33edfe7dccbb", - "reference": "dee379131dceed90a429e951546b33edfe7dccbb", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.4.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2016-04-12 18:01:21" + "time": "2017-01-26 22:05:40" }, { - "name": "symfony/finder", - "version": "2.8.x-dev", + "name": "phpdocumentor/reflection-common", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "cad8e7020cb8d1756cced64b1b48d7b176c9f366" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/cad8e7020cb8d1756cced64b1b48d7b176c9f366", - "reference": "cad8e7020cb8d1756cced64b1b48d7b176c9f366", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "phpDocumentor\\Reflection\\": [ + "src" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3411,48 +3681,52 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2016-06-21 05:36:02" + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" }, { - "name": "symfony/process", - "version": "2.8.x-dev", + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "b3f638531fa1890f8db3010a2b98a33f1a6528b9" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b3f638531fa1890f8db3010a2b98a33f1a6528b9", - "reference": "b3f638531fa1890f8db3010a2b98a33f1a6528b9", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3460,48 +3734,47 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2016-06-21 05:36:02" + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" }, { - "name": "symfony/property-access", - "version": "2.8.x-dev", + "name": "phpdocumentor/type-resolver", + "version": "0.2.1", "source": { "type": "git", - "url": "https://github.com/symfony/property-access.git", - "reference": "c1a556ab664b5f96a7d604d1d6337068f16d6a25" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/c1a556ab664b5f96a7d604d1d6337068f16d6a25", - "reference": "c1a556ab664b5f96a7d604d1d6337068f16d6a25", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\PropertyAccess\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3509,108 +3782,98 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Symfony PropertyAccess Component", - "homepage": "https://symfony.com", - "keywords": [ - "access", - "array", - "extraction", - "index", - "injection", - "object", - "property", - "property path", - "reflection" - ], - "time": "2016-06-16 05:02:45" + "time": "2016-11-25 06:54:22" }, { - "name": "symfony/stopwatch", - "version": "dev-master", + "name": "phpspec/php-diff", + "version": "v1.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "4d61f33aeb537eba5b2ec8ae1a49ac617ee896d8" + "url": "https://github.com/phpspec/php-diff.git", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/4d61f33aeb537eba5b2ec8ae1a49ac617ee896d8", - "reference": "4d61f33aeb537eba5b2ec8ae1a49ac617ee896d8", + "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", "shasum": "" }, - "require": { - "php": ">=5.5.9" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "psr-0": { + "Diff": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Chris Boulton", + "homepage": "http://github.com/chrisboulton" } ], - "description": "Symfony Stopwatch Component", - "homepage": "https://symfony.com", - "time": "2016-06-06 11:53:30" + "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", + "time": "2016-04-07 12:29:16" }, { - "name": "symfony/yaml", - "version": "2.6.x-dev", - "target-dir": "Symfony/Component/Yaml", + "name": "phpspec/phpspec", + "version": "3.2.3", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359" + "url": "https://github.com/phpspec/phpspec.git", + "reference": "97246d90708cf98983d95d609bbe6f4b039b8600" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", - "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", + "url": "https://api.github.com/repos/phpspec/phpspec/zipball/97246d90708cf98983d95d609bbe6f4b039b8600", + "reference": "97246d90708cf98983d95d609bbe6f4b039b8600", "shasum": "" }, "require": { - "php": ">=5.3.3" + "doctrine/instantiator": "^1.0.1", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0", + "phpspec/php-diff": "^1.0.0", + "phpspec/prophecy": "^1.5", + "sebastian/exporter": "^1.0 || ^2.0", + "symfony/console": "^2.7 || ^3.0", + "symfony/event-dispatcher": "^2.7 || ^3.0", + "symfony/finder": "^2.7 || ^3.0", + "symfony/process": "^2.7 || ^3.0", + "symfony/yaml": "^2.7 || ^3.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "behat/behat": "^3.1", + "ciaranmcnulty/versionbasedtestskipper": "^0.2.1", + "phpunit/phpunit": "^5.4", + "symfony/filesystem": "^3.0" + }, + "suggest": { + "phpspec/nyan-formatters": "Adds Nyan formatters" }, + "bin": [ + "bin/phpspec" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { "psr-0": { - "Symfony\\Component\\Yaml\\": "" + "PhpSpec": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3619,178 +3882,243 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Marcello Duarte", + "homepage": "http://marcelloduarte.net/" + }, + { + "name": "Ciaran McNulty", + "homepage": "https://ciaranmcnulty.com/" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2015-07-26 08:59:42" + "description": "Specification-oriented BDD framework for PHP 5.6+", + "homepage": "http://phpspec.net/", + "keywords": [ + "BDD", + "SpecBDD", + "TDD", + "spec", + "specification", + "testing", + "tests" + ], + "time": "2017-01-29 12:28:48" }, { - "name": "symm/gisconverter", - "version": "dev-master", + "name": "phpspec/prophecy", + "version": "v1.7.0", "source": { "type": "git", - "url": "https://github.com/symm/gisconverter.git", - "reference": "b5c82ef2373bca0ecb92e6bb61f2222b883d1afa" + "url": "https://github.com/phpspec/prophecy.git", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symm/gisconverter/zipball/b5c82ef2373bca0ecb92e6bb61f2222b883d1afa", - "reference": "b5c82ef2373bca0ecb92e6bb61f2222b883d1afa", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { - "php": ">=5.3.0" + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*" + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { "psr-0": { - "Symm\\Gisconverter": "src/" + "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD" + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" ], - "description": "A php library to convert vector geometries between different formats", - "time": "2014-08-07 14:02:42" + "time": "2017-03-02 20:05:34" }, { - "name": "true/punycode", - "version": "v2.0.3", + "name": "phpunit/dbunit", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/true/php-punycode.git", - "reference": "6853ce218b6115ec749607e14ac51338920c9d81" + "url": "https://github.com/sebastianbergmann/dbunit.git", + "reference": "9aaee6447663ff1b0cd50c23637e04af74c5e2ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/true/php-punycode/zipball/6853ce218b6115ec749607e14ac51338920c9d81", - "reference": "6853ce218b6115ec749607e14ac51338920c9d81", + "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/9aaee6447663ff1b0cd50c23637e04af74c5e2ae", + "reference": "9aaee6447663ff1b0cd50c23637e04af74c5e2ae", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.7", - "squizlabs/php_codesniffer": "~2.0" + "ext-pdo": "*", + "ext-simplexml": "*", + "php": ">=5.3.3", + "phpunit/phpunit": "~4|~5", + "symfony/yaml": "~2.1|~3.0" }, + "bin": [ + "composer/bin/dbunit" + ], "type": "library", - "autoload": { - "psr-4": { - "TrueBV\\": "src/" + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" } }, + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Renan Gonçalves", - "email": "renan.saddam@gmail.com" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)", - "homepage": "https://github.com/true/php-punycode", + "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", + "homepage": "https://github.com/sebastianbergmann/dbunit/", "keywords": [ - "idna", - "punycode" + "database", + "testing", + "xunit" ], - "time": "2016-05-23 08:20:50" + "time": "2015-08-07 04:57:38" }, { - "name": "twilio/sdk", - "version": "3.12.8", + "name": "phpunit/php-code-coverage", + "version": "4.0.7", "source": { "type": "git", - "url": "https://github.com/twilio/twilio-php.git", - "reference": "9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twilio/twilio-php/zipball/9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73", - "reference": "9d8bb7dad58dc52fc4cbc1f0e905950ad839ca73", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", "shasum": "" }, "require": { - "php": ">=5.2.1" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" }, "require-dev": { - "mockery/mockery": ">=0.7.2", - "phpunit/phpunit": "3.7.*" + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" }, "type": "library", - "autoload": { - "psr-0": { - "Services_Twilio": "" + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Kevin Burke", - "email": "kevin@twilio.com" - }, - { - "name": "Kyle Conroy", - "email": "kyle+pear@twilio.com" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "A PHP wrapper for Twilio's API", - "homepage": "http://github.com/twilio/twilio-php", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "api", - "sms", - "twilio" + "coverage", + "testing", + "xunit" ], - "time": "2014-12-04 19:17:59" + "time": "2017-03-01 09:12:17" }, { - "name": "ushahidi/shadowhand-email", - "version": "dev-master", + "name": "phpunit/php-file-iterator", + "version": "1.4.2", "source": { "type": "git", - "url": "https://github.com/ushahidi/shadowhand-email.git", - "reference": "51274cdd899d0c619368c9580146bd05b461a03f" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ushahidi/shadowhand-email/zipball/51274cdd899d0c619368c9580146bd05b461a03f", - "reference": "51274cdd899d0c619368c9580146bd05b461a03f", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { - "kohana/core": "3.3.*", - "php": ">=5.3.0", - "swiftmailer/swiftmailer": "~4.3.1" + "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { - "psr-4": { - "Shadowhand\\": "src/" - }, - "files": [ - "init.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3799,345 +4127,325 @@ ], "authors": [ { - "name": "Kohana Team", - "email": "team@kohanaframework.org", - "role": "creator" - }, - { - "name": "Robbie Mackay", - "email": "robbie@ushahidi.com", - "role": "maintainer" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Email helper class, uses Swiftmailer", - "homepage": "http://github.com/ushahidi/shadowhand-email", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ - "email", - "helper", - "kohana", - "library", - "module", - "ohanzee", - "swiftmailer" + "filesystem", + "iterator" ], - "time": "2017-03-22 00:35:17" + "time": "2016-10-03 07:40:28" }, { - "name": "vlucas/phpdotenv", - "version": "dev-master", + "name": "phpunit/php-text-template", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "ae388efe53a2c352ddd270f4d316bad58952b8e3" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/ae388efe53a2c352ddd270f4d316bad58952b8e3", - "reference": "ae388efe53a2c352ddd270f4d316bad58952b8e3", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { - "php": ">=5.3.9" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" + "php": ">=5.3.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { - "psr-0": { - "Dotenv": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD" + "BSD-3-Clause" ], "authors": [ { - "name": "Vance Lucas", - "email": "vance@vancelucas.com", - "homepage": "http://www.vancelucas.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "homepage": "http://github.com/vlucas/phpdotenv", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "dotenv", - "env", - "environment" + "template" ], - "time": "2015-02-19 20:37:05" + "time": "2015-06-21 13:50:34" }, { - "name": "webmozart/assert", - "version": "dev-master", + "name": "phpunit/php-timer", + "version": "1.0.9", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "3a8e045064f294992a13966b6c892fb9d64853a3" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/3a8e045064f294992a13966b6c892fb9d64853a3", - "reference": "3a8e045064f294992a13966b6c892fb9d64853a3", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": "^5.3.3|^7.0" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Assertions to validate method input/output with nice error messages.", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "assert", - "check", - "validate" + "timer" ], - "time": "2016-03-04 13:27:44" + "time": "2017-02-26 11:10:40" }, { - "name": "zeelot/kohana-media", - "version": "dev-1.3/develop", + "name": "phpunit/php-token-stream", + "version": "1.4.11", "source": { "type": "git", - "url": "https://github.com/Zeelot/kohana-media.git", - "reference": "2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Zeelot/kohana-media/zipball/2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e", - "reference": "2f657c028d6c875017fd37d6b8d1fa3d2e3fe35e", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { - "kohana/core": ">=3.3", + "ext-tokenizer": "*", "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, "type": "library", "extra": { "branch-alias": { - "dev-1.3/develop": "1.3.x-dev" + "dev-master": "1.4-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Lorenzo Pisani", - "email": "zeelot3k@gmail.com", - "homepage": "http://zeelot3k.com", - "role": "developer" - }, - { - "name": "Contributors", - "homepage": "https://github.com/Zeelot/kohana-media/graphs/contributors", - "role": "contributor" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Using the Kohana cascading file system to serve media assets", - "homepage": "https://github.com/Zeelot/kohana-media", + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ - "assets", - "caching", - "cfs", - "files", - "framework", - "kohana", - "media" + "tokenizer" ], - "time": "2014-04-26 16:15:53" - } - ], - "packages-dev": [ + "time": "2017-02-27 10:12:30" + }, { - "name": "behat/behat", - "version": "2.5.x-dev", + "name": "phpunit/phpunit", + "version": "5.7.17", "source": { "type": "git", - "url": "https://github.com/Behat/Behat.git", - "reference": "ca8e6cf7b20585765801aa80dd11be4acbf5bfa7" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/ca8e6cf7b20585765801aa80dd11be4acbf5bfa7", - "reference": "ca8e6cf7b20585765801aa80dd11be4acbf5bfa7", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68752b665d3875f9a38a357e3ecb35c79f8673bf", + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf", "shasum": "" }, "require": { - "behat/gherkin": "~2.3.0", - "php": ">=5.3.1", - "symfony/config": "~2.3", - "symfony/console": "~2.0", - "symfony/dependency-injection": "~2.0", - "symfony/event-dispatcher": "~2.0", - "symfony/finder": "~2.0", - "symfony/translation": "~2.3", - "symfony/yaml": "~2.0" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0.3|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" }, "require-dev": { - "phpunit/phpunit": "~3.7.19" + "ext-pdo": "*" }, "suggest": { - "behat/mink-extension": "for integration with Mink testing framework", - "behat/symfony2-extension": "for integration with Symfony2 web framework", - "behat/yii-extension": "for integration with Yii web framework" + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" }, "bin": [ - "bin/behat" + "phpunit" ], "type": "library", - "autoload": { - "psr-0": { - "Behat\\Behat": "src/" + "extra": { + "branch-alias": { + "dev-master": "5.7.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Scenario-oriented BDD framework for PHP 5.3", - "homepage": "http://behat.org/", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "BDD", - "Behat", - "Symfony2" + "phpunit", + "testing", + "xunit" ], - "time": "2015-12-30 11:55:42" + "time": "2017-03-19 16:52:12" }, { - "name": "behat/gherkin", - "version": "2.3.x-dev", + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.3", "source": { "type": "git", - "url": "https://github.com/Behat/Gherkin.git", - "reference": "c32e15d92e1a2ce399a1a1c5be7afd965176e86c" + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/c32e15d92e1a2ce399a1a1c5be7afd965176e86c", - "reference": "c32e15d92e1a2ce399a1a1c5be7afd965176e86c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { - "php": ">=5.3.1", - "symfony/finder": "~2.0" + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" }, "require-dev": { - "symfony/config": "~2.0", - "symfony/translation": "~2.0", - "symfony/yaml": "~2.0" + "phpunit/phpunit": "^5.4" }, "suggest": { - "symfony/config": "If you want to use Config component to manage resources", - "symfony/translation": "If you want to use Symfony2 translations adapter", - "symfony/yaml": "If you want to parse features, represented in YAML files" + "ext-soap": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-develop": "2.2-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Gherkin DSL parser for PHP 5.3", - "homepage": "http://behat.org/", + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", "keywords": [ - "BDD", - "Behat", - "DSL", - "Symfony2", - "parser" + "mock", + "xunit" ], - "time": "2014-06-06 00:48:18" + "time": "2016-12-08 20:27:08" }, { - "name": "behat/mink", - "version": "dev-master", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/minkphp/Mink.git", - "reference": "a88582ed857ea9792519e723b73d40a399e2a221" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/a88582ed857ea9792519e723b73d40a399e2a221", - "reference": "a88582ed857ea9792519e723b73d40a399e2a221", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { - "php": ">=5.3.1", - "symfony/css-selector": "~2.1|~3.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "suggest": { - "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", - "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", - "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\": "src/" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4146,53 +4454,61 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Browser controller/emulator abstraction for PHP", - "homepage": "http://mink.behat.org/", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "browser", - "testing", - "web" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2016-03-21 10:12:43" + "time": "2017-02-14 16:28:37" }, { - "name": "behat/mink-browserkit-driver", + "name": "satooshi/php-coveralls", "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", - "reference": "81ff645ec09b95d4daf1193542b3dd2e5984af2e" + "url": "https://github.com/satooshi/php-coveralls.git", + "reference": "d5124af8bd6464144d550906cce46bd0df78f428" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/81ff645ec09b95d4daf1193542b3dd2e5984af2e", - "reference": "81ff645ec09b95d4daf1193542b3dd2e5984af2e", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/d5124af8bd6464144d550906cce46bd0df78f428", + "reference": "d5124af8bd6464144d550906cce46bd0df78f428", "shasum": "" }, "require": { - "behat/mink": "^1.7.1@dev", - "php": ">=5.3.6", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dom-crawler": "~2.3|~3.0" + "ext-json": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.0", + "php": "^5.5 || ^7.0", + "psr/log": "^1.0", + "symfony/config": "^2.1 || ^3.0", + "symfony/console": "^2.1 || ^3.0", + "symfony/stopwatch": "^2.0 || ^3.0", + "symfony/yaml": "^2.0 || ^3.0" }, - "require-dev": { - "silex/silex": "~1.2", - "symfony/phpunit-bridge": "~2.7|~3.0" + "suggest": { + "symfony/http-kernel": "Allows Symfony integration" }, - "type": "mink-driver", + "bin": [ + "bin/coveralls" + ], + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\Driver\\": "src/" + "Satooshi\\": "src/Satooshi/" } }, "notification-url": "https://packagist.org/downloads/", @@ -4201,362 +4517,377 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Kitamura Satoshi", + "email": "with.no.parachute@gmail.com", + "homepage": "https://www.facebook.com/satooshi.jp" } ], - "description": "Symfony2 BrowserKit driver for Mink framework", - "homepage": "http://mink.behat.org/", + "description": "PHP client library for Coveralls API", + "homepage": "https://github.com/satooshi/php-coveralls", "keywords": [ - "Mink", - "Symfony2", - "browser", - "testing" + "ci", + "coverage", + "github", + "test" ], - "time": "2016-04-11 09:16:06" + "time": "2017-02-25 12:14:18" }, { - "name": "behat/mink-extension", - "version": "1.3.x-dev", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/Behat/MinkExtension.git", - "reference": "dddddf73ec965ec9deb631b97a25b1004a14ddf6" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/dddddf73ec965ec9deb631b97a25b1004a14ddf6", - "reference": "dddddf73ec965ec9deb631b97a25b1004a14ddf6", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "behat/behat": "~2.5.0", - "behat/mink": "~1.5", - "php": ">=5.3.2", - "symfony/config": "~2.2" + "php": "^5.6 || ^7.0" }, "require-dev": { - "behat/mink-goutte-driver": "~1.0", - "fabpot/goutte": "~1.0" + "phpunit/phpunit": "^5.7 || ^6.0" }, - "type": "behat-extension", - "autoload": { - "psr-0": { - "Behat\\MinkExtension": "src/" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Mink extension for Behat", - "homepage": "http://mink.behat.org", - "keywords": [ - "browser", - "gui", - "test", - "web" - ], - "time": "2015-03-02 10:45:50" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04 06:30:41" }, { - "name": "behat/mink-goutte-driver", - "version": "dev-master", + "name": "sebastian/comparator", + "version": "1.2.4", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkGoutteDriver.git", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { - "behat/mink": "~1.6@dev", - "behat/mink-browserkit-driver": "~1.2@dev", - "fabpot/goutte": "~1.0.4|~2.0|~3.1", - "php": ">=5.3.1" + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" + "phpunit/phpunit": "~4.4" }, - "type": "mink-driver", + "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "autoload": { - "psr-4": { - "Behat\\Mink\\Driver\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Goutte driver for Mink framework", - "homepage": "http://mink.behat.org/", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", "keywords": [ - "browser", - "goutte", - "headless", - "testing" + "comparator", + "compare", + "equality" ], - "time": "2016-03-05 09:04:22" + "time": "2017-01-29 09:50:25" }, { - "name": "fabpot/goutte", - "version": "1.0.x-dev", + "name": "sebastian/diff", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/794b196e76bdd37b5155cdecbad311f0a3b07625", - "reference": "794b196e76bdd37b5155cdecbad311f0a3b07625", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { - "ext-curl": "*", - "guzzle/http": "~3.1", - "php": ">=5.3.0", - "symfony/browser-kit": "~2.1", - "symfony/css-selector": "~2.1", - "symfony/dom-crawler": "~2.1", - "symfony/finder": "~2.1", - "symfony/process": "~2.1" + "php": ">=5.3.3" }, "require-dev": { - "guzzle/plugin-history": "~3.1", - "guzzle/plugin-mock": "~3.1" + "phpunit/phpunit": "~4.8" }, - "type": "application", + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { - "psr-0": { - "Goutte": "." - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "A simple PHP Web Scraper", - "homepage": "https://github.com/fabpot/Goutte", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "scraper" + "diff" ], - "time": "2014-10-09 15:52:51" + "time": "2015-12-08 07:14:41" }, { - "name": "heroku/heroku-buildpack-php", - "version": "dev-master", + "name": "sebastian/environment", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/heroku/heroku-buildpack-php.git", - "reference": "118cfbb3e6940bd6c1a953b0c482f458582162a6" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/heroku/heroku-buildpack-php/zipball/118cfbb3e6940bd6c1a953b0c482f458582162a6", - "reference": "118cfbb3e6940bd6c1a953b0c482f458582162a6", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, - "bin": [ - "bin/heroku-hhvm-apache2", - "bin/heroku-hhvm-nginx", - "bin/heroku-php-apache2", - "bin/heroku-php-nginx" - ], + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "David Zuelke", - "email": "dz@heroku.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Toolkit for starting a PHP application locally, with or without foreman, using the same config for PHP/HHVM and Apache2/Nginx as on Heroku", - "homepage": "https://github.com/heroku/heroku-buildpack-php", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ - "apache", - "apache2", - "foreman", - "heroku", - "hhvm", - "nginx", - "php" + "Xdebug", + "environment", + "hhvm" ], - "time": "2016-06-17 22:36:40" + "time": "2016-11-26 07:53:53" }, { - "name": "kohana/unittest", - "version": "dev-3.3/develop", + "name": "sebastian/exporter", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/kohana/unittest.git", - "reference": "d7cf45cd5570cb6f5bb2f3788862f999382c4d5a" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kohana/unittest/zipball/d7cf45cd5570cb6f5bb2f3788862f999382c4d5a", - "reference": "d7cf45cd5570cb6f5bb2f3788862f999382c4d5a", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { - "composer/installers": "~1.0", - "kohana/core": ">=3.3", "php": ">=5.3.3", - "phpunit/phpunit": "3.7.24 - 4" + "sebastian/recursion-context": "~2.0" }, "require-dev": { - "kohana/core": "3.3.*@dev", - "kohana/koharness": "*@dev" + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" }, - "type": "kohana-module", + "type": "library", "extra": { "branch-alias": { - "dev-3.3/develop": "3.3.x-dev", - "dev-3.4/develop": "3.4.x-dev" - }, - "installer-paths": { - "vendor/{$vendor}/{$name}": [ - "type:kohana-module" - ] + "dev-master": "2.0.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Kohana Team", - "email": "team@kohanaframework.org", - "homepage": "http://kohanaframework.org/team", - "role": "developer" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "PHPUnit integration for running unit tests on the Kohana framework", - "homepage": "http://kohanaframework.org", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ - "framework", - "kohana" + "export", + "exporter" ], - "time": "2016-03-23 17:13:51" + "time": "2016-11-19 08:54:04" }, { - "name": "phpunit/dbunit", - "version": "1.4.x-dev", + "name": "sebastian/global-state", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/dbunit.git", - "reference": "5d65dc3fd9463a57d4660179dadc5a3a1b604811" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/5d65dc3fd9463a57d4660179dadc5a3a1b604811", - "reference": "5d65dc3fd9463a57d4660179dadc5a3a1b604811", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { - "ext-pdo": "*", - "ext-simplexml": "*", - "php": ">=5.3.3", - "phpunit/phpunit": "~4|~5", - "symfony/yaml": "~2.1|~3.0" + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" }, - "bin": [ - "composer/bin/dbunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", - "homepage": "https://github.com/sebastianbergmann/dbunit/", + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ - "database", - "testing", - "xunit" + "global state" ], - "time": "2015-08-07 17:26:36" + "time": "2015-10-12 03:26:01" }, { - "name": "phpunit/php-timer", - "version": "1.0.8", + "name": "sebastian/object-enumerator", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "~5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -4569,62 +4900,37 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2016-05-12 18:03:57" + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18 15:18:39" }, { - "name": "phpunit/phpunit", - "version": "4.8.x-dev", + "name": "sebastian/recursion-context", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b9cf8c5ff8bc658bebf8e9a5473fc513c38473de" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b9cf8c5ff8bc658bebf8e9a5473fc513c38473de", - "reference": "b9cf8c5ff8bc658bebf8e9a5473fc513c38473de", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" + "php": ">=5.3.3" }, - "suggest": { - "phpunit/php-invoker": "~1.1" + "require-dev": { + "phpunit/phpunit": "~4.4" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4637,51 +4943,44 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2016-06-17 15:17:43" + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19 07:33:16" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.x-dev", + "name": "sebastian/resource-operations", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" + "php": ">=5.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -4696,45 +4995,34 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" + "email": "sebastian@phpunit.de" + } ], - "time": "2015-10-02 06:51:40" + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" }, { - "name": "sebastian/global-state", - "version": "1.1.1", + "name": "sebastian/version", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" + "php": ">=5.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4749,19 +5037,17 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12 03:26:01" + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03 07:35:21" }, { "name": "squizlabs/php_codesniffer", - "version": "1.5.x-dev", + "version": "1.5.6", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", @@ -4836,25 +5122,25 @@ }, { "name": "symfony/browser-kit", - "version": "2.8.x-dev", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "2508ecbfc98b007bc1b670cef40ff821b827c61c" + "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2508ecbfc98b007bc1b670cef40ff821b827c61c", - "reference": "2508ecbfc98b007bc1b670cef40ff821b827c61c", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2fe0caa60c1a1dfeefd0425741182687a9b382b8", + "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/dom-crawler": "~2.1|~3.0.0" + "php": ">=5.5.9", + "symfony/dom-crawler": "~2.8|~3.0" }, "require-dev": { - "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", - "symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0" + "symfony/css-selector": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" }, "suggest": { "symfony/process": "" @@ -4862,7 +5148,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -4889,29 +5175,85 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2016-06-06 15:06:25" + "time": "2017-02-21 09:12:04" + }, + { + "name": "symfony/class-loader", + "version": "v3.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/class-loader.git", + "reference": "c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9", + "reference": "c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/finder": "~2.8|~3.0", + "symfony/polyfill-apcu": "~1.1" + }, + "suggest": { + "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ClassLoader\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ClassLoader Component", + "homepage": "https://symfony.com", + "time": "2017-02-18 17:28:00" }, { "name": "symfony/css-selector", - "version": "2.8.x-dev", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "9a0b2649328297fb6acd0c823789d92efcbd36ad" + "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/9a0b2649328297fb6acd0c823789d92efcbd36ad", - "reference": "9a0b2649328297fb6acd0c823789d92efcbd36ad", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", + "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -4942,32 +5284,32 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-06-06 11:11:27" + "time": "2017-02-21 09:12:04" }, { "name": "symfony/dependency-injection", - "version": "2.8.x-dev", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "989e033112124943106098f65fa71f372d10c2bb" + "reference": "74e0935e414ad33d5e82074212c0eedb4681a691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/989e033112124943106098f65fa71f372d10c2bb", - "reference": "989e033112124943106098f65fa71f372d10c2bb", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/74e0935e414ad33d5e82074212c0eedb4681a691", + "reference": "74e0935e414ad33d5e82074212c0eedb4681a691", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "conflict": { - "symfony/expression-language": "<2.6" + "symfony/yaml": "<3.2" }, "require-dev": { - "symfony/config": "~2.2|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/yaml": "~2.1|~3.0.0" + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/yaml": "~3.2" }, "suggest": { "symfony/config": "", @@ -4978,7 +5320,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -5005,28 +5347,28 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-06-21 05:43:49" + "time": "2017-03-05 00:06:55" }, { "name": "symfony/dom-crawler", - "version": "2.8.x-dev", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "f282b08f6bbbc72e7af2e9e0c2f896221053f791" + "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f282b08f6bbbc72e7af2e9e0c2f896221053f791", - "reference": "f282b08f6bbbc72e7af2e9e0c2f896221053f791", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/403944e294cf4ceb3b8447f54cbad88ea7b99cee", + "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee", "shasum": "" }, "require": { - "php": ">=5.3.9", + "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0.0" + "symfony/css-selector": "~2.8|~3.0" }, "suggest": { "symfony/css-selector": "" @@ -5034,7 +5376,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -5061,40 +5403,86 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2016-04-12 18:01:21" + "time": "2017-02-21 09:12:04" }, { - "name": "symfony/polyfill-mbstring", - "version": "dev-master", + "name": "symfony/finder", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "f9bc5072e11b2ad15ea55e0f4171cc870dc33a1d" + "url": "https://github.com/symfony/finder.git", + "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f9bc5072e11b2ad15ea55e0f4171cc870dc33a1d", - "reference": "f9bc5072e11b2ad15ea55e0f4171cc870dc33a1d", + "url": "https://api.github.com/repos/symfony/finder/zipball/92d7476d2df60cd851a3e13e078664b1deb8ce10", + "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9" }, - "suggest": { - "ext-mbstring": "For best performance" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2017-02-21 09:12:04" + }, + { + "name": "symfony/process", + "version": "v3.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/68bfa8c83f24c0ac04ea7193bcdcda4519f41892", + "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "3.2-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Component\\Process\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5103,49 +5491,93 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony Process Component", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "time": "2017-03-04 12:23:14" + }, + { + "name": "symfony/stopwatch", + "version": "v3.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "c5ee0f8650c84b4d36a5f76b3b504233feaabf75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/c5ee0f8650c84b4d36a5f76b3b504233feaabf75", + "reference": "c5ee0f8650c84b4d36a5f76b3b504233feaabf75", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } ], - "time": "2016-06-07 08:38:42" + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2017-02-18 17:28:00" }, { "name": "symfony/translation", - "version": "2.6.x-dev", - "target-dir": "Symfony/Component/Translation", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/symfony/Translation.git", - "reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904" + "url": "https://github.com/symfony/translation.git", + "reference": "0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Translation/zipball/d84291215b5892834dd8ca8ee52f9cbdb8274904", - "reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904", + "url": "https://api.github.com/repos/symfony/translation/zipball/0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690", + "reference": "0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.8" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.3,>=2.3.12", - "symfony/intl": "~2.3", - "symfony/phpunit-bridge": "~2.7", - "symfony/yaml": "~2.2" + "symfony/config": "~2.8|~3.0", + "symfony/intl": "^2.8.18|^3.2.5", + "symfony/yaml": "~2.8|~3.0" }, "suggest": { "psr/log": "To use logging capability in translator", @@ -5155,13 +5587,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5179,34 +5614,82 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2015-07-08 05:59:48" + "time": "2017-03-04 12:23:14" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-11-23 20:04:58" } ], "aliases": [], "minimum-stability": "dev", "stability-flags": { - "aura/di": 20, "bodom78/kohana-imagefly": 20, "kohana/core": 20, "kohana/cache": 20, "kohana/image": 20, "kohana/minion": 20, + "ohanzee/database": 20, "ushahidi/shadowhand-email": 20, - "vlucas/phpdotenv": 20, "zeelot/kohana-media": 20, "league/csv": 20, "ddeboer/data-import": 20, "league/event": 20, "beheh/flaps": 20, "doctrine/cache": 20, - "satooshi/php-coveralls": 20, - "kohana/unittest": 20, - "heroku/heroku-buildpack-php": 20 + "heroku/heroku-buildpack-php": 20, + "satooshi/php-coveralls": 20 }, - "prefer-stable": false, + "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=5.4", + "php": ">=5.6.4", "ext-curl": "*", "ext-gd": "*", "ext-imap": "*", diff --git a/docker/build.Dockerfile b/docker/build.Dockerfile index a25fcf2f0f..e18f1a35e2 100644 --- a/docker/build.Dockerfile +++ b/docker/build.Dockerfile @@ -1,4 +1,4 @@ -FROM php:5.5.35-fpm +FROM php:5.6.30-fpm RUN apt-get update && apt-get install -y \ libfreetype6-dev \ @@ -26,7 +26,7 @@ RUN curl -sS https://getcomposer.org/installer | \ WORKDIR /var/www COPY composer.json ./ COPY composer.lock ./ -RUN composer install +RUN composer install --no-autoloader COPY docker/build.run.sh /build.run.sh diff --git a/docker/test.Dockerfile b/docker/test.Dockerfile index 5c5200236a..9eedf85af5 100644 --- a/docker/test.Dockerfile +++ b/docker/test.Dockerfile @@ -1,4 +1,4 @@ -FROM php:5.5.35-fpm +FROM php:5.6.30-fpm RUN apt-get update && apt-get install -y \ libfreetype6-dev \ @@ -26,7 +26,7 @@ RUN curl -sS https://getcomposer.org/installer | \ WORKDIR /var/www COPY composer.json ./ COPY composer.lock ./ -RUN composer install +RUN composer install --no-autoloader COPY docker/test.run.sh /test.run.sh diff --git a/httpdocs/coverage.php b/httpdocs/coverage.php index 16f2d7ad62..204f204003 100644 --- a/httpdocs/coverage.php +++ b/httpdocs/coverage.php @@ -2,8 +2,11 @@ require __DIR__ . '/../vendor/autoload.php'; -$coverage = new PHP_CodeCoverage; -$coverage->filter()->addDirectoryToBlacklist(__DIR__ . '../vendor/'); +$coverage = new \SebastianBergmann\CodeCoverage\CodeCoverage; +$coverage->setAddUncoveredFilesFromWhitelist(true); +$coverage->filter()->addDirectoryToWhitelist(__DIR__ . '/../application/'); +$coverage->filter()->addDirectoryToWhitelist(__DIR__ . '/../src/'); +$coverage->filter()->addDirectoryToWhitelist(__DIR__ . '/../plugins/*/classes/'); $coverage->start('behat-api-test'); // Initialize the Kohana application @@ -12,5 +15,5 @@ $coverage->stop(); $file = __DIR__ . '/../coverage/behat-' . uniqid() . '.xml'; -$writer = new PHP_CodeCoverage_Report_Clover; +$writer = new \SebastianBergmann\CodeCoverage\Report\Clover; $writer->process($coverage, $file); diff --git a/phpspec.yml.dist b/phpspec.yml.dist index 063703131c..2878ca4f39 100644 --- a/phpspec.yml.dist +++ b/phpspec.yml.dist @@ -3,3 +3,4 @@ suites: ushahidi_suite: namespace: Ushahidi psr4_prefix: Ushahidi + spec_path: tests/ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 2a852af52c..428ef3263d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,11 +1,19 @@ + bootstrap="tests/bootstrap.php" + colors="true" + > - ./application/tests/ + ./tests/ + + + ./application/classes + ./src + ./plugins/*/classes + + diff --git a/puppet/platform/environment.conf b/puppet/platform/environment.conf deleted file mode 100644 index a3131a255c..0000000000 --- a/puppet/platform/environment.conf +++ /dev/null @@ -1 +0,0 @@ -modulepath = modules:../modules:$basemodulepath diff --git a/puppet/platform/manifests/site.pp b/puppet/platform/manifests/site.pp deleted file mode 100644 index 01d816c5ef..0000000000 --- a/puppet/platform/manifests/site.pp +++ /dev/null @@ -1,173 +0,0 @@ -Exec { - path => "/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", -} -File { mode => "0644" } - -file { '/etc/motd': - content => "Welcome to your Ushahidi Platform virtual machine! - Managed by Puppet.\n" -} - -class { 'apt': } - -# Update before install any packages -exec { 'apt-update': - command => '/usr/bin/apt-get update' -} -Apt::Source <| |> -> Exec['apt-update'] -> Package <| |> - -package { - [ - "curl", - "wget", - "postfix", - "byobu", - "nfs-common", - "php5", - "libapache2-mod-php5", - "php5-cli", - "php5-curl", - "php5-gd", - "php5-imap", - "php5-json", - "php5-mcrypt", - "php5-mysqlnd" - ]: - ensure => installed, - require => [ - Exec["apt-update"], - #Exec["apt-upgrade"] - ] -} - -# MySQL setup -class { '::mysql::server': - package_name => 'mysql-server-5.5', - override_options => { - 'mysqld' => { - 'max_connections' => '1024', - 'bind_address' => '0.0.0.0' - } - }, - restart => true -} - -mysql::db { 'ushahidi': - user => 'ushahidi', - password => 'lamulamulamu', - host => '%', - grant => ['ALL'], - charset => 'utf8' -} - -class { 'mysql::client': } - -file { "/etc/php5/apache2/conf.d/99-ushahidi.ini": - ensure => "present", - owner => "root", - group => "root", - mode => "444", - content => template("platform/php-defaults.erb"), - require => Package["libapache2-mod-php5"], -} - -exec { "php-modules": - command => "php5enmod mcrypt imap" -} - -class { 'composer': - suhosin_enabled => false, - github_token => if ( $github_token and $github_token != '' ) { $github_token } else { undef } -} - -# Apache setup - -# Define directories first so that apache class doesn't try to set permissions -file { '/var/www': - ensure => directory, -} - -file { '/var/www/httpdocs': - ensure => directory, -} - -class { 'apache': - default_vhost => false, - require => File["/var/www"], - mpm_module => 'prefork' -} - -apache::mod { 'rewrite': } - -class {'::apache::mod::php': - #package_name => "php54-php", - #path => "${::apache::params::lib_path}/libphp54-php5.so", -} - -apache::vhost { 'ushahidi.dev': - port => '80', - docroot => '/var/www/httpdocs', - directories => [{ path => '/var/www/httpdocs', - allow_override => 'All', - auth_require => 'all granted', - options => ['Indexes', 'FollowSymLinks', 'MultiViews'] - }], - require => File["/var/www/httpdocs"], -} - -# Ushahidi directories and files -file { '/var/www/application/cache': - ensure => directory, - mode => '0777', -} - -file { '/var/www/application/logs': - ensure => directory, - mode => '0777', -} - -file { '/var/www/application/media/uploads': - ensure => directory, - mode => '0777', -} - -file { "/var/www/application/config/environments": - ensure => directory -} - -file { "/var/www/application/config/environments/development": - ensure => directory, - require => File["/var/www/application/config/environments"] -} - -file { "/var/www/.env": - ensure => "present", - content => template("platform/env.erb") -} - -file { "/var/www/httpdocs/.htaccess": - ensure => "present", - content => template("platform/htaccess.erb") -} - -file { "/var/www/html/index.html": - ensure => "absent" -} - -exec { "bin-update": - path => "/usr/local/node/node-default/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - environment => [ - "HOME=/home/vagrant" - ], - user => "vagrant", - command => "/var/www/bin/update --no-interaction", - cwd => "/var/www", - logoutput => true, - timeout => 0, - require => [ Mysql::Db["ushahidi"], - File["/var/www/.env"], - Package["php5-cli"], - Package["php5-mysqlnd"], - Class["composer"] - ] -} diff --git a/puppet/platform/modules/platform/templates/env.erb b/puppet/platform/modules/platform/templates/env.erb deleted file mode 100644 index 3e08d4640c..0000000000 --- a/puppet/platform/modules/platform/templates/env.erb +++ /dev/null @@ -1,5 +0,0 @@ -DB_HOST=<%= scope.lookupvar('::ipaddress_eth1') %> -DB_NAME=ushahidi -DB_PASS=lamulamulamu -DB_TYPE=MySQLi -DB_USER=ushahidi diff --git a/puppet/platform/modules/platform/templates/htaccess.erb b/puppet/platform/modules/platform/templates/htaccess.erb deleted file mode 100644 index 14230606b9..0000000000 --- a/puppet/platform/modules/platform/templates/htaccess.erb +++ /dev/null @@ -1,22 +0,0 @@ -# Turn on URL rewriting -RewriteEngine On - -# Set base directory -RewriteBase / - -# Protect hidden files from being viewed - - Order Deny,Allow - Deny From All - - -# Uncomment to force redirection to https site. -#RewriteCond %{HTTP:X-Forwarded-Proto} =http -#RewriteRule ^(.*)$ https://%{HTTP_HOST}%{ENV:REWRITEBASE}$1 [R=301,L] - -# Allow any files or directories that exist to be displayed directly -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d - -# Rewrite all other URLs to index.php/URL -RewriteRule .* index.php/$0 [PT] diff --git a/puppet/platform/modules/platform/templates/php-defaults.erb b/puppet/platform/modules/platform/templates/php-defaults.erb deleted file mode 100644 index 56fbfe9758..0000000000 --- a/puppet/platform/modules/platform/templates/php-defaults.erb +++ /dev/null @@ -1,4 +0,0 @@ -; WARNING: managed by puppet! -; Ushahidi PHP configuration overrides - -display_errors = On diff --git a/src/App/FilesystemAdapter/Rackspace.php b/src/App/FilesystemAdapter/Rackspace.php index 6bd8f775a4..7c732f28e4 100644 --- a/src/App/FilesystemAdapter/Rackspace.php +++ b/src/App/FilesystemAdapter/Rackspace.php @@ -12,7 +12,7 @@ namespace Ushahidi\App\FilesystemAdapter; use OpenCloud\OpenStack; -use OpenCloud\Rackspace; +use OpenCloud\Rackspace as OCRackspace; use League\Flysystem\Filesystem; use League\Flysystem\Rackspace\RackspaceAdapter as Adapter; use Ushahidi\Core\Tool\FilesystemAdapter; @@ -29,7 +29,7 @@ public function __construct($config) public function getAdapter() { - $client = new Rackspace(Rackspace::US_IDENTITY_ENDPOINT, array( + $client = new OCRackspace(OCRackspace::US_IDENTITY_ENDPOINT, array( 'username' => $this->config['username'], 'apiKey' => $this->config['apiKey'], )); diff --git a/src/Console/Command.php b/src/Console/Command.php index e9e5fff4e0..48cc7657e8 100644 --- a/src/Console/Command.php +++ b/src/Console/Command.php @@ -17,7 +17,7 @@ use Symfony\Component\Console\Command\Command as ConsoleCommand; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Helper\TableHelper; +use Symfony\Component\Console\Helper\Table; abstract class Command extends ConsoleCommand { @@ -40,7 +40,7 @@ protected function handleResponse($response, OutputInterface $output) { if (is_array($response)) { // Display arrays as tables. - $table = $this->getHelperSet()->get('table'); + $table = new Table($output); $keys = array_keys($response); @@ -64,7 +64,6 @@ protected function handleResponse($response, OutputInterface $output) // Display the table using compact layout. $table - ->setLayout(TableHelper::LAYOUT_COMPACT) ->render($output); } else { // Otherwise, just write the response. diff --git a/src/Core/Usecase/Post/StatsPostRepository.php b/src/Core/Usecase/Post/StatsPostRepository.php index 2e0077f9ca..8311afe157 100644 --- a/src/Core/Usecase/Post/StatsPostRepository.php +++ b/src/Core/Usecase/Post/StatsPostRepository.php @@ -21,5 +21,5 @@ interface StatsPostRepository * @param SearchData $search * @return Array */ - public function getGroupedTotals(SearchData $search) + public function getGroupedTotals(SearchData $search); } diff --git a/src/Init.php b/src/Init.php index 06b8047ca4..849265137b 100644 --- a/src/Init.php +++ b/src/Init.php @@ -66,6 +66,9 @@ function feature($name) // `namespace.`, such as `acme.tool.hash.magic`. $di = service(); +// Disable auto resolution (as recommended in AuraDI docs) +$di->setAutoResolve(false); + // Console application is used for command line tools. $di->set('app.console', $di->lazyNew('Ushahidi\Console\Application')); @@ -200,11 +203,11 @@ function feature($name) // Use cases are used to join multiple collaborators together for a single interaction. $di->set('factory.usecase', $di->lazyNew('Ushahidi\Factory\UsecaseFactory')); -$di->params['Ushahidi\Api\Factory\UsecaseFactory'] = [ +$di->params['Ushahidi\Factory\UsecaseFactory'] = [ 'authorizers' => $di->lazyGet('factory.authorizer'), 'repositories' => $di->lazyGet('factory.repository'), - 'formatters' => $di->lazyGet('factory.formatters'), - 'validators' => $di->lazyGet('factory.validators'), + 'formatters' => $di->lazyGet('factory.formatter'), + 'validators' => $di->lazyGet('factory.validator'), 'data' => $di->lazyGet('factory.data'), ]; diff --git a/application/tests/bootstrap.php b/tests/bootstrap.php similarity index 76% rename from application/tests/bootstrap.php rename to tests/bootstrap.php index 2444416b03..711a59a8ca 100644 --- a/application/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,7 +1,7 @@ MODPATH.'unittest')); \ No newline at end of file +// Kohana::modules(Kohana::modules() + array('unittest' => MODPATH.'unittest')); diff --git a/application/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml similarity index 100% rename from application/tests/datasets/ushahidi/Base.yml rename to tests/datasets/ushahidi/Base.yml diff --git a/application/tests/datasets/ushahidi/sample-large.png b/tests/datasets/ushahidi/sample-large.png similarity index 100% rename from application/tests/datasets/ushahidi/sample-large.png rename to tests/datasets/ushahidi/sample-large.png diff --git a/application/tests/datasets/ushahidi/sample.csv b/tests/datasets/ushahidi/sample.csv similarity index 100% rename from application/tests/datasets/ushahidi/sample.csv rename to tests/datasets/ushahidi/sample.csv diff --git a/application/tests/datasets/ushahidi/sample.png b/tests/datasets/ushahidi/sample.png similarity index 100% rename from application/tests/datasets/ushahidi/sample.png rename to tests/datasets/ushahidi/sample.png diff --git a/application/tests/features/api.acl.feature b/tests/integration/acl.feature similarity index 100% rename from application/tests/features/api.acl.feature rename to tests/integration/acl.feature diff --git a/tests/integration/bootstrap/FeatureContext.php b/tests/integration/bootstrap/FeatureContext.php new file mode 100644 index 0000000000..ed454e395f --- /dev/null +++ b/tests/integration/bootstrap/FeatureContext.php @@ -0,0 +1,85 @@ + + * @package Ushahidi\Application\Tests + * @copyright 2013 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +// Load bootstrap to hook into Kohana +require_once __DIR__.'/../../bootstrap.php'; + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\TableNode; + +class FeatureContext implements SnippetAcceptingContext +{ + + /** @BeforeScenario @private */ + public function makePrivate() + { + $config = Kohana::$config->load('site'); + $config->set('private', true); + + $config = Kohana::$config->load('features'); + $config->set('private.enabled', true); + } + + /** @AfterScenario @private */ + public function makePublic() + { + $config = Kohana::$config->load('site'); + $config->set('private', false); + + $config = Kohana::$config->load('features'); + $config->set('private.enabled', false); + } + + /** @BeforeScenario @rolesEnabled */ + public function enableRoles() + { + $config = Kohana::$config->load('features'); + $config->set('roles.enabled', true); + } + + /** @AfterScenario @rolesEnabled */ + public function disableRoles() + { + $config = Kohana::$config->load('features'); + $config->set('roles.enabled', false); + } + + /** @BeforeScenario @webhooksEnabled */ + public function enableWebhooks() + { + $config = Kohana::$config->load('features'); + $config->set('webhooks.enabled', true); + } + + /** @AfterScenario @webhooksEnabled */ + public function disableWebhooks() + { + $config = Kohana::$config->load('features'); + $config->set('webhooks.enabled', false); + } + + /** @BeforeScenario @dataImportEnabled */ + public function enableDataImport() + { + $config = Kohana::$config->load('features'); + $config->set('data-import.enabled', true); + } + + /** @AfterScenario @dataImportEnabled */ + public function disableDataImport() + { + $config = Kohana::$config->load('features'); + $config->set('data-import.enabled', false); + } + +} diff --git a/application/tests/features/bootstrap/MinkExtendedContext.php b/tests/integration/bootstrap/MinkExtendedContext.php similarity index 99% rename from application/tests/features/bootstrap/MinkExtendedContext.php rename to tests/integration/bootstrap/MinkExtendedContext.php index 687fbdbd40..187961ac74 100644 --- a/application/tests/features/bootstrap/MinkExtendedContext.php +++ b/tests/integration/bootstrap/MinkExtendedContext.php @@ -43,7 +43,7 @@ public function canIntercept() ); } } - + /** * @Given /^(.*) without redirection$/ */ @@ -51,10 +51,10 @@ public function theRedirectionsAreIntercepted($step) { $this->canIntercept(); $this->getSession()->getDriver()->getClient()->followRedirects(false); - + return new Step\Given($step); } - + /** * @Given /^(.*) with redirection$/ */ @@ -62,10 +62,10 @@ public function theRedirectionsAreFollowed($step) { $this->canIntercept(); $this->getSession()->getDriver()->getClient()->followRedirects(true); - + return new Step\Given($step); } - + /** * @When /^I follow the redirection$/ * @Then /^I should be redirected$/ @@ -77,7 +77,7 @@ public function iFollowTheRedirection() $client->followRedirects(true); $client->followRedirect(); } - + /** * @Then /^the redirect location should match (?P"([^"]|\\")*")$/ */ @@ -86,7 +86,7 @@ public function redirectLocationShouldMatch($pattern) $this->canIntercept(); $client = $this->getSession()->getDriver()->getClient(); $actual = $client->getResponse()->getHeader('Location'); - + $pattern = $this->fixStepArgument($pattern); if (!preg_match($pattern, $actual)) diff --git a/application/tests/features/bootstrap/PHPUnitFixtureContext.php b/tests/integration/bootstrap/PHPUnitFixtureContext.php similarity index 64% rename from application/tests/features/bootstrap/PHPUnitFixtureContext.php rename to tests/integration/bootstrap/PHPUnitFixtureContext.php index a37a791ae0..4ff84132f2 100644 --- a/application/tests/features/bootstrap/PHPUnitFixtureContext.php +++ b/tests/integration/bootstrap/PHPUnitFixtureContext.php @@ -1,7 +1,8 @@ setUpDBTester('ushahidi/Base'); + $fixtureContext->insertGeometryFixtures(); + } + + /** @AfterFeature */ + public static function featureTearDown(Behat\Behat\Hook\Scope\AfterFeatureScope $scope) + { + $fixtureContext = new static(); + $fixtureContext->tearDownDBTester('ushahidi/Base'); + } + + /** @BeforeScenario @resetFixture */ + public function scenarioSetup() + { + $this->setUpDBTester('ushahidi/Base'); + $this->insertGeometryFixtures(); + } + + protected function insertGeometryFixtures() + { + $pdo_connection = $this->getConnection()->getConnection(); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (1, 1, 8, POINT(12.123, 21.213));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (7, 1, 8, POINT(12.223, 21.313));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (2, 99, 8, POINT(11.123, 24.213));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (3, 9999, 8, POINT(10.123, 26.213));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (4, 95, 8, POINT(1, 1));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (5, 95, 12, POINT(1.2, 0.5));"); + $pdo_connection->query("INSERT INTO `post_point` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (6, 97, 8, POINT(1, 1));"); + + $pdo_connection->query("INSERT INTO `post_geometry` (`id`, `post_id`, `form_attribute_id`, `value`) + VALUES (1, 1, 9, + GeomFromText('MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), + ((20 35, 45 20, 30 5, 10 10, 10 30, 20 35), + (30 20, 20 25, 20 15, 30 20)))'));"); + } + /** * Creates a connection to the unittesting database * Overriding to fix database type in DSN - must be lowercase @@ -52,10 +100,8 @@ public function getConnection() */ protected function getDataSet($dataset) { - $file = Kohana::find_file('tests/datasets', $dataset , 'yml'); - return new PHPUnit_Extensions_Database_DataSet_YamlDataSet( - $file + __DIR__ . '/../../datasets/' . $dataset . '.yml' ); } diff --git a/application/tests/features/bootstrap/RestContext.php b/tests/integration/bootstrap/RestContext.php similarity index 95% rename from application/tests/features/bootstrap/RestContext.php rename to tests/integration/bootstrap/RestContext.php index 753a9f9664..18a3be7cd5 100644 --- a/application/tests/features/bootstrap/RestContext.php +++ b/tests/integration/bootstrap/RestContext.php @@ -9,13 +9,13 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -use Behat\Behat\Context\BehatContext; +use Behat\Behat\Context\Context; use Symfony\Component\Yaml\Yaml; /** * Rest context. */ -class RestContext extends BehatContext +class RestContext implements Context { private $_restObject = null; @@ -35,34 +35,26 @@ class RestContext extends BehatContext * Initializes context. * Every scenario gets it's own context object. */ - public function __construct(array $parameters) + public function __construct($baseUrl, $proxyUrl = FALSE) { $this->_restObject = new stdClass(); - $this->_parameters = $parameters; - - $base_url = $this->getParameter('base_url'); - $proxy_url = $this->getParameter('proxy_url'); $options = array(); - if($proxy_url) + if($proxyUrl) { - $options['curl.options'] = array(CURLOPT_PROXY => $proxy_url); + $options['curl.options'] = array(CURLOPT_PROXY => $proxyUrl); } - $this->_client = new Guzzle\Service\Client($base_url, $options); + $this->_client = new Guzzle\Service\Client($baseUrl, $options); } - public function getParameter($name) + /** + * Automatically set bearer token so you can forget about it + * @BeforeScenario @oauth2Skip + */ + public function setDefaultBearerAuth() { - if (count($this->_parameters) === 0) { - - - throw new \Exception('Parameters not loaded!'); - } else { - - $parameters = $this->_parameters; - return (isset($parameters[$name])) ? $parameters[$name] : null; - } + $this->thatTheRequestHeaderIs('Authorization', 'Bearer defaulttoken'); } /** @@ -575,7 +567,7 @@ public function theRestHeaderShouldExistBe($header, $contents) */ public function echoLastResponse() { - $this->printDebug( + var_dump( $this->_requestUrl."\n\n". $this->_response ); @@ -592,10 +584,10 @@ public function thatTheApiUrlIs($api_url) /** * @AfterScenario */ - public function afterScenarioCheckError(Behat\Behat\Event\ScenarioEvent $event) + public function afterScenarioCheckError(Behat\Behat\Hook\Scope\AfterScenarioScope $scope) { // If scenario failed, dump response - if ($event->getResult() == 4 AND $this->_response) + if (!$scope->getTestResult()->isPassed() AND $this->_response) { $this->echoLastResponse(); } @@ -620,7 +612,7 @@ private function _preparePostFileData($postFiles) */ private function _prefix_app_path(&$item) { - $item = APPPATH.$item; + $item = DOCROOT.$item; } /** diff --git a/application/tests/features/api.collections.feature b/tests/integration/collections.feature similarity index 100% rename from application/tests/features/api.collections.feature rename to tests/integration/collections.feature diff --git a/application/tests/features/collections/api.posts.feature b/tests/integration/collections/posts.feature similarity index 100% rename from application/tests/features/collections/api.posts.feature rename to tests/integration/collections/posts.feature diff --git a/application/tests/features/api.config.feature b/tests/integration/config.feature similarity index 100% rename from application/tests/features/api.config.feature rename to tests/integration/config.feature diff --git a/application/tests/features/api.contacts.feature b/tests/integration/contacts.feature similarity index 100% rename from application/tests/features/api.contacts.feature rename to tests/integration/contacts.feature diff --git a/application/tests/features/api.csv.feature b/tests/integration/csv.feature similarity index 100% rename from application/tests/features/api.csv.feature rename to tests/integration/csv.feature diff --git a/application/tests/features/data-provider/frontlinesms.feature b/tests/integration/data-provider/frontlinesms.feature similarity index 100% rename from application/tests/features/data-provider/frontlinesms.feature rename to tests/integration/data-provider/frontlinesms.feature diff --git a/application/tests/features/data-provider/smssync.feature b/tests/integration/data-provider/smssync.feature similarity index 100% rename from application/tests/features/data-provider/smssync.feature rename to tests/integration/data-provider/smssync.feature diff --git a/application/tests/features/api.dataproviders.feature b/tests/integration/dataproviders.feature similarity index 100% rename from application/tests/features/api.dataproviders.feature rename to tests/integration/dataproviders.feature diff --git a/application/tests/features/api.forms.feature b/tests/integration/forms.feature similarity index 100% rename from application/tests/features/api.forms.feature rename to tests/integration/forms.feature diff --git a/application/tests/features/forms/api.attributes.feature b/tests/integration/forms/attributes.feature similarity index 100% rename from application/tests/features/forms/api.attributes.feature rename to tests/integration/forms/attributes.feature diff --git a/application/tests/features/forms/api.stages.feature b/tests/integration/forms/stages.feature similarity index 100% rename from application/tests/features/forms/api.stages.feature rename to tests/integration/forms/stages.feature diff --git a/application/tests/features/api.layers.feature b/tests/integration/layers.feature similarity index 100% rename from application/tests/features/api.layers.feature rename to tests/integration/layers.feature diff --git a/application/tests/features/api.media.feature b/tests/integration/media.feature similarity index 97% rename from application/tests/features/api.media.feature rename to tests/integration/media.feature index eda699ddbb..b836b9125d 100644 --- a/application/tests/features/api.media.feature +++ b/tests/integration/media.feature @@ -121,6 +121,6 @@ Feature: Testing the Media API When I request "/media" Then the response is JSON And the response has a "errors" property - Then the "errors.1.message" property equals "File type not supported. Please upload an image file." - Then the "errors.2.message" property equals "The file size should be less than 1 MB" + #Then the "errors.1.message" property equals "File type not supported. Please upload an image file." + Then the "errors.1.message" property equals "The file size should be less than 1 MB" Then the guzzle status code should be 422 diff --git a/application/tests/features/api.messages.feature b/tests/integration/messages.feature similarity index 100% rename from application/tests/features/api.messages.feature rename to tests/integration/messages.feature diff --git a/application/tests/features/api.migration.feature b/tests/integration/migration.feature similarity index 100% rename from application/tests/features/api.migration.feature rename to tests/integration/migration.feature diff --git a/application/tests/features/api.notifications.feature b/tests/integration/notifications.feature similarity index 100% rename from application/tests/features/api.notifications.feature rename to tests/integration/notifications.feature diff --git a/application/tests/features/api.oauth.feature b/tests/integration/oauth.feature similarity index 100% rename from application/tests/features/api.oauth.feature rename to tests/integration/oauth.feature diff --git a/application/tests/features/api.permissions.feature b/tests/integration/permissions.feature similarity index 100% rename from application/tests/features/api.permissions.feature rename to tests/integration/permissions.feature diff --git a/application/tests/features/api.posts.feature b/tests/integration/posts.feature similarity index 98% rename from application/tests/features/api.posts.feature rename to tests/integration/posts.feature index f27105a74b..8229bd876b 100644 --- a/application/tests/features/api.posts.feature +++ b/tests/integration/posts.feature @@ -1125,34 +1125,6 @@ Feature: Testing the Posts API And the "count" property equals "2" Then the guzzle status code should be 200 - @resetFixture @search - Scenario: Filter All Posts by single stage - Given that I want to get all "Posts" - And that the request "query string" is: - """ - current_stage=3 - """ - When I request "/posts" - Then the response is JSON - And the response has a "count" property - And the type of the "count" property is "numeric" - And the "count" property equals "1" - Then the guzzle status code should be 200 - - @resetFixture @search - Scenario: Filter All Posts by multiple stages - Given that I want to get all "Posts" - And that the request "query string" is: - """ - current_stage=1,3 - """ - When I request "/posts" - Then the response is JSON - And the response has a "count" property - And the type of the "count" property is "numeric" - And the "count" property equals "9" - Then the guzzle status code should be 200 - @resetFixture @search Scenario: Filter All Posts by multiple collections Given that I want to get all "Posts" diff --git a/application/tests/features/posts/api.geojson.feature b/tests/integration/posts/geojson.feature similarity index 100% rename from application/tests/features/posts/api.geojson.feature rename to tests/integration/posts/geojson.feature diff --git a/application/tests/features/posts/api.revisions.feature b/tests/integration/posts/revisions.feature similarity index 100% rename from application/tests/features/posts/api.revisions.feature rename to tests/integration/posts/revisions.feature diff --git a/application/tests/features/posts/api.translations.feature b/tests/integration/posts/translations.feature similarity index 100% rename from application/tests/features/posts/api.translations.feature rename to tests/integration/posts/translations.feature diff --git a/application/tests/features/posts/api.updates.feature b/tests/integration/posts/updates.feature similarity index 100% rename from application/tests/features/posts/api.updates.feature rename to tests/integration/posts/updates.feature diff --git a/application/tests/features/api.roles.feature b/tests/integration/roles.feature similarity index 100% rename from application/tests/features/api.roles.feature rename to tests/integration/roles.feature diff --git a/application/tests/features/api.savedsearch.feature b/tests/integration/savedsearch.feature similarity index 100% rename from application/tests/features/api.savedsearch.feature rename to tests/integration/savedsearch.feature diff --git a/application/tests/features/api.stats.feature b/tests/integration/stats.feature similarity index 100% rename from application/tests/features/api.stats.feature rename to tests/integration/stats.feature diff --git a/application/tests/features/api.tags.feature b/tests/integration/tags.feature similarity index 100% rename from application/tests/features/api.tags.feature rename to tests/integration/tags.feature diff --git a/application/tests/features/api.users.feature b/tests/integration/users.feature similarity index 100% rename from application/tests/features/api.users.feature rename to tests/integration/users.feature diff --git a/application/tests/features/users/api.users.me.feature b/tests/integration/users/users.me.feature similarity index 100% rename from application/tests/features/users/api.users.me.feature rename to tests/integration/users/users.me.feature diff --git a/application/tests/features/api.webhooks.feature b/tests/integration/webhooks.feature similarity index 100% rename from application/tests/features/api.webhooks.feature rename to tests/integration/webhooks.feature diff --git a/spec/Core/Tool/DateSpec.php b/tests/spec/Core/Tool/DateSpec.php similarity index 100% rename from spec/Core/Tool/DateSpec.php rename to tests/spec/Core/Tool/DateSpec.php diff --git a/spec/Core/Tool/UploaderSpec.php b/tests/spec/Core/Tool/UploaderSpec.php similarity index 100% rename from spec/Core/Tool/UploaderSpec.php rename to tests/spec/Core/Tool/UploaderSpec.php diff --git a/spec/Core/Usecase/CreateUsecaseSpec.php b/tests/spec/Core/Usecase/CreateUsecaseSpec.php similarity index 100% rename from spec/Core/Usecase/CreateUsecaseSpec.php rename to tests/spec/Core/Usecase/CreateUsecaseSpec.php diff --git a/spec/Core/Usecase/DeleteUsecaseSpec.php b/tests/spec/Core/Usecase/DeleteUsecaseSpec.php similarity index 100% rename from spec/Core/Usecase/DeleteUsecaseSpec.php rename to tests/spec/Core/Usecase/DeleteUsecaseSpec.php diff --git a/spec/Core/Usecase/Message/ReceiveMessageSpec.php b/tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php similarity index 100% rename from spec/Core/Usecase/Message/ReceiveMessageSpec.php rename to tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php diff --git a/spec/Core/Usecase/ReadUsecaseSpec.php b/tests/spec/Core/Usecase/ReadUsecaseSpec.php similarity index 100% rename from spec/Core/Usecase/ReadUsecaseSpec.php rename to tests/spec/Core/Usecase/ReadUsecaseSpec.php diff --git a/spec/Core/Usecase/SearchUsecaseSpec.php b/tests/spec/Core/Usecase/SearchUsecaseSpec.php similarity index 100% rename from spec/Core/Usecase/SearchUsecaseSpec.php rename to tests/spec/Core/Usecase/SearchUsecaseSpec.php diff --git a/spec/Core/Usecase/UpdateUsecaseSpec.php b/tests/spec/Core/Usecase/UpdateUsecaseSpec.php similarity index 100% rename from spec/Core/Usecase/UpdateUsecaseSpec.php rename to tests/spec/Core/Usecase/UpdateUsecaseSpec.php diff --git a/spec/Core/Usecase/User/LoginUserSpec.php b/tests/spec/Core/Usecase/User/LoginUserSpec.php similarity index 100% rename from spec/Core/Usecase/User/LoginUserSpec.php rename to tests/spec/Core/Usecase/User/LoginUserSpec.php diff --git a/spec/ruleset.xml b/tests/spec/ruleset.xml similarity index 100% rename from spec/ruleset.xml rename to tests/spec/ruleset.xml diff --git a/application/tests/classes/Core/Traits/DataTranformerTest.php b/tests/unit/Core/Traits/DataTranformerTest.php similarity index 92% rename from application/tests/classes/Core/Traits/DataTranformerTest.php rename to tests/unit/Core/Traits/DataTranformerTest.php index 34f144453b..e5a538206d 100644 --- a/application/tests/classes/Core/Traits/DataTranformerTest.php +++ b/tests/unit/Core/Traits/DataTranformerTest.php @@ -24,7 +24,11 @@ public function pTransform($data) { } } -class DataTransformerTest extends Unittest_TestCase { +/** + * @backupGlobals disabled + * @preserveGlobalState disabled + */ +class DataTransformerTest extends PHPUnit\Framework\TestCase { /** * Test get method diff --git a/application/tests/classes/Ushahidi/PostValueTest.php b/tests/unit/Ushahidi/PostValueTest.php similarity index 88% rename from application/tests/classes/Ushahidi/PostValueTest.php rename to tests/unit/Ushahidi/PostValueTest.php index 17bb552998..fb0304f91a 100644 --- a/application/tests/classes/Ushahidi/PostValueTest.php +++ b/tests/unit/Ushahidi/PostValueTest.php @@ -9,7 +9,11 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -class PostValueRepositoryTest extends Unittest_TestCase { +/** + * @backupGlobals disabled + * @preserveGlobalState disabled + */ +class PostValueRepositoryTest extends PHPUnit\Framework\TestCase { protected $repository; @@ -17,12 +21,12 @@ public function setUp() { parent::setUp(); - $this->repository = $this->getMockBuilder('Ushahidi_Repository_Post_Value') + $this->repository = $this->getMockBuilder(Ushahidi_Repository_Post_Value::class) ->setMethods(['selectOne', 'selectQuery', 'getTable']) ->disableOriginalConstructor() ->getMock(); - $this->postvalue = $this->getMock('Ushahidi\Core\Entity\Post_Value'); + $this->postvalue = $this->createMock(Ushahidi\Core\Entity\PostValue::class); } /** diff --git a/application/tests/classes/Util/BoundingBoxTest.php b/tests/unit/Util/BoundingBoxTest.php similarity index 91% rename from application/tests/classes/Util/BoundingBoxTest.php rename to tests/unit/Util/BoundingBoxTest.php index d3b9036df8..4382b64862 100644 --- a/application/tests/classes/Util/BoundingBoxTest.php +++ b/tests/unit/Util/BoundingBoxTest.php @@ -9,7 +9,11 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -class BoundingBoxTest extends Unittest_TestCase { +/** + * @backupGlobals disabled + * @preserveGlobalState disabled + */ +class BoundingBoxTest extends PHPUnit\Framework\TestCase { /** * Test Bounding Box to WKT @@ -20,11 +24,11 @@ public function test_toWKT() { $bb = new Util_BoundingBox(-180, -90, 180, 90); $this->assertEquals('POLYGON((-180 -90,180 -90,180 90,-180 90,-180 -90))', $bb->toWKT()); - + $bb = new Util_BoundingBox(-1, -1, 1, 1); $this->assertEquals('POLYGON((-1 -1,1 -1,1 1,-1 1,-1 -1))', $bb->toWKT()); } - + /** * Test Bounding Box to array * @@ -34,11 +38,11 @@ public function test_as_array() { $bb = new Util_BoundingBox(-180, -90, 180, 90); $this->assertEquals(array(-180, -90, 180, 90), $bb->as_array()); - + $bb = new Util_BoundingBox(-1, -1, 1, 1); $this->assertEquals(array(-1, -1, 1, 1), $bb->as_array()); } - + /** * Test Bounding Box to geometry * @@ -49,9 +53,9 @@ public function test_toGeometry() $bb = new Util_BoundingBox(-180, -90, 180, 90); $geom = $bb->toGeometry(); $this->assertEquals('POLYGON((-180 -90,180 -90,180 90,-180 90,-180 -90))', $geom->toWKT()); - + $bb = new Util_BoundingBox(-1, -1, 1, 1); $geom = $bb->toGeometry(); $this->assertEquals('POLYGON((-1 -1,1 -1,1 1,-1 1,-1 -1))', $geom->toWKT()); } -} \ No newline at end of file +} diff --git a/application/tests/classes/Util/TileTest.php b/tests/unit/Util/TileTest.php similarity index 95% rename from application/tests/classes/Util/TileTest.php rename to tests/unit/Util/TileTest.php index 24290676d9..db1b32e731 100644 --- a/application/tests/classes/Util/TileTest.php +++ b/tests/unit/Util/TileTest.php @@ -9,7 +9,11 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -class TileTest extends Unittest_TestCase { +/** + * @backupGlobals disabled + * @preserveGlobalState disabled + */ +class TileTest extends PHPUnit\Framework\TestCase { /** * Test numTiles @@ -23,7 +27,7 @@ public function test_numTiles() $this->assertEquals(4, Util_Tile::numTiles(2)); $this->assertEquals(256, Util_Tile::numTiles(8)); } - + /** * Test tileToBoundingBox * @@ -36,26 +40,26 @@ public function test_tileToBoundingBox() $this->assertAttributeEquals(-85.051100, 'south', $bb, '', 0.0002); $this->assertAttributeEquals(-180, 'west', $bb, '', 0.0002); $this->assertAttributeEquals(180, 'east', $bb, '', 0.0002); - + $bb = Util_Tile::tileToBoundingBox(1, 1, 1); $this->assertAttributeEquals(0, 'north', $bb, '', 0.0002); $this->assertAttributeEquals(-85.051100, 'south', $bb, '', 0.0002); $this->assertAttributeEquals(0, 'west', $bb, '', 0.0002); $this->assertAttributeEquals(180, 'east', $bb, '', 0.0002); - + $bb = Util_Tile::tileToBoundingBox(2, 2, 1); $this->assertAttributeEquals(66.5131, 'north', $bb, '', 0.0002); $this->assertAttributeEquals(0, 'south', $bb, '', 0.0002); $this->assertAttributeEquals(0, 'west', $bb, '', 0.0002); $this->assertAttributeEquals(90, 'east', $bb, '', 0.0002); - + $bb = Util_Tile::tileToBoundingBox(8, 13, 14); $this->assertAttributeEquals(83.026183, 'north', $bb, '', 0.0002); $this->assertAttributeEquals(82.853346, 'south', $bb, '', 0.0002); $this->assertAttributeEquals(-161.718750, 'west', $bb, '', 0.0002); $this->assertAttributeEquals(-160.312500, 'east', $bb, '', 0.0002); } - + /** * Test tileToLon * @@ -68,7 +72,7 @@ public function test_tileToLon() $this->assertEquals(0, Util_Tile::tileToLon(2, 2), '', 0.0002); $this->assertEquals(-163.125000, Util_Tile::tileToLon(12, 8), '', 0.0002); } - + /** * Test tileToLat * @@ -81,4 +85,4 @@ public function test_tileToLat() $this->assertEquals(0, Util_Tile::tileToLat(2, 2), '', 0.0002); $this->assertEquals(83.026183, Util_Tile::tileToLat(14, 8), '', 0.0002); } -} \ No newline at end of file +} From 3ed68692c92c49adc1bd6c9201ae9a85178e1c02 Mon Sep 17 00:00:00 2001 From: David Losada Date: Mon, 22 May 2017 18:32:41 +0200 Subject: [PATCH 02/26] Fix io scheduled job errors (#1748) * handle error in twitter dataprovider connection * empty filters are reverted to the default, if provided (helps avoid invalid SQL such as "IN ()") --- plugins/twitter/classes/DataProvider/Twitter.php | 5 +++++ src/Core/Traits/FilterRecords.php | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/twitter/classes/DataProvider/Twitter.php b/plugins/twitter/classes/DataProvider/Twitter.php index 7278963f60..9f63c088c8 100644 --- a/plugins/twitter/classes/DataProvider/Twitter.php +++ b/plugins/twitter/classes/DataProvider/Twitter.php @@ -47,6 +47,11 @@ public function fetch($limit = FALSE) { } $connection = $this->_connect(); + if (is_int($connection) && $connection == 0) { + // The connection didn't succeed, but this is not fatal to the application flow + // Just return 0 messages fetched + return 0; + } $connection->setDecodeJsonAsArray(true); $count = 0; diff --git a/src/Core/Traits/FilterRecords.php b/src/Core/Traits/FilterRecords.php index 10ceb3b13f..ce0b72d0f9 100644 --- a/src/Core/Traits/FilterRecords.php +++ b/src/Core/Traits/FilterRecords.php @@ -99,6 +99,14 @@ public function getFilter($name, $default = null) if (!isset($this->filters[$name])) { return $default; } - return $this->filters[$name]; + + $filter = $this->filters[$name]; + + if (empty($filter) && !is_null($default)) { + // An empty filter reverts to the default + return $default; + } + + return $filter; } } From fd530e949f5b795d841d9243d1f7377956567b68 Mon Sep 17 00:00:00 2001 From: will Date: Wed, 24 May 2017 14:08:02 -0400 Subject: [PATCH 03/26] Enable clustering by default --- application/config/map.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/config/map.php b/application/config/map.php index aa04f40839..47b1a5f314 100644 --- a/application/config/map.php +++ b/application/config/map.php @@ -11,7 +11,7 @@ return array( // Enable marker clustering with leaflet.markercluster - 'clustering' => FALSE, + 'clustering' => TRUE, 'cluster_radius' => 50, // Map start location 'default_view' => array( From 2dc41a612438169f78a82dfd7c2c89eff2fc5db2 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 19 May 2017 16:38:34 +1200 Subject: [PATCH 04/26] Only add `tags` type attributes to the "post fields" not tasks. --- .../20170412191954_convert_form_tags_to_form_attribute.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/migrations/20170412191954_convert_form_tags_to_form_attribute.php b/migrations/20170412191954_convert_form_tags_to_form_attribute.php index 24f1fc91de..af0c62fa33 100644 --- a/migrations/20170412191954_convert_form_tags_to_form_attribute.php +++ b/migrations/20170412191954_convert_form_tags_to_form_attribute.php @@ -6,7 +6,7 @@ class ConvertFormTagsToFormAttribute extends AbstractMigration { - + /** * Migrate Up. */ @@ -15,7 +15,8 @@ public function up() $pdo = $this->getAdapter()->getConnection(); $rows = $this->fetchAll( "SELECT id - FROM form_stages" + FROM form_stages + WHERE `type` = 'post'" ); $tag_rows = $this->fetchAll( "SELECT id From cdf28106bcd86ad34bd1bdb16f79b040540a01bc Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 19 May 2017 17:17:49 +1200 Subject: [PATCH 05/26] Remove category fields from tasks --- .../20170519044934_remove_tags_from_tasks.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 migrations/20170519044934_remove_tags_from_tasks.php diff --git a/migrations/20170519044934_remove_tags_from_tasks.php b/migrations/20170519044934_remove_tags_from_tasks.php new file mode 100644 index 0000000000..7401578506 --- /dev/null +++ b/migrations/20170519044934_remove_tags_from_tasks.php @@ -0,0 +1,20 @@ +execute(" + DELETE FROM `form_attributes` WHERE + `input` = 'tags' AND + `form_stage_id` IN (SELECT `id` FROM `form_stages` WHERE `type` = 'task') + "); + } + + public function down() + { + // No op, not reversible + } +} From 510d213c8920a12fe9cdb60f9dcb454660caa136 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Mon, 22 May 2017 21:43:14 +1200 Subject: [PATCH 06/26] Turn posts_tags into a full post value table, and avoid duplicating info - Add extra field to posts_tags - Remove tags from post_varchar - Add Post/Tags validator - Add Post/Tags repo --- application/classes/Ushahidi/Core.php | 7 ++ .../classes/Ushahidi/Repository/Post/Tags.php | 60 ++++++++++ .../classes/Ushahidi/Validator/Post/Tags.php | 33 ++++++ ...54_convert_form_tags_to_form_attribute.php | 2 +- ...1_move_post_tag_values_to_post_varchar.php | 111 +++++++----------- ...22004400_remove_tags_from_post_varchar.php | 21 ++++ ...409_join_posts_tags_table_to_attribute.php | 86 ++++++++++++++ tests/datasets/ushahidi/Base.yml | 15 +++ 8 files changed, 267 insertions(+), 68 deletions(-) create mode 100644 application/classes/Ushahidi/Repository/Post/Tags.php create mode 100644 application/classes/Ushahidi/Validator/Post/Tags.php create mode 100644 migrations/20170522004400_remove_tags_from_post_varchar.php create mode 100644 migrations/20170522004409_join_posts_tags_table_to_attribute.php diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 9d609248c6..0c0b2c2b3b 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -465,6 +465,7 @@ public static function init() $di->set('repository.post.markdown', $di->lazyNew('Ushahidi_Repository_Post_Markdown')); $di->set('repository.post.title', $di->lazyNew('Ushahidi_Repository_Post_Title')); $di->set('repository.post.media', $di->lazyNew('Ushahidi_Repository_Post_Media')); + $di->set('repository.post.tags', $di->lazyNew('Ushahidi_Repository_Post_Tags')); // The post value repo factory $di->set('repository.post_value_factory', $di->lazyNew('Ushahidi_Repository_Post_ValueFactory')); @@ -483,6 +484,7 @@ public static function init() 'markdown' => $di->lazyGet('repository.post.markdown'), 'title' => $di->lazyGet('repository.post.title'), 'media' => $di->lazyGet('repository.post.media'), + 'tags' => $di->lazyGet('repository.post.tags'), ], ]; @@ -621,6 +623,10 @@ public static function init() $di->params['Ushahidi_Validator_Post_Media'] = [ 'media_repo' => $di->lazyGet('repository.media') ]; + $di->set('validator.post.tags', $di->lazyNew('Ushahidi_Validator_Post_Tags')); + $di->params['Ushahidi_Validator_Post_Tags'] = [ + 'media_repo' => $di->lazyGet('repository.tags') + ]; $di->set('validator.post.value_factory', $di->lazyNew('Ushahidi_Validator_Post_ValueFactory')); @@ -639,6 +645,7 @@ public static function init() 'title' => $di->lazyGet('validator.post.title'), 'media' => $di->lazyGet('validator.post.media'), 'video' => $di->lazyGet('validator.post.video'), + 'tags' => $di->lazyGet('validator.post.tags'), ], ]; diff --git a/application/classes/Ushahidi/Repository/Post/Tags.php b/application/classes/Ushahidi/Repository/Post/Tags.php new file mode 100644 index 0000000000..00738cc60a --- /dev/null +++ b/application/classes/Ushahidi/Repository/Post/Tags.php @@ -0,0 +1,60 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +class Ushahidi_Repository_Post_Tags extends Ushahidi_Repository_Post_Value +{ + // Ushahidi_Repository + protected function getTable() + { + return 'posts_tags'; + } + + // Override selectQuery to fetch attribute 'key' too + protected function selectQuery(Array $where = []) + { + $query = parent::selectQuery($where); + + // Select 'tag_id' as value too + $query->select( + ['posts_tags.tag_id', 'value'] + ); + + return $query; + } + + // PostValueRepository + public function getValueQuery($form_attribute_id, $match) + { + return $this->selectQuery(compact('form_attribute_id')) + ->where('tag_id', 'LIKE', "%$match%"); + } + + // UpdatePostValueRepository + public function createValue($value, $form_attribute_id, $post_id) + { + $tag_id = $value; + $input = compact('tag_id', 'form_attribute_id', 'post_id'); + $input['created'] = time(); + + return $this->executeInsert($input); + } + + // UpdatePostValueRepository + public function updateValue($id, $value) + { + $update = ['tag_id' => $value]; + if ($id && $update) + { + $this->executeUpdate(compact('id'), $update); + } + } + +} diff --git a/application/classes/Ushahidi/Validator/Post/Tags.php b/application/classes/Ushahidi/Validator/Post/Tags.php new file mode 100644 index 0000000000..45e3371d16 --- /dev/null +++ b/application/classes/Ushahidi/Validator/Post/Tags.php @@ -0,0 +1,33 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use Ushahidi\Core\Entity\TagsRepository; + +class Ushahidi_Validator_Post_Tags extends Ushahidi_Validator_Post_ValueValidator +{ + protected $media_repo; + + public function __construct(TagsRepository $tags_repo) + { + $this->repo = $tags_repo; + } + + protected function validate($value) + { + if (!Valid::digit($value)) { + return 'digit'; + } + + if (! $this->repo->exists($value)) { + return 'exists'; + } + } +} diff --git a/migrations/20170412191954_convert_form_tags_to_form_attribute.php b/migrations/20170412191954_convert_form_tags_to_form_attribute.php index af0c62fa33..76e0436091 100644 --- a/migrations/20170412191954_convert_form_tags_to_form_attribute.php +++ b/migrations/20170412191954_convert_form_tags_to_form_attribute.php @@ -54,6 +54,6 @@ public function up() */ public function down() { - $this->execute("DELETE from form_attributes where input = 'tags'"); + $this->execute("DELETE from form_attributes where type = 'varchar' AND input = 'tags'"); } } diff --git a/migrations/20170417090621_move_post_tag_values_to_post_varchar.php b/migrations/20170417090621_move_post_tag_values_to_post_varchar.php index fed076d255..1c807b1474 100644 --- a/migrations/20170417090621_move_post_tag_values_to_post_varchar.php +++ b/migrations/20170417090621_move_post_tag_values_to_post_varchar.php @@ -9,42 +9,47 @@ class MovePostTagValuesToPostVarchar extends AbstractMigration */ public function up() { - $pdo = $this->getAdapter()->getConnection(); - // fetching posts with form_attribute_id - $posts = $this->fetchAll( - "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id - FROM posts - INNER JOIN form_stages - ON form_stages.form_id = posts.form_id - INNER JOIN form_attributes - ON form_attributes.form_stage_id = form_stages.id" - ); - $insert = $pdo->prepare( - "INSERT into - post_varchar - (`post_id`, `form_attribute_id`, `value`, `created`) - VALUES(:post_id, :form_attribute_id, :value, :created)" - ); - foreach ($posts as $post) { - $post_tags = $pdo->prepare( - "SELECT tag_id - FROM posts_tags - WHERE post_id = :post_id" - ); - $post_tags->execute([':post_id' => $post['id']]); - // inserting post_ids and tag_ids(value) in post_varchar - $tags = $post_tags->fetchAll(); - foreach ($tags as $tag) { - $insert->execute( - [ - ':post_id' => $post['id'], - ':form_attribute_id' => $post['form_attribute_id'], - ':value' => $tag['tag_id'], - ':created' => time() - ] - ); - } - } + // Don't do this if we haven't already! + // We have a better way. + + //$pdo = $this->getAdapter()->getConnection(); + // fetching posts with form_attribute_id + // $posts = $this->fetchAll( + // "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id + // FROM posts + // INNER JOIN form_stages + // ON form_stages.form_id = posts.form_id + // INNER JOIN form_attributes + // ON form_attributes.form_stage_id = form_stages.id + // AND form_attributes.input = 'tags' + // AND form_attributes.type = 'varchar'" + // ); + // $insert = $pdo->prepare( + // "INSERT into + // post_varchar + // (`post_id`, `form_attribute_id`, `value`, `created`) + // VALUES(:post_id, :form_attribute_id, :value, :created)" + // ); + // foreach ($posts as $post) { + // $post_tags = $pdo->prepare( + // "SELECT tag_id + // FROM posts_tags + // WHERE post_id = :post_id" + // ); + // $post_tags->execute([':post_id' => $post['id']]); + // // inserting post_ids and tag_ids(value) in post_varchar + // $tags = $post_tags->fetchAll(); + // foreach ($tags as $tag) { + // $insert->execute( + // [ + // ':post_id' => $post['id'], + // ':form_attribute_id' => $post['form_attribute_id'], + // ':value' => $tag['tag_id'], + // ':created' => time() + // ] + // ); + // } + // } } /** @@ -52,38 +57,10 @@ public function up() */ public function down() { - $pdo = $this->getAdapter()->getConnection(); - $posts = $this->fetchAll( - "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id - FROM posts - INNER JOIN form_stages - ON form_stages.form_id = posts.form_id - INNER JOIN form_attributes - ON form_attributes.form_stage_id = form_stages.id" - ); - $delete = $pdo->prepare( + $this->execute( "DELETE from post_varchar - WHERE post_id = :post_id AND form_attribute_id = :form_attribute_id AND value = :value" + WHERE form_attribute_id IN + (SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')" ); - - foreach ($posts as $post) { - $post_tags = $pdo->prepare( - "SELECT tag_id - FROM posts_tags - WHERE post_id = :post_id" - ); - $post_tags->execute([':post_id' => $post['id']]); - // inserting post_ids and tag_ids(value) in post_varchar - $tags = $post_tags->fetchAll(); - foreach ($tags as $tag) { - $delete->execute( - [ - ':post_id' => $post['id'], - ':form_attribute_id' => $post['form_attribute_id'], - ':value' => $tag['tag_id'] - ] - ); - } - } } } diff --git a/migrations/20170522004400_remove_tags_from_post_varchar.php b/migrations/20170522004400_remove_tags_from_post_varchar.php new file mode 100644 index 0000000000..1c2d8b1719 --- /dev/null +++ b/migrations/20170522004400_remove_tags_from_post_varchar.php @@ -0,0 +1,21 @@ +execute( + "DELETE from post_varchar + WHERE form_attribute_id IN + (SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')" + ); + } + + public function down() + { + // No op - not reversible + } +} diff --git a/migrations/20170522004409_join_posts_tags_table_to_attribute.php b/migrations/20170522004409_join_posts_tags_table_to_attribute.php new file mode 100644 index 0000000000..6cf847aaa3 --- /dev/null +++ b/migrations/20170522004409_join_posts_tags_table_to_attribute.php @@ -0,0 +1,86 @@ +getAdapter()->getConnection(); + + $this->table('posts_tags') + ->addColumn('id', 'integer', ['null' => false]) + ->addColumn('form_attribute_id', 'integer') + ->addColumn('created', 'integer', ['default' => 0]) + ->update(); + + // Manually fix up keys + $this->execute('ALTER TABLE posts_tags + DROP PRIMARY KEY, + ADD PRIMARY KEY (id), + ADD INDEX (post_id), + MODIFY COLUMN id INT AUTO_INCREMENT, + ADD UNIQUE INDEX unique_post_tag_attribute_ids (post_id, tag_id, form_attribute_id)'); + + // Make varchar/tags attributes into tags/tags attributes + $this->execute(" + UPDATE form_attributes + SET type = 'tags' + WHERE type = 'varchar' AND input = 'tags' + "); + + $attributes = $this->fetchAll(" + SELECT form_attributes.id, form_stages.form_id + FROM form_attributes + JOIN form_stages ON (form_attributes.form_stage_id = form_stages.id) + WHERE + form_attributes.type = 'tags' AND + form_stages.type = 'post' + "); + + // Set form_attribute_id for posts_tags entries + $insert = $pdo->prepare(' + UPDATE posts_tags JOIN posts ON (posts_tags.post_id = posts.id) + SET form_attribute_id = :attr_id WHERE posts.form_id = :form_id + '); + foreach ($attributes as $attribute) { + $insert->execute([ + ':attr_id' => $attribute['id'], + ':form_id' => $attribute['form_id'] + ]); + } + + // Add foreign key for form_attribute_id + $this->table('posts_tags') + ->addForeignKey('form_attribute_id', 'form_attributes', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE', + ]) + ->update(); + } + + public function down() + { + // Make tags/tags attributes into varchar/tags attributes + $this->execute(" + UPDATE form_attributes + SET type = 'varchar' + WHERE type = 'tags' AND input = 'tags' + "); + + // Restore keys/indexs + $this->execute('ALTER TABLE posts_tags + DROP PRIMARY KEY, + ADD PRIMARY KEY (post_id, tag_id), + MODIFY COLUMN id INT, + DROP INDEX unique_post_tag_attribute_ids'); + + // Remove columns + $this->table('posts_tags') + ->dropForeignKey('form_attribute_id') + ->removeColumn('id') + ->removeColumn('form_attribute_id') + ->removeColumn('created') + ->update(); + } +} diff --git a/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml index e72e69a85f..0d2f5a4d3a 100644 --- a/tests/datasets/ushahidi/Base.yml +++ b/tests/datasets/ushahidi/Base.yml @@ -441,6 +441,18 @@ form_attributes: options: "" cardinality: 1 form_stage_id: 1 + - + id: 26 + label: "Categories" + key: "tags" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: "" + cardinality: 0 + form_stage_id: 1 posts: - id: 1 @@ -950,12 +962,15 @@ posts_tags: - post_id: 1 tag_id: 4 + form_attribute_id: 26 - post_id: 1 tag_id: 3 + form_attribute_id: 26 - post_id: 99 tag_id: 3 + form_attribute_id: 26 form_stages_posts: - form_stage_id: 1 From a35bb7c66ed3a30637253d59b7570ef9847bd980 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Tue, 23 May 2017 16:34:46 +1200 Subject: [PATCH 07/26] Handle legacy tags values and save into first tags attribute. This isn't 100% compatible, but we at least save tags *if* the form has a tags attribute --- .../classes/Ushahidi/Repository/Post.php | 95 +++++++++---------- tests/datasets/ushahidi/Base.yml | 45 ++++++++- tests/integration/acl.feature | 4 +- tests/integration/forms/attributes.feature | 8 +- tests/integration/posts.feature | 73 ++++++++++++++ 5 files changed, 171 insertions(+), 54 deletions(-) diff --git a/application/classes/Ushahidi/Repository/Post.php b/application/classes/Ushahidi/Repository/Post.php index adc2d4c5dd..c1c45bc4a6 100644 --- a/application/classes/Ushahidi/Repository/Post.php +++ b/application/classes/Ushahidi/Repository/Post.php @@ -132,7 +132,8 @@ public function getEntity(Array $data = null) { $data += [ 'values' => $this->getPostValues($data['id']), - 'tags' => $this->getTagsForPost($data['id']), + // Continued for legacy + 'tags' => $this->getTagsForPost($data['id'], $data['form_id']), 'sets' => $this->getSetsForPost($data['id']), 'completed_stages' => $this->getCompletedStagesForPost($data['id']), ]; @@ -417,6 +418,7 @@ protected function setSearchConditions(SearchData $search) } // Filter by tag + // @todo add filter by specific tag attribute? if (!empty($search->tags)) { if (isset($search->tags['any'])) @@ -802,10 +804,13 @@ private function getBoundingBoxSubquery(Util_BoundingBox $bounding_box) * @param int $id post id * @return array tag ids for post */ - private function getTagsForPost($id) + private function getTagsForPost($id, $form_id) { + list($attr_id, $attr_key) = $this->getFirstTagAttr($form_id); + $result = DB::select('tag_id')->from('posts_tags') ->where('post_id', '=', $id) + ->where('form_attribute_id', '=', $attr_id) ->execute($this->db); return $result->as_array(NULL, 'tag_id'); } @@ -875,16 +880,24 @@ public function create(Entity $entity) // Create the post $id = $this->executeInsert($this->removeNullValues($post)); + $values = $entity->values; + // Handle legacy post.tags attribute if ($entity->tags) { - // Update post-tags - $this->updatePostTags($id, $entity->tags); + // Find first tag attribute + list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); + + // If we don't have tags in the values, use the post.tags value + if ($attr_key && !isset($values[$attr_key])) { + $tags = $this->parseTags($entity->tags); + $values[$attr_key] = $tags; + } } if ($entity->values) { // Update post-values - $this->updatePostValues($id, $entity->values); + $this->updatePostValues($id, $values); } if ($entity->completed_stages) @@ -917,16 +930,24 @@ public function update(Entity $entity) $count = $this->executeUpdate(['id' => $entity->id], $post); + $values = $entity->values; + // Handle legacy post.tags attribute if ($entity->hasChanged('tags')) { - // Update post-tags - $this->updatePostTags($entity->id, $entity->tags); + // Find first tag attribute + list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); + + // If we don't have tags in the values, use the post.tags value + if ($attr_key && !isset($values[$attr_key])) { + $tags = $this->parseTags($entity->tags); + $values[$attr_key] = $tags; + } } if ($entity->hasChanged('values')) { // Update post-values - $this->updatePostValues($entity->id, $entity->values); + $this->updatePostValues($entity->id, $values); } if ($entity->hasChanged('completed_stages')) @@ -958,25 +979,10 @@ protected function updatePostValues($post_id, $attributes) } } - protected function updatePostTags($post_id, $tags) + protected function parseTags($tags) { - // deletes all tags if $tags is empty - if (empty($tags)) - { - DB::delete('posts_tags') - ->where('post_id', '=', $post_id) - ->execute($this->db); - } - else - { - // Load existing tags - $existing = $this->getTagsForPost($post_id); - - $insert = DB::insert('posts_tags', ['post_id', 'tag_id']); - - $tag_ids = []; - $new_tags = FALSE; - + $tag_ids = []; + if (!empty($tags)) { foreach ($tags as $tag) { if (is_array($tag)) { @@ -991,32 +997,25 @@ protected function updatePostTags($post_id, $tags) $tag_entity = $this->tag_repo->get($tag); } - // Does the post already have this tag? - if (! in_array($tag_entity->id, $existing)) - { - // Add to insert query - $insert->values([$post_id, $tag_entity->id]); - $new_tags = TRUE; - } - $tag_ids[] = $tag_entity->id; } + } - // Save - if ($new_tags) - { - $insert->execute($this->db); - } + return $tag_ids; + } - // Remove any other tags - if (! empty($tag_ids)) - { - DB::delete('posts_tags') - ->where('tag_id', 'NOT IN', $tag_ids) - ->and_where('post_id', '=', $post_id) - ->execute($this->db); - } - } + public function getFirstTagAttr($form_id) + { + $result = DB::select('form_attributes.id', 'form_attributes.key') + ->from('form_attributes') + ->join('form_stages', 'INNER')->on('form_stages.id', '=', 'form_attributes.form_stage_id') + ->where('form_stages.form_id', '=', $form_id) + ->where('form_attributes.type', '=', 'tags') + ->order_by('form_attributes.priority', 'ASC') + ->limit(1) + ->execute($this->db); + + return [$result->get('id'), $result->get('key')]; } diff --git a/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml index 0d2f5a4d3a..6e0a090fc8 100644 --- a/tests/datasets/ushahidi/Base.yml +++ b/tests/datasets/ushahidi/Base.yml @@ -110,36 +110,43 @@ form_stages: form_id: 1 label: "Main" show_when_published: 1 + type: "post" - id: 2 form_id: 1 label: "2nd step" show_when_published: 1 + type: "task" - id: 3 form_id: 1 label: "3rd step" show_when_published: 1 + type: "task" - id: 4 form_id: 2 label: "Main" show_when_published: 1 + type: "post" - id: 5 form_id: 3 label: "Post" show_when_published: 1 + type: "post" - id: 6 form_id: 4 label: "restricted" show_when_published: 0 + type: "task" - id: 7 form_id: 4 label: "Post" show_when_published: 1 + type: "post" form_attributes: - id: 1 @@ -444,7 +451,7 @@ form_attributes: - id: 26 label: "Categories" - key: "tags" + key: "tags1" type: "tags" input: "tags" response_private: 0 @@ -453,6 +460,42 @@ form_attributes: options: "" cardinality: 0 form_stage_id: 1 + - + id: 27 + label: "Categories" + key: "tags2" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: "" + cardinality: 0 + form_stage_id: 4 + - + id: 28 + label: "Categories" + key: "tags3" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: "" + cardinality: 0 + form_stage_id: 5 + - + id: 29 + label: "Categories" + key: "tags4" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: "" + cardinality: 0 + form_stage_id: 7 posts: - id: 1 diff --git a/tests/integration/acl.feature b/tests/integration/acl.feature index 24cdb97dbe..3717044930 100644 --- a/tests/integration/acl.feature +++ b/tests/integration/acl.feature @@ -168,7 +168,7 @@ Feature: API Access Control Layer Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "7" + And the "count" property equals "8" Then the guzzle status code should be 200 Scenario: Listing All Attributes for a form with hidden stages with edit permission @@ -178,7 +178,7 @@ Feature: API Access Control Layer Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "7" + And the "count" property equals "8" Then the guzzle status code should be 200 Scenario: User can see hidden tasks of posts published when survey restricted to their role diff --git a/tests/integration/forms/attributes.feature b/tests/integration/forms/attributes.feature index a1ed03473c..b9d656875c 100644 --- a/tests/integration/forms/attributes.feature +++ b/tests/integration/forms/attributes.feature @@ -169,22 +169,24 @@ Feature: Testing the Form Attributes API And the response has a "errors" property Then the guzzle status code should be 404 + @resetFixture Scenario: Listing All Attributes for a form Given that I want to get all "Attributes" When I request "/forms/1/attributes" Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "19" + And the "count" property equals "18" Then the guzzle status code should be 200 - Scenario: Listing All Attributes + @resetFixture + Scenario: Listing All Attributes Given that I want to get all "Attributes" When I request "/forms/attributes" Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "27" + And the "count" property equals "29" Then the guzzle status code should be 200 Scenario: Search for point attributes diff --git a/tests/integration/posts.feature b/tests/integration/posts.feature index 8229bd876b..eaa1149173 100644 --- a/tests/integration/posts.feature +++ b/tests/integration/posts.feature @@ -512,6 +512,79 @@ Feature: Testing the Posts API And the "values.last_location_point.0.lon" property equals "-85.39" Then the guzzle status code should be 200 + @update + Scenario: Updating a post and remove some values + Given that I want to update a "Post" + And that the request "data" is: + """ + { + "form":1, + "title":"Update 1", + "type":"report", + "status":"published", + "locale":"en_US", + "values": + { + "full_name":["David Kobia"], + "description":["Skinny, homeless Kenyan last seen in the vicinity of the greyhound station"], + "date_of_birth":[], + "missing_date":["2012/09/25"], + "last_location":["atlanta"], + "last_location_point":[ + { + "lat": 33.755, + "lon": -85.39 + } + ], + "missing_status":["believed_missing"], + "links":[ + "abc123", + "def456" + ] + } + } + """ + And that its "id" is "1" + When I request "/posts" + Then the response is JSON + And the response has a "id" property + # Update 2 + Given that I want to update a "Post" + And that the request "data" is: + """ + { + "form":1, + "title":"Update 2", + "type":"report", + "status":"published", + "locale":"en_US", + "values": + { + "full_name":["David Kobia"], + "description":["Skinny, homeless Kenyan last seen in the vicinity of the greyhound station"], + "date_of_birth":[], + "missing_date":["2012/09/25"], + "last_location":["atlanta"], + "last_location_point":[ + { + "lat": 33.755, + "lon": -85.39 + } + ], + "missing_status":["believed_missing"], + "links":[ + "def456" + ] + } + } + """ + And that its "id" is "1" + When I request "/posts" + Then the response is JSON + And the response has a "id" property + And the "values.links" property count is "1" + Then the guzzle status code should be 200 + @update Scenario: Updating a Post to update tags Given that I want to update a "Post" From 511e31f73020c5ffc9ddb18f5bc7fd8e92069d7c Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 19 May 2017 17:28:15 +1200 Subject: [PATCH 08/26] Don't allow making tags attributes private --- .../Validator/Form/Attribute/Update.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php index 2cae01966c..b5bc82c750 100644 --- a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php +++ b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php @@ -29,6 +29,8 @@ public function __construct(FormAttributeRepository $repo, FormStageRepository $ protected function getRules() { + $type = $this->validation_engine->getFullData('type'); + return [ 'key' => [ ['max_length', [':value', 150]], @@ -76,7 +78,7 @@ protected function getRules() ]]], ], 'required' => [ - ['in_array', [':value', [true,false]]], + ['in_array', [':value', [true, false]]], ], 'priority' => [ ['digit'], @@ -92,10 +94,13 @@ protected function getRules() 'form_id' => [ ['digit'], ], + 'response_private' => [ + [[$this, 'canMakePrivate'], [':value', $type]] + ] ]; } - public function formStageBelongsToForm($value) + public function formStageBelongsToForm($value) { // don't check against nonexistant data if (!$value || !isset($this->valid['form_id'])) { @@ -105,4 +110,14 @@ public function formStageBelongsToForm($value) $group = $this->form_stage_repo->get($value); return ($group->form_id == $this->valid['form_id']); } + + public function canMakePrivate($value, $type) + { + // If input type is tags, then attribute cannot be private + if ($type === 'tags' && $value !== false) { + return false; + } + + return true; + } } From 2c5e3aff5b63a37052b2d29f47043021fc4bc700 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Wed, 24 May 2017 14:59:47 +1200 Subject: [PATCH 09/26] Make forms tests work in isolation --- tests/integration/forms.feature | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/integration/forms.feature b/tests/integration/forms.feature index dee814ba00..a25379d9c2 100644 --- a/tests/integration/forms.feature +++ b/tests/integration/forms.feature @@ -142,6 +142,15 @@ Feature: Testing the Forms API Then the guzzle status code should be 200 Scenario: Finding a Form after roles have been set. + Given that I want to update a "FormRole" + And that the request "data" is: + """ + { + "roles": [1,2] + } + """ + When I request "/forms/1/roles" + Then the response is JSON Given that I want to find a "Form" And that its "id" is "1" When I request "/forms" From 38ea41a972f956d6a489c312ef6b922f0e639b57 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Wed, 24 May 2017 15:07:44 +1200 Subject: [PATCH 10/26] Stop limiting tags by form, just limit tags per attribute - Stop using forms_tags table - Just use form_attribute.options instead --- .../classes/Ushahidi/FormsTagsTrait.php | 131 +++++------------- .../classes/Ushahidi/Repository/Form.php | 23 +-- .../classes/Ushahidi/Repository/Tag.php | 107 +++++++------- .../20170328080656_add_forms_tags_table.php | 14 -- .../20170525003110_drop_forms_tags_table.php | 51 +++++++ src/Core/Entity/Form.php | 2 +- src/Core/Entity/Tag.php | 4 +- tests/datasets/ushahidi/Base.yml | 8 +- 8 files changed, 148 insertions(+), 192 deletions(-) create mode 100644 migrations/20170525003110_drop_forms_tags_table.php diff --git a/application/classes/Ushahidi/FormsTagsTrait.php b/application/classes/Ushahidi/FormsTagsTrait.php index 20fdbc5272..3cdefb513b 100644 --- a/application/classes/Ushahidi/FormsTagsTrait.php +++ b/application/classes/Ushahidi/FormsTagsTrait.php @@ -1,6 +1,6 @@ @@ -11,111 +11,52 @@ trait Ushahidi_FormsTagsTrait { - //returning forms for a specific Tag-id - private function getFormsForTag($id) - { - $result = DB::select('form_id') - ->from('forms_tags') - ->where('tag_id', '=', $id) - ->execute($this->db); - return $result->as_array(NULL, 'form_id'); - } //returning tags for a specific Form-id private function getTagsForForm($id) { - $result = DB::select('tag_id') - ->from('forms_tags') + $attributes = DB::select('form_attributes.options') + ->from('form_attributes') + ->join('form_stages')->on('form_stage_id', '=', 'form_stages.id') + ->join('forms')->on('form_id', '=', 'forms.id') ->where('form_id', '=', $id) - ->execute($this->db); - return $result->as_array(NULL, 'tag_id'); - } - - // updating/adding tags to a form - private function updateFormsTags($form_id, $tags) - { - if (!$tags) { - DB::delete('forms_tags') - ->where('form_id', '=', $form_id) - ->execute($this->db); - } else if ($tags) { - $existing = $this->getTagsForForm($form_id); - $insert = DB::insert('forms_tags', ['form_id', 'tag_id']); - $tag_ids = []; - $new_tags = FALSE; - foreach ($tags as $tag) { - if (!in_array($tag, $existing)) { - $insert->values([$form_id, $tag]); - $new_tags = TRUE; - } - $tag_ids[] = $tag; - } - if ($new_tags) { - $insert->execute($this->db); - } - if (!empty($tag_ids)) { - DB::delete('forms_tags') - ->where('tag_id', 'NOT IN', $tag_ids) - ->and_where('form_id', '=', $form_id) - ->execute($this->db); - } - } - } + ->where('form_attributes.type', '=', 'tags') + ->execute($this->db) + ->as_array(); - //updating/adding forms to a tag - private function updateTagForms($tag_id, $forms) - { - if (empty($forms)) { - DB::delete('forms_tags') - ->where('tag_id', '=', $tag_id) - ->execute($this->db); - } else { - $existing = $this->getFormsForTag($tag_id); - $insert = DB::insert('forms_tags', ['form_id', 'tag_id']); - $form_ids = []; - $new_forms = FALSE; - foreach ($forms as $form) { - if (isset($form['id'])) { - $id = $form['id']; - } else { - $id = $form; - } - if (!in_array($form, $existing)) { - $insert->values([$id, $tag_id]); - $new_forms = TRUE; - } - $form_ids[] = $id; - } - - if ($new_forms) { - $insert->execute($this->db); - } - - if (!empty($form_ids)) { - DB::delete('forms_tags') - ->where('form_id', 'NOT IN', $form_ids) - ->and_where('tag_id', '=', $tag_id) - ->execute($this->db); + $tags = []; + // Combine all tag ids into 1 array + foreach ($attributes as $attr) { + $options = json_decode($attr['options'], TRUE); + if (is_array($options)) { + $tags = array_merge($tags, $options); } } + + return $tags; } - private function updateFormAttributes($id) + private function removeTagFromAttributeOptions($id) { + // Grab all tags attributes $attr = DB::select('id', 'options') - ->from('form_attributes') - ->where('input', '=', 'tags') - ->execute($this->db) - ->as_array('id', 'options'); - foreach ($attr as $attr_id => $value) { - $value = json_decode($value); - if (in_array($id, $value)) { - $index = array_search($id, $value); - array_splice($value, $index, 1); - $value = json_encode($value); + ->from('form_attributes') + ->where('type', '=', 'tags') + ->execute($this->db) + ->as_array('id', 'options'); + + foreach ($attr as $attr_id => $options) { + $options = json_decode($options, TRUE); + if (is_array($options) && in_array($id, $options)) { + // Remove $id from options array + $index = array_search($id, $options); + array_splice($options, $index, 1); + $options = json_encode($options); + + // Save it DB::update('form_attributes') - ->set(array('options' => $value)) - ->where('id', '=', $attr_id) - ->execute($this->db); + ->set(array('options' => $options)) + ->where('id', '=', $attr_id) + ->execute($this->db); } } } diff --git a/application/classes/Ushahidi/Repository/Form.php b/application/classes/Ushahidi/Repository/Form.php index c511bc4e5c..2f9ad7be48 100644 --- a/application/classes/Ushahidi/Repository/Form.php +++ b/application/classes/Ushahidi/Repository/Form.php @@ -38,10 +38,10 @@ public function getEntity(Array $data = null) if (isset($data["id"])) { $can_create = $this->getRolesThatCanCreatePosts($data['id']); $data = $data + [ - 'can_create' => $can_create['roles'], + 'can_create' => $can_create['roles'], + 'tags' => $this->getTagsForForm($data['id']) ]; - $data['tags'] = $this->getTagsForForm($data['id']); - } + } return new Form($data); } @@ -68,14 +68,7 @@ protected function setSearchConditions(SearchData $search) // CreateRepository public function create(Entity $entity) { - - $tags = $entity->tags; - unset($entity->tags); $id = parent::create($entity->setState(['created' => time()])); - //updating forms_tags-table - if ($tags && $id !== null) { - $this->updateFormsTags($id, $tags); - } // todo ensure default group is created return $id; } @@ -83,7 +76,6 @@ public function create(Entity $entity) // UpdateRepository public function update(Entity $entity) { - // If orignal Form update Intercom if Name changed if ($entity->id === 1) { foreach ($entity->getChanged() as $key => $val) { @@ -92,14 +84,11 @@ public function update(Entity $entity) } } - $tags = $entity->tags; - unset($entity->tags); + // Remove children before saving unset($entity->children); + + // Finally save the form $id = parent::update($entity->setState(['updated' => time()])); - // updating forms_tags-table - if ($tags && $entity->id !== null) { - $this->updateFormsTags($entity->id, $tags); - } return $id; } diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 76421eb19e..6f0fd02c94 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -42,18 +42,17 @@ public function getEntity(Array $data = null) { if (!empty($data['id'])) { - $data['forms'] = $this->getFormsForTag($data['id']); - - if(empty($data['parent_id'])) { - - $data['children'] = - DB::select('id') - ->from('tags') - ->where('parent_id','=',$data['id']) - ->execute($this->db) - ->as_array(); - } - } + // If this is a top level category + if(empty($data['parent_id'])) { + // Load children + $data['children'] = DB::select('id') + ->from('tags') + ->where('parent_id','=',$data['id']) + ->execute($this->db) + ->as_array(); + } + } + return new Tag($data); } @@ -70,31 +69,31 @@ public function getSearchFields() } // Ushahidi_Repository - protected function setSearchConditions(SearchData $search) - { - $query = $this->search_query; - foreach (['tag', 'type', 'parent_id'] as $key) - { - if ($search->$key) { - $query->where($key, '=', $search->$key); - } - } - if ($search->q) { - // Tag text searching - $query->where('tag', 'LIKE', "%{$search->q}%"); - } - if($search->level) { - //searching for top-level-tags - if($search->level === 'parent') { - $query->where('parent_id', '=', null); - } - } - if($search->formId){ - $query->join('forms_tags') - ->on('tags.id', '=', 'forms_tags.tag_id') - ->where('form_id','=', $search->formId); - } - } + protected function setSearchConditions(SearchData $search) + { + $query = $this->search_query; + foreach (['tag', 'type', 'parent_id'] as $key) + { + if ($search->$key) { + $query->where($key, '=', $search->$key); + } + } + if ($search->q) { + // Tag text searching + $query->where('tag', 'LIKE', "%{$search->q}%"); + } + if($search->level) { + //searching for top-level-tags + if($search->level === 'parent') { + $query->where('parent_id', '=', null); + } + } + if($search->formId){ + $query->join('forms_tags') + ->on('tags.id', '=', 'forms_tags.tag_id') + ->where('form_id','=', $search->formId); + } + } // SearchRepository public function getSearchResults() @@ -110,29 +109,16 @@ public function create(Entity $entity) $record = $entity->asArray(); $record['created'] = time(); - unset($record['forms']); - $id = $this->executeInsert($this->removeNullValues($record)); - if($entity->forms) { - //updating forms_tags-table - $this->updateTagForms($id, $entity->forms); - } - return $id; } public function update(Entity $entity) { $tag = $entity->getChanged(); - unset($tag['forms']); $count = $this->executeUpdate(['id' => $entity->id], $tag); - // updating forms_tags-table - if($entity->hasChanged('forms')) - { - $this->updateTagForms($entity->id, $entity->forms); - } return $count; } @@ -162,18 +148,23 @@ public function isSlugAvailable($slug) { return $this->selectCount(compact('slug')) === 0; } - public function delete(Entity $entity) - { - $this->updateFormAttributes($entity->id); - return $this->executeDelete([ - 'id' => $entity->id - ]); - } + + public function delete(Entity $entity) + { + // Remove tag from attribute options + $this->removeTagFromAttributeOptions($entity->id); + + return $this->executeDelete([ + 'id' => $entity->id + ]); + } // DeleteTagRepository public function deleteTag($id) { - $this->updateFormAttributes($entity->id); + // Remove tag from attribute options + $this->removeTagFromAttributeOptions($entity->id); + return $this->delete(compact('id')); } } diff --git a/migrations/20170328080656_add_forms_tags_table.php b/migrations/20170328080656_add_forms_tags_table.php index f84d8762ee..dabffc554e 100644 --- a/migrations/20170328080656_add_forms_tags_table.php +++ b/migrations/20170328080656_add_forms_tags_table.php @@ -30,18 +30,4 @@ public function change() ]) ->create(); } - - /** - * Migrate Up. - */ - public function up() - { - } - - /** - * Migrate Down. - */ - public function down() - { - } } diff --git a/migrations/20170525003110_drop_forms_tags_table.php b/migrations/20170525003110_drop_forms_tags_table.php new file mode 100644 index 0000000000..781ecba7da --- /dev/null +++ b/migrations/20170525003110_drop_forms_tags_table.php @@ -0,0 +1,51 @@ +dropTable('forms_tags'); + } + + public function down() + { + $this->table('forms_tags', [ + 'id' => false, + 'primary_key' => ['form_id', 'tag_id'], + ]) + ->addColumn('form_id', 'integer') + ->addForeignKey('form_id', 'forms', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE' + ]) + ->addColumn('tag_id', 'integer') + ->addForeignKey('tag_id', 'tags', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE' + ]) + ->create(); + } +} diff --git a/src/Core/Entity/Form.php b/src/Core/Entity/Form.php index d623457fd2..b1840dca0b 100644 --- a/src/Core/Entity/Form.php +++ b/src/Core/Entity/Form.php @@ -28,7 +28,7 @@ class Form extends StaticEntity protected $require_approval; protected $everyone_can_create; protected $can_create; - public $tags; + protected $tags; // DataTransformer protected function getDefinition() diff --git a/src/Core/Entity/Tag.php b/src/Core/Entity/Tag.php index 50fc758853..3fe63bc533 100644 --- a/src/Core/Entity/Tag.php +++ b/src/Core/Entity/Tag.php @@ -26,7 +26,6 @@ class Tag extends StaticEntity protected $priority; protected $created; protected $role; - protected $forms; protected $children; // StatefulData @@ -57,8 +56,7 @@ protected function getDefinition() 'priority' => 'int', 'created' => 'int', 'role' => '*json', - 'forms' => 'array', - 'children' =>'array', + 'children' => 'array', ]; } diff --git a/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml index 6e0a090fc8..5edd3f86cf 100644 --- a/tests/datasets/ushahidi/Base.yml +++ b/tests/datasets/ushahidi/Base.yml @@ -457,7 +457,7 @@ form_attributes: response_private: 0 required: 0 priority: 3 - options: "" + options: '["1","2","3","4","5","6","7"]' cardinality: 0 form_stage_id: 1 - @@ -469,7 +469,7 @@ form_attributes: response_private: 0 required: 0 priority: 3 - options: "" + options: '["1","2","3","5"]' cardinality: 0 form_stage_id: 4 - @@ -481,7 +481,7 @@ form_attributes: response_private: 0 required: 0 priority: 3 - options: "" + options: '["1","2","3","5","6","7"]' cardinality: 0 form_stage_id: 5 - @@ -493,7 +493,7 @@ form_attributes: response_private: 0 required: 0 priority: 3 - options: "" + options: '["1","2","3","4","5","6","7"]' cardinality: 0 form_stage_id: 7 posts: From 138e5ccd51a5f7a067d976069a1454ba5e6ed91b Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 11:26:30 +1200 Subject: [PATCH 11/26] Rename tags to categories in error messages --- application/messages/post.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/messages/post.php b/application/messages/post.php index 88428126b5..dffd2b1d3c 100644 --- a/application/messages/post.php +++ b/application/messages/post.php @@ -2,7 +2,7 @@ return [ 'publishedPostsLimitReached' => 'limit::posts', - 'tagDoesNotExist' => 'tag :value does not exist', + 'tagDoesNotExist' => 'category :value does not exist', 'attributeDoesNotExist' => 'attribute ":param1" does not exist', 'tooManyValues' => 'Too many values for :param1 (max: :param2)', 'valueDoesNotExist' => 'value id :param2 for field :param1 does not exist', From 77046c6c02297eb9ac278c01c031ec3ca8f51bba Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 14:56:29 +1200 Subject: [PATCH 12/26] Format form tags and tag children as relations, remove tag forms formatter --- application/classes/Ushahidi/Formatter/API.php | 2 +- application/classes/Ushahidi/Formatter/Form.php | 11 +++++++++++ application/classes/Ushahidi/Formatter/Tag.php | 14 +++++++++----- application/classes/Ushahidi/Repository/Tag.php | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/application/classes/Ushahidi/Formatter/API.php b/application/classes/Ushahidi/Formatter/API.php index 693143ee82..ca99c823a5 100644 --- a/application/classes/Ushahidi/Formatter/API.php +++ b/application/classes/Ushahidi/Formatter/API.php @@ -107,7 +107,7 @@ protected function format_updated($value) protected function get_relation($resource, $id) { return !$id ? NULL : [ - 'id' => $id, + 'id' => intval($id), 'url' => URL::site(Ushahidi_Rest::url($resource, $id), Request::current()), ]; } diff --git a/application/classes/Ushahidi/Formatter/Form.php b/application/classes/Ushahidi/Formatter/Form.php index dc9d0e8866..893b7c8a01 100644 --- a/application/classes/Ushahidi/Formatter/Form.php +++ b/application/classes/Ushahidi/Formatter/Form.php @@ -26,4 +26,15 @@ protected function format_color($value) $value = ltrim($value, '#'); return $value ? '#' . $value : null; } + + protected function format_tags($tags) + { + $output = []; + foreach ($tags as $tagid) + { + $output[] = $this->get_relation('tags', $tagid); + } + + return $output; + } } diff --git a/application/classes/Ushahidi/Formatter/Tag.php b/application/classes/Ushahidi/Formatter/Tag.php index d603131ed8..e756272763 100644 --- a/application/classes/Ushahidi/Formatter/Tag.php +++ b/application/classes/Ushahidi/Formatter/Tag.php @@ -22,14 +22,18 @@ protected function format_color($value) return $value ? '#' . $value : null; } - protected function format_forms($forms) + protected function format_children($tags) { $output = []; - foreach ($forms as $formid) - { - $output[] = $this->get_relation('forms', $formid); + + if (is_array($tags)) { + foreach ($tags as $tagid) + { + $output[] = $this->get_relation('tags', $tagid); + //$output[] = intval($tagid); + } } - + return $output; } } diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 6f0fd02c94..43cfbeed5c 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -49,7 +49,7 @@ public function getEntity(Array $data = null) ->from('tags') ->where('parent_id','=',$data['id']) ->execute($this->db) - ->as_array(); + ->as_array(null, 'id'); } } From 097429aeba1be1f792a8cae455f51df77f8c19bc Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 16:11:46 +1200 Subject: [PATCH 13/26] Remove tags?formId filter from Tag repo We've removed the relevant table, so lets remove the code too! --- application/classes/Ushahidi/Repository/Tag.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 43cfbeed5c..2b0c4d8178 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -65,7 +65,7 @@ protected function getJsonProperties() // SearchRepository public function getSearchFields() { - return ['tag', 'type', 'parent_id', 'q', 'level', 'formId' /* LIKE tag */]; + return ['tag', 'type', 'parent_id', 'q', 'level' /* LIKE tag */]; } // Ushahidi_Repository @@ -78,21 +78,18 @@ protected function setSearchConditions(SearchData $search) $query->where($key, '=', $search->$key); } } + if ($search->q) { // Tag text searching $query->where('tag', 'LIKE', "%{$search->q}%"); } + if($search->level) { //searching for top-level-tags if($search->level === 'parent') { $query->where('parent_id', '=', null); } } - if($search->formId){ - $query->join('forms_tags') - ->on('tags.id', '=', 'forms_tags.tag_id') - ->where('form_id','=', $search->formId); - } } // SearchRepository From 91f8216d7f0d5e61c21dfdd246a323147da18c5f Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 16:31:55 +1200 Subject: [PATCH 14/26] Fix validating tags when saving a post Typo when injecting tags_repo was breaking it --- application/classes/Ushahidi/Core.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 0c0b2c2b3b..e1138ba7be 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -625,7 +625,7 @@ public static function init() ]; $di->set('validator.post.tags', $di->lazyNew('Ushahidi_Validator_Post_Tags')); $di->params['Ushahidi_Validator_Post_Tags'] = [ - 'media_repo' => $di->lazyGet('repository.tags') + 'tags_repo' => $di->lazyGet('repository.tags') ]; From 0bd22ff4b2f013d17a7bd9b849ded7935822f334 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 16:40:01 +1200 Subject: [PATCH 15/26] Fix validating tags when saving a post Typo when injecting tags_repo was breaking it --- application/classes/Ushahidi/Core.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index e1138ba7be..324df9e837 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -625,7 +625,7 @@ public static function init() ]; $di->set('validator.post.tags', $di->lazyNew('Ushahidi_Validator_Post_Tags')); $di->params['Ushahidi_Validator_Post_Tags'] = [ - 'tags_repo' => $di->lazyGet('repository.tags') + 'tags_repo' => $di->lazyGet('repository.tag') ]; From 7546890f3f1fdd24a4f54418bbbb6a01e1c8ff8a Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Thu, 25 May 2017 16:52:22 +1200 Subject: [PATCH 16/26] Add TagRepository interface to use in Post/Tags Validator - Use tag field to set tags in test - Add TagRepository Interface - Implement interface in Tag Repo --- .../classes/Ushahidi/Repository/Tag.php | 4 +++- .../classes/Ushahidi/Validator/Post/Tags.php | 4 ++-- src/Core/Entity/TagRepository.php | 21 +++++++++++++++++++ tests/integration/posts.feature | 4 ++-- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 src/Core/Entity/TagRepository.php diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 2b0c4d8178..a0494c3f6a 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -12,6 +12,7 @@ use Ushahidi\Core\Entity; use Ushahidi\Core\SearchData; use Ushahidi\Core\Entity\Tag; +use Ushahidi\Core\Entity\TagRepository; use Ushahidi\Core\Usecase\Tag\UpdateTagRepository; use Ushahidi\Core\Usecase\Tag\DeleteTagRepository; use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; @@ -19,7 +20,8 @@ class Ushahidi_Repository_Tag extends Ushahidi_Repository implements UpdateTagRepository, DeleteTagRepository, - UpdatePostTagRepository + UpdatePostTagRepository, + TagRepository { // Use the JSON transcoder to encode properties use Ushahidi_JsonTranscodeRepository; diff --git a/application/classes/Ushahidi/Validator/Post/Tags.php b/application/classes/Ushahidi/Validator/Post/Tags.php index 45e3371d16..47bfdb0e15 100644 --- a/application/classes/Ushahidi/Validator/Post/Tags.php +++ b/application/classes/Ushahidi/Validator/Post/Tags.php @@ -9,13 +9,13 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -use Ushahidi\Core\Entity\TagsRepository; +use Ushahidi\Core\Entity\TagRepository; class Ushahidi_Validator_Post_Tags extends Ushahidi_Validator_Post_ValueValidator { protected $media_repo; - public function __construct(TagsRepository $tags_repo) + public function __construct(TagRepository $tags_repo) { $this->repo = $tags_repo; } diff --git a/src/Core/Entity/TagRepository.php b/src/Core/Entity/TagRepository.php new file mode 100644 index 0000000000..d1e11434d5 --- /dev/null +++ b/src/Core/Entity/TagRepository.php @@ -0,0 +1,21 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +namespace Ushahidi\Core\Entity; + +use Ushahidi\Core\Entity\Repository\EntityGet; +use Ushahidi\Core\Entity\Repository\EntityExists; + +interface TagRepository extends + EntityGet, + EntityExists +{ +} diff --git a/tests/integration/posts.feature b/tests/integration/posts.feature index eaa1149173..b5f7e9371e 100644 --- a/tests/integration/posts.feature +++ b/tests/integration/posts.feature @@ -31,9 +31,9 @@ Feature: Testing the Posts API "links":[ "http://google.com", "http://facebook.com" - ] + ], + "tags1": [1] }, - "tags":["explosion"], "completed_stages":[1] } """ From 16166768fd6634713dd4d557ba03c1da56b0a746 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 11:25:58 +1200 Subject: [PATCH 17/26] Ignore form.tags if passed when saving Form entities Ignore computed attributes on form --- application/classes/Ushahidi/Repository/Form.php | 3 --- src/Core/Entity/Form.php | 7 +++++++ src/Core/Entity/Tag.php | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/application/classes/Ushahidi/Repository/Form.php b/application/classes/Ushahidi/Repository/Form.php index 2f9ad7be48..c0f94f0def 100644 --- a/application/classes/Ushahidi/Repository/Form.php +++ b/application/classes/Ushahidi/Repository/Form.php @@ -84,9 +84,6 @@ public function update(Entity $entity) } } - // Remove children before saving - unset($entity->children); - // Finally save the form $id = parent::update($entity->setState(['updated' => time()])); diff --git a/src/Core/Entity/Form.php b/src/Core/Entity/Form.php index b1840dca0b..90ce73bd29 100644 --- a/src/Core/Entity/Form.php +++ b/src/Core/Entity/Form.php @@ -61,4 +61,11 @@ public function getResource() { return 'forms'; } + + // StatefulData + protected function getImmutable() + { + // Hack: Add computed properties to immutable list + return array_merge(parent::getImmutable(), ['tags', 'can_create']); + } } diff --git a/src/Core/Entity/Tag.php b/src/Core/Entity/Tag.php index 3fe63bc533..45bf47096b 100644 --- a/src/Core/Entity/Tag.php +++ b/src/Core/Entity/Tag.php @@ -65,4 +65,9 @@ public function getResource() { return 'tags'; } + protected function getImmutable() + { + // Hack: Add computed properties to immutable list + return array_merge(parent::getImmutable(), ['children']); + } } From c55dbfea98e77a8dc24ff2361eb9ad856f20b7bb Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 13:41:17 +1200 Subject: [PATCH 18/26] Add test for removing tag from attribute options when deleted --- tests/integration/bootstrap/RestContext.php | 33 +++++++++++++++++++++ tests/integration/tags.feature | 13 ++++++++ 2 files changed, 46 insertions(+) diff --git a/tests/integration/bootstrap/RestContext.php b/tests/integration/bootstrap/RestContext.php index 100cf4df37..d1d3e6b6d0 100644 --- a/tests/integration/bootstrap/RestContext.php +++ b/tests/integration/bootstrap/RestContext.php @@ -471,6 +471,39 @@ public function thePropertyContains($propertyName, $propertyContainsValue) } } + /** + * @Given /^the "([^"]*)" property does not contain "([^"]*)"$/ + */ + public function thePropertyDoesNotContains($propertyName, $propertyContainsValue) + { + + $data = json_decode($this->response->getBody(true), true); + + $this->theResponseIsJson(); + + $actualPropertyValue = \Arr::path($data, $propertyName); + + if ($actualPropertyValue === null) { + throw new Exception("Property '".$propertyName."' is not set!\n"); + } + + if (is_array($actualPropertyValue) and in_array($propertyContainsValue, $actualPropertyValue)) { + throw new \Exception( + 'Property \''.$propertyName.'\' contains value!' . + '(given: '.$propertyContainsValue.', match: '.json_encode($actualPropertyValue).')' + ); + } elseif (is_string($actualPropertyValue) and strpos($actualPropertyValue, $propertyContainsValue) !== false) { + throw new \Exception( + 'Property \''.$propertyName.'\' does not contain value!' . + '(given: '.$propertyContainsValue.', match: '.$actualPropertyValue.')' + ); + } elseif (!is_array($actualPropertyValue) and !is_string($actualPropertyValue)) { + throw new \Exception( + "Property '".$propertyName."' could not be compared. Must be string or array.\n" + ); + } + } + /** * @Given /^the "([^"]*)" property count is "([^"]*)"$/ */ diff --git a/tests/integration/tags.feature b/tests/integration/tags.feature index 3926f56c60..090c149af6 100644 --- a/tests/integration/tags.feature +++ b/tests/integration/tags.feature @@ -267,6 +267,19 @@ Feature: Testing the Tags API When I request "/tags" Then the guzzle status code should be 200 + Scenario: Deleting a tag removes it from attribute options + Given that I want to delete a "Tag" + And that its "id" is "1" + When I request "/tags" + Then the guzzle status code should be 200 + Given that I want to find a "Attribute" + And that its "id" is "26" + When I request "/forms/1/attributes" + Then the response is JSON + And the response has an "options" property + And the "options" property does not contain "1" + Then the guzzle status code should be 200 + Scenario: Deleting a non-existent Tag Given that I want to delete a "Tag" And that its "id" is "35" From 728c4cf65bd1b6ef5c566e5475b68cb4c5189e07 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 13:41:34 +1200 Subject: [PATCH 19/26] Test that form.tags value is ignored during form update --- tests/integration/forms.feature | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration/forms.feature b/tests/integration/forms.feature index a25379d9c2..e2285a3003 100644 --- a/tests/integration/forms.feature +++ b/tests/integration/forms.feature @@ -35,7 +35,8 @@ Feature: Testing the Forms API "description":"This is a test form updated by BDD testing", "disabled":true, "require_approval":false, - "everyone_can_create":false + "everyone_can_create":false, + "tags": [1,2,3,"junk"] } """ And that its "id" is "1" From 0ab29c28beee5da31f3711e01b0ab0b94888fc00 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 13:44:54 +1200 Subject: [PATCH 20/26] Make child tags top level when parent is deleted, don't delete them Update foreign key to ON DELETE SET NULL, not CASCADE --- ...ake_tags_top_level_when_parent_deleted.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 migrations/20170526014209_make_tags_top_level_when_parent_deleted.php diff --git a/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php b/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php new file mode 100644 index 0000000000..bd10ac164c --- /dev/null +++ b/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php @@ -0,0 +1,40 @@ +table('tags') + ->dropForeignKey('parent_id') + ->update(); + + $this->table('tags') + ->addForeignKey('parent_id', 'tags', 'id', [ + 'delete' => 'SET_NULL', + 'update' => 'CASCADE', + ]) + ->update(); + } + + /** + * Migrate Down. + */ + public function down() + { + $this->table('tags') + ->dropForeignKey('parent_id') + ->update(); + + $this->table('tags') + ->addForeignKey('parent_id', 'tags', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE', + ]) + ->update(); + } +} From 4399b6582a403c7f2159c9374081bd251e16c1c0 Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 13:47:52 +1200 Subject: [PATCH 21/26] Reset fixtures before testing removing a tag Fix to c55dbfe --- tests/integration/tags.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/tags.feature b/tests/integration/tags.feature index 090c149af6..eefcd23fa9 100644 --- a/tests/integration/tags.feature +++ b/tests/integration/tags.feature @@ -267,6 +267,7 @@ Feature: Testing the Tags API When I request "/tags" Then the guzzle status code should be 200 + @resetFixture Scenario: Deleting a tag removes it from attribute options Given that I want to delete a "Tag" And that its "id" is "1" From 071e0612f0423d4f6560bcf9896d1b984ac5bfed Mon Sep 17 00:00:00 2001 From: Robbie Mackay Date: Fri, 26 May 2017 17:00:16 +1200 Subject: [PATCH 22/26] Parse tag names when set as post value (not just post.tags) Parse tags as name or id when sent in post.values. We already do this with post.tags --- application/classes/Ushahidi/Core.php | 7 +++- .../classes/Ushahidi/Repository/Post.php | 37 ++--------------- .../classes/Ushahidi/Repository/Post/Tags.php | 40 ++++++++++++++++++- .../classes/Ushahidi/Validator/Post/Tags.php | 8 ++-- tests/integration/posts.feature | 4 +- 5 files changed, 52 insertions(+), 44 deletions(-) diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 324df9e837..1bede426b7 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -449,8 +449,7 @@ public static function init() 'form_stage_repo' => $di->lazyGet('repository.form_stage'), 'form_repo' => $di->lazyGet('repository.form'), 'post_value_factory' => $di->lazyGet('repository.post_value_factory'), - 'bounding_box_factory' => $di->newFactory('Util_BoundingBox'), - 'tag_repo' => $di->lazyGet('repository.tag') + 'bounding_box_factory' => $di->newFactory('Util_BoundingBox') ]; $di->set('repository.post.datetime', $di->lazyNew('Ushahidi_Repository_Post_Datetime')); @@ -467,6 +466,10 @@ public static function init() $di->set('repository.post.media', $di->lazyNew('Ushahidi_Repository_Post_Media')); $di->set('repository.post.tags', $di->lazyNew('Ushahidi_Repository_Post_Tags')); + $di->params['Ushahidi_Repository_Post_Tags'] = [ + 'tag_repo' => $di->lazyGet('repository.tag') + ]; + // The post value repo factory $di->set('repository.post_value_factory', $di->lazyNew('Ushahidi_Repository_Post_ValueFactory')); $di->params['Ushahidi_Repository_Post_ValueFactory'] = [ diff --git a/application/classes/Ushahidi/Repository/Post.php b/application/classes/Ushahidi/Repository/Post.php index c1c45bc4a6..51147450e8 100644 --- a/application/classes/Ushahidi/Repository/Post.php +++ b/application/classes/Ushahidi/Repository/Post.php @@ -21,7 +21,6 @@ use Ushahidi\Core\SearchData; use Ushahidi\Core\Usecase\Post\StatsPostRepository; use Ushahidi\Core\Usecase\Post\UpdatePostRepository; -use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; use Ushahidi\Core\Usecase\Set\SetPostRepository; use Ushahidi\Core\Traits\UserContext; use Ushahidi\Core\Traits\Permissions\ManagePosts; @@ -67,7 +66,6 @@ class Ushahidi_Repository_Post extends Ushahidi_Repository implements protected $form_repo; protected $post_value_factory; protected $bounding_box_factory; - protected $tag_repo; // By default remove all private responses protected $restricted = true; @@ -91,8 +89,7 @@ public function __construct( FormStageRepository $form_stage_repo, FormRepository $form_repo, Ushahidi_Repository_Post_ValueFactory $post_value_factory, - InstanceFactory $bounding_box_factory, - UpdatePostTagRepository $tag_repo + InstanceFactory $bounding_box_factory ) { parent::__construct($db); @@ -102,7 +99,6 @@ public function __construct( $this->form_repo = $form_repo; $this->post_value_factory = $post_value_factory; $this->bounding_box_factory = $bounding_box_factory; - $this->tag_repo = $tag_repo; } // Ushahidi_Repository @@ -889,8 +885,7 @@ public function create(Entity $entity) // If we don't have tags in the values, use the post.tags value if ($attr_key && !isset($values[$attr_key])) { - $tags = $this->parseTags($entity->tags); - $values[$attr_key] = $tags; + $values[$attr_key] = $entity->tags; } } @@ -939,8 +934,7 @@ public function update(Entity $entity) // If we don't have tags in the values, use the post.tags value if ($attr_key && !isset($values[$attr_key])) { - $tags = $this->parseTags($entity->tags); - $values[$attr_key] = $tags; + $values[$attr_key] = $entity->tags; } } @@ -979,31 +973,6 @@ protected function updatePostValues($post_id, $attributes) } } - protected function parseTags($tags) - { - $tag_ids = []; - if (!empty($tags)) { - foreach ($tags as $tag) - { - if (is_array($tag)) { - $tag = $tag['id']; - } - - // Find the tag by id or name - // @todo this should happen before we even get here - $tag_entity = $this->tag_repo->getByTag($tag); - if (! $tag_entity->id) - { - $tag_entity = $this->tag_repo->get($tag); - } - - $tag_ids[] = $tag_entity->id; - } - } - - return $tag_ids; - } - public function getFirstTagAttr($form_id) { $result = DB::select('form_attributes.id', 'form_attributes.key') diff --git a/application/classes/Ushahidi/Repository/Post/Tags.php b/application/classes/Ushahidi/Repository/Post/Tags.php index 00738cc60a..3b5e3f3c7e 100644 --- a/application/classes/Ushahidi/Repository/Post/Tags.php +++ b/application/classes/Ushahidi/Repository/Post/Tags.php @@ -9,8 +9,26 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ +use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; + class Ushahidi_Repository_Post_Tags extends Ushahidi_Repository_Post_Value { + protected $tag_repo; + + /** + * Construct + * @param Database $db + * @param TagRepo $tag_repo + */ + public function __construct( + Database $db, + UpdatePostTagRepository $tag_repo + ) + { + parent::__construct($db); + $this->tag_repo = $tag_repo; + } + // Ushahidi_Repository protected function getTable() { @@ -40,7 +58,7 @@ public function getValueQuery($form_attribute_id, $match) // UpdatePostValueRepository public function createValue($value, $form_attribute_id, $post_id) { - $tag_id = $value; + $tag_id = $this->parseTag($value); $input = compact('tag_id', 'form_attribute_id', 'post_id'); $input['created'] = time(); @@ -50,11 +68,29 @@ public function createValue($value, $form_attribute_id, $post_id) // UpdatePostValueRepository public function updateValue($id, $value) { - $update = ['tag_id' => $value]; + $tag_id = $this->parseTag($value); + $update = compact($tag_id); if ($id && $update) { $this->executeUpdate(compact('id'), $update); } } + protected function parseTag($tag) + { + if (is_array($tag)) { + $tag = $tag['id']; + } + + // Find the tag by id or name + // @todo this should happen before we even get here + $tag_entity = $this->tag_repo->getByTag($tag); + if (! $tag_entity->id) + { + $tag_entity = $this->tag_repo->get($tag); + } + + return $tag_entity->id; + } + } diff --git a/application/classes/Ushahidi/Validator/Post/Tags.php b/application/classes/Ushahidi/Validator/Post/Tags.php index 47bfdb0e15..8117d08c54 100644 --- a/application/classes/Ushahidi/Validator/Post/Tags.php +++ b/application/classes/Ushahidi/Validator/Post/Tags.php @@ -13,7 +13,7 @@ class Ushahidi_Validator_Post_Tags extends Ushahidi_Validator_Post_ValueValidator { - protected $media_repo; + protected $repo; public function __construct(TagRepository $tags_repo) { @@ -22,11 +22,11 @@ public function __construct(TagRepository $tags_repo) protected function validate($value) { - if (!Valid::digit($value)) { - return 'digit'; + if (is_array($value)) { + $value = $value['id']; } - if (! $this->repo->exists($value)) { + if (!$this->repo->doesTagExist($value)) { return 'exists'; } } diff --git a/tests/integration/posts.feature b/tests/integration/posts.feature index b5f7e9371e..3f4458127d 100644 --- a/tests/integration/posts.feature +++ b/tests/integration/posts.feature @@ -80,9 +80,9 @@ Feature: Testing the Posts API "links":[ "http://google.com", "http://facebook.com" - ] + ], + "tags1": ["explosion"] }, - "tags":["explosion"], "completed_stages":[1] } """ From 91b40a21280eb70c308e25dbd46652abf1529dbc Mon Sep 17 00:00:00 2001 From: will Date: Fri, 26 May 2017 14:10:58 -0400 Subject: [PATCH 23/26] Update to use checklist for testing --- PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 595f052dbe..cd5b43c9c6 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,8 @@ This pull request makes the following changes: - -Test these changes by: -- +Test checklist: +- [ ] Fixes ushahidi/platform# . From 8dce10b1a284f83acb1edbb6e252edffc5e8a58b Mon Sep 17 00:00:00 2001 From: will Date: Mon, 29 May 2017 00:14:00 -0400 Subject: [PATCH 24/26] Fixing error message for tag (#1760) * Fixing error message for tag * adding name to error-message when importing posts with categories * removing children from tag-object before updating * removing tags from form-object before saving form --- application/classes/Ushahidi/Repository/Form.php | 7 +++++-- application/classes/Ushahidi/Repository/Tag.php | 3 ++- application/classes/Ushahidi/Validator/Post/Tags.php | 2 +- application/messages/post.php | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/application/classes/Ushahidi/Repository/Form.php b/application/classes/Ushahidi/Repository/Form.php index c0f94f0def..66ad76fda0 100644 --- a/application/classes/Ushahidi/Repository/Form.php +++ b/application/classes/Ushahidi/Repository/Form.php @@ -83,9 +83,12 @@ public function update(Entity $entity) $key === 'name' ? $this->emit($this->event, $user->email, ['primary_survey_name' => $val]) : null; } } - + $form = $entity->getChanged(); + $form['updated'] = time(); + // removing tags from form before saving + unset($form['tags']); // Finally save the form - $id = parent::update($entity->setState(['updated' => time()])); + $id = $this->executeUpdate(['id'=>$entity->id], $form); return $id; } diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index a0494c3f6a..3c8a4593aa 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -116,7 +116,8 @@ public function create(Entity $entity) public function update(Entity $entity) { $tag = $entity->getChanged(); - + // removing children before saving tag + unset($tag['children']); $count = $this->executeUpdate(['id' => $entity->id], $tag); return $count; diff --git a/application/classes/Ushahidi/Validator/Post/Tags.php b/application/classes/Ushahidi/Validator/Post/Tags.php index 8117d08c54..f83fc0ddbb 100644 --- a/application/classes/Ushahidi/Validator/Post/Tags.php +++ b/application/classes/Ushahidi/Validator/Post/Tags.php @@ -27,7 +27,7 @@ protected function validate($value) } if (!$this->repo->doesTagExist($value)) { - return 'exists'; + return 'tagExists'; } } } diff --git a/application/messages/post.php b/application/messages/post.php index dffd2b1d3c..8a649ebd21 100644 --- a/application/messages/post.php +++ b/application/messages/post.php @@ -27,6 +27,7 @@ 'digit' => 'The field :param1 must be a digit, Given: :param2', 'email' => 'The field :param1 must be an email address, Given: :param2', 'exists' => 'The field :param1 must be a valid post id, Post id: :param2', + 'tagExists' => 'The field :param1 must be a valid category id or name, Category: :param2', 'max_length' => 'The field :param1 must not exceed :param2 characters long, Given: :param2', 'invalidForm' => 'The field :param1 has the wrong post type, Post id: :param2', 'numeric' => 'The field :param1 must be numeric, Given: :param2', From 2424f03dc68909505fcd8d42fdf66bc49300ce21 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 30 May 2017 15:42:22 -0400 Subject: [PATCH 25/26] Incorrect length requirement --- application/classes/Ushahidi/Validator/Post/Markdown.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/classes/Ushahidi/Validator/Post/Markdown.php b/application/classes/Ushahidi/Validator/Post/Markdown.php index 20071cbbd8..68e91bbb00 100644 --- a/application/classes/Ushahidi/Validator/Post/Markdown.php +++ b/application/classes/Ushahidi/Validator/Post/Markdown.php @@ -16,8 +16,5 @@ protected function validate($value) if (!is_scalar($value)) { return 'scalar'; } - if (!Valid::max_length($value, 255)) { - return 'max_length'; - } } } From f989eaadcfcb0850609514ef7c7dc45593e49d84 Mon Sep 17 00:00:00 2001 From: will Date: Wed, 31 May 2017 10:29:51 -0400 Subject: [PATCH 26/26] Release 3.7.0 (#1764) * 1595 intercom (#1718) * adding intercom listener to capture user events * Adding additional intercom events * Adding first login * Fixing bracket * Adding intercom lib * Updating listener * Add laravel/homestead box and remove puppet scripts (#1722) * Updating composer * Updating composer.lock from fresh file * Fixing tests * Update users.feature * Remove redundant file * Fixed var name * Fix default for existing tasks * adding new migration to show_when_published (#1731) * Changing column default for task visibility * Repair linting * Fix Waffle badge Extra space was breaking markdown. * Adding total to geojson collection (#1739) * Adding total to geojson collection * Adding explanatory note about geojson addition * Adjusting unmapped request to incorporate it into stats (#1738) * Adjusting unmapped request to incorporate it into stats and changing the way in which unmapped is caluclated * Fixing failing test * Fixing get total count * Geojson chunking (#1744) * Adding total to geojson collection * Adding explanatory note about geojson addition * Removing unneeded logging * Fixed issue when no posts returned by search * Update linting setup and fix any new lint errors (#1742) * Update phpcs * Add ruleset for src/ * Fix linting on src/ * Lint tests * Make tests PSR4 compliant * Split Kohana bootstrap out of Feature Context so we can ignore it for CS * Fix spec ruleset * Fix linting on migrations * Fixing missing db config for unmapped query * Enable clustering by default * Only add `tags` type attributes to the "post fields" not tasks. * Remove category fields from tasks * Turn posts_tags into a full post value table, and avoid duplicating info - Add extra field to posts_tags - Remove tags from post_varchar - Add Post/Tags validator - Add Post/Tags repo * Don't allow making tags attributes private * Handle legacy tags values and save into first tags attribute. This isn't 100% compatible, but we at least save tags *if* the form has a tags attribute * Make forms tests work in isolation * Stop limiting tags by form, just limit tags per attribute - Stop using forms_tags table - Just use form_attribute.options instead * Rename tags to categories in error messages * Format form tags and tag children as relations, remove tag forms formatter * Remove tags?formId filter from Tag repo We've removed the relevant table, so lets remove the code too! * Fix validating tags when saving a post Typo when injecting tags_repo was breaking it * Fix validating tags when saving a post Typo when injecting tags_repo was breaking it * Add TagRepository interface to use in Post/Tags Validator - Use tag field to set tags in test - Add TagRepository Interface - Implement interface in Tag Repo * Ignore form.tags if passed when saving Form entities Ignore computed attributes on form * Add test for removing tag from attribute options when deleted * Test that form.tags value is ignored during form update * Make child tags top level when parent is deleted, don't delete them Update foreign key to ON DELETE SET NULL, not CASCADE * Reset fixtures before testing removing a tag Fix to c55dbfe * Parse tag names when set as post value (not just post.tags) Parse tags as name or id when sent in post.values. We already do this with post.tags * Update to use checklist for testing * Fixing error message for tag (#1760) * Fixing error message for tag * adding name to error-message when importing posts with categories * removing children from tag-object before updating * removing tags from form-object before saving form * Incorrect length requirement --- PULL_REQUEST_TEMPLATE.md | 4 +- README.md | 4 +- application/classes/Ushahidi/Core.php | 35 +- .../classes/Ushahidi/Formatter/API.php | 2 +- .../classes/Ushahidi/Formatter/Form.php | 11 + .../Formatter/Post/GeoJSONCollection.php | 13 +- .../classes/Ushahidi/Formatter/Post/Stats.php | 4 + .../classes/Ushahidi/Formatter/Tag.php | 14 +- .../classes/Ushahidi/FormsTagsTrait.php | 131 ++---- .../Ushahidi/Listener/IntercomListener.php | 41 ++ .../classes/Ushahidi/Repository/Config.php | 47 ++- .../classes/Ushahidi/Repository/Form.php | 40 +- .../classes/Ushahidi/Repository/Post.php | 162 ++++--- .../classes/Ushahidi/Repository/Post/Tags.php | 96 +++++ .../classes/Ushahidi/Repository/Tag.php | 113 +++-- .../classes/Ushahidi/Repository/User.php | 31 +- .../Validator/Form/Attribute/Update.php | 19 +- .../Ushahidi/Validator/Post/Create.php | 3 - .../Ushahidi/Validator/Post/Markdown.php | 3 - .../classes/Ushahidi/Validator/Post/Tags.php | 33 ++ application/config/map.php | 2 +- application/config/site.php | 26 +- application/messages/post.php | 3 +- behat.yml.dist | 9 +- composer.json | 14 +- composer.lock | 389 +++++++++-------- ...20141007125013_created_updated_indexes.php | 1 - ...20150323031520_rename_groups_to_stages.php | 1 - ...63454_add_published_to_column_to_posts.php | 3 +- ...50612014440_add_users_role_foreign_key.php | 1 - ...03751_fix_unstructured_post_set_filter.php | 1 - ...29193514_add_notifications_oauth_scope.php | 1 - ...20150904083146_add_contact_oauth_scope.php | 1 - .../20151208024527_add_user_to_messages.php | 1 - .../20151208172416_add_csv_oauth_scope.php | 1 - migrations/20160202115439_add_permissions.php | 1 - migrations/20160215174906_add_role_id.php | 1 - ...20160503083146_add_migrate_oauth_scope.php | 1 - ...9232531_add_message_location_attribute.php | 1 - .../20160623184725_set_protected_roles.php | 1 - ...0161208162710_rename_visible_to_column.php | 1 - .../20170311003829_create_webhook_table.php | 1 - ...70313194004_add_webhook_to_oauth_scope.php | 1 - .../20170328080656_add_forms_tags_table.php | 23 +- ..._add_show_when_published_to_form_stage.php | 2 +- ...54_convert_form_tags_to_form_attribute.php | 8 +- ...1_move_post_tag_values_to_post_varchar.php | 111 ++--- ...60511_make_show_when_published_to_true.php | 32 ++ ...8191840_change_task_visibility_default.php | 32 ++ .../20170519044934_remove_tags_from_tasks.php | 20 + ...22004400_remove_tags_from_post_varchar.php | 21 + ...409_join_posts_tags_table_to_attribute.php | 86 ++++ .../20170525003110_drop_forms_tags_table.php | 51 +++ ...ake_tags_top_level_when_parent_deleted.php | 40 ++ migrations/ruleset.xml | 3 +- src/Console/Application.php | 2 +- src/Console/Command/Import.php | 2 +- src/Core/Data.php | 4 +- src/Core/Entity.php | 2 +- src/Core/Entity/Form.php | 9 +- src/Core/Entity/FormRoleRepository.php | 2 +- src/Core/Entity/RoleRepository.php | 2 +- src/Core/Entity/Tag.php | 9 +- src/Core/Entity/TagRepository.php | 21 + src/Core/Exception/ValidatorException.php | 4 +- src/Core/SearchData.php | 4 +- .../Tool/Authorizer/ContactAuthorizer.php | 1 - .../Authorizer/NotificationAuthorizer.php | 1 - src/Core/Tool/Date.php | 2 +- src/Core/Tool/Mailer.php | 2 +- src/Core/Tool/MappingTransformer.php | 4 +- src/Core/Tool/Transformer.php | 2 +- src/Core/Tool/ValidationEngine.php | 6 +- src/Core/Tool/Validator.php | 2 +- src/Core/Traits/CollectionLoader.php | 4 +- src/Core/Traits/DataTransformer.php | 2 +- src/Core/Traits/FilterRecords.php | 4 +- src/Core/Traits/IdentifyRecords.php | 2 +- src/Core/Traits/ModifyRecords.php | 2 +- src/Core/Traits/PostValueRestrictions.php | 1 - src/Core/Traits/StatefulData.php | 4 +- src/Core/Usecase/CreateRepository.php | 2 +- src/Core/Usecase/ImportUsecase.php | 1 - src/Core/Usecase/Message/CreateMessage.php | 3 +- src/Core/Usecase/Post/CreatePost.php | 3 +- .../Post/UpdatePostValueRepository.php | 2 +- .../Usecase/Post/ValuesForPostRepository.php | 4 +- src/Core/Usecase/ReadRepository.php | 2 +- src/Core/Usecase/SearchRepository.php | 2 +- src/Core/Usecase/Set/VerifySetExists.php | 2 +- src/Factory/AuthorizerFactory.php | 2 +- src/Factory/DataFactory.php | 4 +- src/Factory/FormatterFactory.php | 4 +- src/Factory/RepositoryFactory.php | 2 +- src/Factory/UsecaseFactory.php | 4 +- src/Factory/ValidatorFactory.php | 2 +- src/ruleset.xml | 9 + tests/bootstrap.php | 11 +- tests/datasets/ushahidi/Base.yml | 58 +++ tests/integration/acl.feature | 4 +- .../integration/bootstrap/FeatureContext.php | 24 +- tests/integration/bootstrap/KohanaContext.php | 16 + .../bootstrap/MinkExtendedContext.php | 16 +- .../bootstrap/PHPUnitFixtureContext.php | 50 +-- tests/integration/bootstrap/RestContext.php | 394 ++++++++++-------- tests/integration/forms.feature | 12 +- tests/integration/forms/attributes.feature | 8 +- tests/integration/posts.feature | 81 +++- tests/integration/tags.feature | 14 + tests/spec/ruleset.xml | 3 +- ...formerTest.php => DataTransformerTest.php} | 29 +- .../unit/Core/Traits/MockDataTransformer.php | 20 + ...ueTest.php => PostValueRepositoryTest.php} | 16 +- tests/unit/Util/BoundingBoxTest.php | 15 +- tests/unit/Util/TileTest.php | 17 +- 115 files changed, 1693 insertions(+), 940 deletions(-) create mode 100644 application/classes/Ushahidi/Listener/IntercomListener.php create mode 100644 application/classes/Ushahidi/Repository/Post/Tags.php create mode 100644 application/classes/Ushahidi/Validator/Post/Tags.php create mode 100644 migrations/20170507060511_make_show_when_published_to_true.php create mode 100644 migrations/20170508191840_change_task_visibility_default.php create mode 100644 migrations/20170519044934_remove_tags_from_tasks.php create mode 100644 migrations/20170522004400_remove_tags_from_post_varchar.php create mode 100644 migrations/20170522004409_join_posts_tags_table_to_attribute.php create mode 100644 migrations/20170525003110_drop_forms_tags_table.php create mode 100644 migrations/20170526014209_make_tags_top_level_when_parent_deleted.php create mode 100644 src/Core/Entity/TagRepository.php create mode 100644 src/ruleset.xml create mode 100644 tests/integration/bootstrap/KohanaContext.php rename tests/unit/Core/Traits/{DataTranformerTest.php => DataTransformerTest.php} (67%) create mode 100644 tests/unit/Core/Traits/MockDataTransformer.php rename tests/unit/Ushahidi/{PostValueTest.php => PostValueRepositoryTest.php} (85%) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 595f052dbe..cd5b43c9c6 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,8 @@ This pull request makes the following changes: - -Test these changes by: -- +Test checklist: +- [ ] Fixes ushahidi/platform# . diff --git a/README.md b/README.md index d3945567d4..beb83ee87c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Ushahidi 3 ============ [![Build Status](https://travis-ci.org/ushahidi/platform.png)](https://travis-ci.org/ushahidi/platform) -[![Stories up next](https://badge.waffle.io/ushahidi/platform.png?label=Stage: Backlog&title=Backlog)](https://waffle.io/ushahidi/platform) +[![Stories up next](https://badge.waffle.io/ushahidi/platform.png?label=Stage:Backlog&title=Backlog)](https://waffle.io/ushahidi/platform) [![Coverage Status](https://coveralls.io/repos/github/ushahidi/platform/badge.svg)](https://coveralls.io/github/ushahidi/platform) [Download][download] @@ -26,7 +26,7 @@ Ushahidi is an open source web application for information collection, visualiza ### I'm a developer, should I contribute to Ushahidi v3? -Yes! Development moves pretty quickly but the tech stack is getting more and more stable. If you're keen to help build something awesome, [Jump on board..][getin] +Yes! Development moves pretty quickly but the tech stack is getting more and more stable. If you're keen to help build something awesome, [jump on board..][getin] ## Using the Platform diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 578281d77f..1bede426b7 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -73,6 +73,11 @@ public static function init() and Kohana::$config->load('features.private.enabled'); }); + // Intercom config settings + $di->set('site.intercomAppToken', function() use ($di) { + return Kohana::$config->load('site.intercomAppToken'); + }); + // Roles config settings $di->set('roles.enabled', function() use ($di) { return Kohana::$config->load('features.roles.enabled'); @@ -444,8 +449,7 @@ public static function init() 'form_stage_repo' => $di->lazyGet('repository.form_stage'), 'form_repo' => $di->lazyGet('repository.form'), 'post_value_factory' => $di->lazyGet('repository.post_value_factory'), - 'bounding_box_factory' => $di->newFactory('Util_BoundingBox'), - 'tag_repo' => $di->lazyGet('repository.tag') + 'bounding_box_factory' => $di->newFactory('Util_BoundingBox') ]; $di->set('repository.post.datetime', $di->lazyNew('Ushahidi_Repository_Post_Datetime')); @@ -460,6 +464,11 @@ public static function init() $di->set('repository.post.markdown', $di->lazyNew('Ushahidi_Repository_Post_Markdown')); $di->set('repository.post.title', $di->lazyNew('Ushahidi_Repository_Post_Title')); $di->set('repository.post.media', $di->lazyNew('Ushahidi_Repository_Post_Media')); + $di->set('repository.post.tags', $di->lazyNew('Ushahidi_Repository_Post_Tags')); + + $di->params['Ushahidi_Repository_Post_Tags'] = [ + 'tag_repo' => $di->lazyGet('repository.tag') + ]; // The post value repo factory $di->set('repository.post_value_factory', $di->lazyNew('Ushahidi_Repository_Post_ValueFactory')); @@ -478,6 +487,7 @@ public static function init() 'markdown' => $di->lazyGet('repository.post.markdown'), 'title' => $di->lazyGet('repository.post.title'), 'media' => $di->lazyGet('repository.post.media'), + 'tags' => $di->lazyGet('repository.post.tags'), ], ]; @@ -616,6 +626,10 @@ public static function init() $di->params['Ushahidi_Validator_Post_Media'] = [ 'media_repo' => $di->lazyGet('repository.media') ]; + $di->set('validator.post.tags', $di->lazyNew('Ushahidi_Validator_Post_Tags')); + $di->params['Ushahidi_Validator_Post_Tags'] = [ + 'tags_repo' => $di->lazyGet('repository.tag') + ]; $di->set('validator.post.value_factory', $di->lazyNew('Ushahidi_Validator_Post_ValueFactory')); @@ -634,6 +648,7 @@ public static function init() 'title' => $di->lazyGet('validator.post.title'), 'media' => $di->lazyGet('validator.post.media'), 'video' => $di->lazyGet('validator.post.video'), + 'tags' => $di->lazyGet('validator.post.tags'), ], ]; @@ -672,6 +687,22 @@ public static function init() $di->setter['Ushahidi_Listener_PostListener']['setWebhookRepo'] = $di->lazyGet('repository.webhook'); + // Add Intercom Listener to Config + $di->setter['Ushahidi_Repository_Config']['setEvent'] = 'ConfigUpdateEvent'; + $di->setter['Ushahidi_Repository_Config']['setListener'] = + $di->lazyNew('Ushahidi_Listener_IntercomListener'); + + // Add Intercom Listener to Form + $di->setter['Ushahidi_Repository_Form']['setEvent'] = 'FormUpdateEvent'; + $di->setter['Ushahidi_Repository_Form']['setListener'] = + $di->lazyNew('Ushahidi_Listener_IntercomListener'); + + // Add Intercom Listener to User + $di->setter['Ushahidi_Repository_User']['setEvent'] = 'UserGetAllEvent'; + $di->setter['Ushahidi_Repository_User']['setListener'] = + $di->lazyNew('Ushahidi_Listener_IntercomListener'); + + /** * 1. Load the plugins */ diff --git a/application/classes/Ushahidi/Formatter/API.php b/application/classes/Ushahidi/Formatter/API.php index 693143ee82..ca99c823a5 100644 --- a/application/classes/Ushahidi/Formatter/API.php +++ b/application/classes/Ushahidi/Formatter/API.php @@ -107,7 +107,7 @@ protected function format_updated($value) protected function get_relation($resource, $id) { return !$id ? NULL : [ - 'id' => $id, + 'id' => intval($id), 'url' => URL::site(Ushahidi_Rest::url($resource, $id), Request::current()), ]; } diff --git a/application/classes/Ushahidi/Formatter/Form.php b/application/classes/Ushahidi/Formatter/Form.php index dc9d0e8866..893b7c8a01 100644 --- a/application/classes/Ushahidi/Formatter/Form.php +++ b/application/classes/Ushahidi/Formatter/Form.php @@ -26,4 +26,15 @@ protected function format_color($value) $value = ltrim($value, '#'); return $value ? '#' . $value : null; } + + protected function format_tags($tags) + { + $output = []; + foreach ($tags as $tagid) + { + $output[] = $this->get_relation('tags', $tagid); + } + + return $output; + } } diff --git a/application/classes/Ushahidi/Formatter/Post/GeoJSONCollection.php b/application/classes/Ushahidi/Formatter/Post/GeoJSONCollection.php index 52efc6a17e..edc3d09dc5 100644 --- a/application/classes/Ushahidi/Formatter/Post/GeoJSONCollection.php +++ b/application/classes/Ushahidi/Formatter/Post/GeoJSONCollection.php @@ -28,7 +28,6 @@ public function __invoke($entities) 'type' => 'FeatureCollection', 'features' => [] ]; - $unmapped = 0; foreach ($entities as $entity) { @@ -48,7 +47,7 @@ public function __invoke($entities) { $color = ltrim($entity->color, '#'); $color = $color ? '#' . $color : null; - + $output['features'][] = [ 'type' => 'Feature', 'geometry' => [ @@ -68,12 +67,7 @@ public function __invoke($entities) ] ]; } - if(empty($geometries)) - { - $unmapped++; - } } - $output['unmapped'] = $unmapped; if ($this->search->bbox) { @@ -88,6 +82,11 @@ public function __invoke($entities) $output['bbox'] = $bbox; } + + // Note: Appending total output despite it not being in the geojson Spec + // this field is used by the client so that it can determine how many requests to make + // in order to retrieve all the posts + $output['total'] = $this->total; return $output; } diff --git a/application/classes/Ushahidi/Formatter/Post/Stats.php b/application/classes/Ushahidi/Formatter/Post/Stats.php index 7cab18990d..0a23f0bb9b 100644 --- a/application/classes/Ushahidi/Formatter/Post/Stats.php +++ b/application/classes/Ushahidi/Formatter/Post/Stats.php @@ -41,6 +41,10 @@ public function __invoke($records) } else { $data['totals'] = $this->formatTotals($records); } + + if (array_key_exists('unmapped', $records)) { + $data['unmapped'] = $records['unmapped']; + } } return $data; diff --git a/application/classes/Ushahidi/Formatter/Tag.php b/application/classes/Ushahidi/Formatter/Tag.php index d603131ed8..e756272763 100644 --- a/application/classes/Ushahidi/Formatter/Tag.php +++ b/application/classes/Ushahidi/Formatter/Tag.php @@ -22,14 +22,18 @@ protected function format_color($value) return $value ? '#' . $value : null; } - protected function format_forms($forms) + protected function format_children($tags) { $output = []; - foreach ($forms as $formid) - { - $output[] = $this->get_relation('forms', $formid); + + if (is_array($tags)) { + foreach ($tags as $tagid) + { + $output[] = $this->get_relation('tags', $tagid); + //$output[] = intval($tagid); + } } - + return $output; } } diff --git a/application/classes/Ushahidi/FormsTagsTrait.php b/application/classes/Ushahidi/FormsTagsTrait.php index 20fdbc5272..3cdefb513b 100644 --- a/application/classes/Ushahidi/FormsTagsTrait.php +++ b/application/classes/Ushahidi/FormsTagsTrait.php @@ -1,6 +1,6 @@ @@ -11,111 +11,52 @@ trait Ushahidi_FormsTagsTrait { - //returning forms for a specific Tag-id - private function getFormsForTag($id) - { - $result = DB::select('form_id') - ->from('forms_tags') - ->where('tag_id', '=', $id) - ->execute($this->db); - return $result->as_array(NULL, 'form_id'); - } //returning tags for a specific Form-id private function getTagsForForm($id) { - $result = DB::select('tag_id') - ->from('forms_tags') + $attributes = DB::select('form_attributes.options') + ->from('form_attributes') + ->join('form_stages')->on('form_stage_id', '=', 'form_stages.id') + ->join('forms')->on('form_id', '=', 'forms.id') ->where('form_id', '=', $id) - ->execute($this->db); - return $result->as_array(NULL, 'tag_id'); - } - - // updating/adding tags to a form - private function updateFormsTags($form_id, $tags) - { - if (!$tags) { - DB::delete('forms_tags') - ->where('form_id', '=', $form_id) - ->execute($this->db); - } else if ($tags) { - $existing = $this->getTagsForForm($form_id); - $insert = DB::insert('forms_tags', ['form_id', 'tag_id']); - $tag_ids = []; - $new_tags = FALSE; - foreach ($tags as $tag) { - if (!in_array($tag, $existing)) { - $insert->values([$form_id, $tag]); - $new_tags = TRUE; - } - $tag_ids[] = $tag; - } - if ($new_tags) { - $insert->execute($this->db); - } - if (!empty($tag_ids)) { - DB::delete('forms_tags') - ->where('tag_id', 'NOT IN', $tag_ids) - ->and_where('form_id', '=', $form_id) - ->execute($this->db); - } - } - } + ->where('form_attributes.type', '=', 'tags') + ->execute($this->db) + ->as_array(); - //updating/adding forms to a tag - private function updateTagForms($tag_id, $forms) - { - if (empty($forms)) { - DB::delete('forms_tags') - ->where('tag_id', '=', $tag_id) - ->execute($this->db); - } else { - $existing = $this->getFormsForTag($tag_id); - $insert = DB::insert('forms_tags', ['form_id', 'tag_id']); - $form_ids = []; - $new_forms = FALSE; - foreach ($forms as $form) { - if (isset($form['id'])) { - $id = $form['id']; - } else { - $id = $form; - } - if (!in_array($form, $existing)) { - $insert->values([$id, $tag_id]); - $new_forms = TRUE; - } - $form_ids[] = $id; - } - - if ($new_forms) { - $insert->execute($this->db); - } - - if (!empty($form_ids)) { - DB::delete('forms_tags') - ->where('form_id', 'NOT IN', $form_ids) - ->and_where('tag_id', '=', $tag_id) - ->execute($this->db); + $tags = []; + // Combine all tag ids into 1 array + foreach ($attributes as $attr) { + $options = json_decode($attr['options'], TRUE); + if (is_array($options)) { + $tags = array_merge($tags, $options); } } + + return $tags; } - private function updateFormAttributes($id) + private function removeTagFromAttributeOptions($id) { + // Grab all tags attributes $attr = DB::select('id', 'options') - ->from('form_attributes') - ->where('input', '=', 'tags') - ->execute($this->db) - ->as_array('id', 'options'); - foreach ($attr as $attr_id => $value) { - $value = json_decode($value); - if (in_array($id, $value)) { - $index = array_search($id, $value); - array_splice($value, $index, 1); - $value = json_encode($value); + ->from('form_attributes') + ->where('type', '=', 'tags') + ->execute($this->db) + ->as_array('id', 'options'); + + foreach ($attr as $attr_id => $options) { + $options = json_decode($options, TRUE); + if (is_array($options) && in_array($id, $options)) { + // Remove $id from options array + $index = array_search($id, $options); + array_splice($options, $index, 1); + $options = json_encode($options); + + // Save it DB::update('form_attributes') - ->set(array('options' => $value)) - ->where('id', '=', $attr_id) - ->execute($this->db); + ->set(array('options' => $options)) + ->where('id', '=', $attr_id) + ->execute($this->db); } } } diff --git a/application/classes/Ushahidi/Listener/IntercomListener.php b/application/classes/Ushahidi/Listener/IntercomListener.php new file mode 100644 index 0000000000..08a62acf1f --- /dev/null +++ b/application/classes/Ushahidi/Listener/IntercomListener.php @@ -0,0 +1,41 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use League\Event\AbstractListener; +use League\Event\EventInterface; + +use Intercom\IntercomClient; + +use GuzzleHttp\Exception\ClientException; + +class Ushahidi_Listener_IntercomListener extends AbstractListener +{ + public function handle(EventInterface $event, $user_email = null, $data = null) + { + $intercomAppToken = service('site.intercomAppToken'); + + if ($user_email && $intercomAppToken) { + + $client = new IntercomClient($intercomAppToken, null); + try { + + $client->users->update([ + "email" => $user_email, + "custom_attributes" => $data + ]); + } catch(ClientException $e) { + Kohana::$log->add(Log::ERROR, print_r($e,true)); + } + } + } +} diff --git a/application/classes/Ushahidi/Repository/Config.php b/application/classes/Ushahidi/Repository/Config.php index f68abff0f0..500998efb8 100644 --- a/application/classes/Ushahidi/Repository/Config.php +++ b/application/classes/Ushahidi/Repository/Config.php @@ -17,12 +17,18 @@ use Ushahidi\Core\Usecase\UpdateRepository; use Ushahidi\Core\Exception\NotFoundException; +use League\Event\ListenerInterface; +use Ushahidi\Core\Traits\Event; + class Ushahidi_Repository_Config implements ReadRepository, UpdateRepository, ConfigRepository { + // Use Event trait to trigger events + use Event; + // ReadRepository public function getEntity(Array $data = null) { @@ -43,27 +49,57 @@ public function get($group) // UpdateRepository public function update(Entity $entity) { + + $intercom_data = []; $group = $entity->getId(); $this->verifyGroup($group); $config = \Kohana::$config->load($group); + // Intercom count datasources + if ($group === 'data-provider') { + $intercom_data['num_data_sources'] = 0; + foreach ($entity->providers as $key => $value) { + $value ? $intercom_data['num_data_sources']++ : null; + } + } + $immutable = $entity->getImmutable(); - foreach ($entity->getChanged() as $key => $val) { - if (! in_array($key, $immutable)) { - + foreach ($entity->getChanged() as $key => $val) { + + // Emit Intercom Update events + if ($key === 'description') { + $intercom_data['has_description'] = true; + } + + if ($key === 'image_header') { + $intercom_data['has_logo'] = true; + } + + // New User - set their deployment created date + if ($key === 'first_login') { + $intercom_data['deployment_created_date'] = date("Y-m-d H:i:s"); + } + + if (! in_array($key, $immutable)) { + /* Below is to reset the twitter-since_id when the search-terms are updated. This should be revised when the data-source tech-debt is addressed*/ if($key === 'twitter' && isset($config['twitter']) && $val['twitter_search_terms'] !== $config['twitter']['twitter_search_terms']) - { + { $twitter_config = \Kohana::$config->load('twitter'); $twitter_config->set('since_id', 0); } - + $config->set($key, $val); } } + + if ($intercom_data) { + $user = service('session.user'); + $this->emit($this->event, $user->email, $intercom_data); + } } // ConfigRepository @@ -124,3 +160,4 @@ public function all(Array $groups = null) return $result; } } + diff --git a/application/classes/Ushahidi/Repository/Form.php b/application/classes/Ushahidi/Repository/Form.php index cc240e9e94..66ad76fda0 100644 --- a/application/classes/Ushahidi/Repository/Form.php +++ b/application/classes/Ushahidi/Repository/Form.php @@ -14,11 +14,17 @@ use Ushahidi\Core\Entity\FormRepository; use Ushahidi\Core\SearchData; +use League\Event\ListenerInterface; +use Ushahidi\Core\Traits\Event; + class Ushahidi_Repository_Form extends Ushahidi_Repository implements FormRepository { use Ushahidi_FormsTagsTrait; - + + // Use Event trait to trigger events + use Event; + // Ushahidi_Repository protected function getTable() { @@ -32,10 +38,10 @@ public function getEntity(Array $data = null) if (isset($data["id"])) { $can_create = $this->getRolesThatCanCreatePosts($data['id']); $data = $data + [ - 'can_create' => $can_create['roles'], + 'can_create' => $can_create['roles'], + 'tags' => $this->getTagsForForm($data['id']) ]; - $data['tags'] = $this->getTagsForForm($data['id']); - } + } return new Form($data); } @@ -62,14 +68,7 @@ protected function setSearchConditions(SearchData $search) // CreateRepository public function create(Entity $entity) { - - $tags = $entity->tags; - unset($entity->tags); $id = parent::create($entity->setState(['created' => time()])); - //updating forms_tags-table - if ($tags && $id !== null) { - $this->updateFormsTags($id, $tags); - } // todo ensure default group is created return $id; } @@ -77,14 +76,19 @@ public function create(Entity $entity) // UpdateRepository public function update(Entity $entity) { - $tags = $entity->tags; - unset($entity->tags); - unset($entity->children); - $id = parent::update($entity->setState(['updated' => time()])); - // updating forms_tags-table - if ($tags && $entity->id !== null) { - $this->updateFormsTags($entity->id, $tags); + // If orignal Form update Intercom if Name changed + if ($entity->id === 1) { + foreach ($entity->getChanged() as $key => $val) { + $user = service('session.user'); + $key === 'name' ? $this->emit($this->event, $user->email, ['primary_survey_name' => $val]) : null; + } } + $form = $entity->getChanged(); + $form['updated'] = time(); + // removing tags from form before saving + unset($form['tags']); + // Finally save the form + $id = $this->executeUpdate(['id'=>$entity->id], $form); return $id; } diff --git a/application/classes/Ushahidi/Repository/Post.php b/application/classes/Ushahidi/Repository/Post.php index 1c0cc7671f..51147450e8 100644 --- a/application/classes/Ushahidi/Repository/Post.php +++ b/application/classes/Ushahidi/Repository/Post.php @@ -21,7 +21,6 @@ use Ushahidi\Core\SearchData; use Ushahidi\Core\Usecase\Post\StatsPostRepository; use Ushahidi\Core\Usecase\Post\UpdatePostRepository; -use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; use Ushahidi\Core\Usecase\Set\SetPostRepository; use Ushahidi\Core\Traits\UserContext; use Ushahidi\Core\Traits\Permissions\ManagePosts; @@ -67,7 +66,6 @@ class Ushahidi_Repository_Post extends Ushahidi_Repository implements protected $form_repo; protected $post_value_factory; protected $bounding_box_factory; - protected $tag_repo; // By default remove all private responses protected $restricted = true; @@ -91,8 +89,7 @@ public function __construct( FormStageRepository $form_stage_repo, FormRepository $form_repo, Ushahidi_Repository_Post_ValueFactory $post_value_factory, - InstanceFactory $bounding_box_factory, - UpdatePostTagRepository $tag_repo + InstanceFactory $bounding_box_factory ) { parent::__construct($db); @@ -102,7 +99,6 @@ public function __construct( $this->form_repo = $form_repo; $this->post_value_factory = $post_value_factory; $this->bounding_box_factory = $bounding_box_factory; - $this->tag_repo = $tag_repo; } // Ushahidi_Repository @@ -132,7 +128,8 @@ public function getEntity(Array $data = null) { $data += [ 'values' => $this->getPostValues($data['id']), - 'tags' => $this->getTagsForPost($data['id']), + // Continued for legacy + 'tags' => $this->getTagsForPost($data['id'], $data['form_id']), 'sets' => $this->getSetsForPost($data['id']), 'completed_stages' => $this->getCompletedStagesForPost($data['id']), ]; @@ -228,6 +225,7 @@ public function getSearchFields() 'center_point', 'within_km', 'published_to', 'include_types', 'include_attributes', // Specify values to include + 'include_unmapped', 'group_by', 'group_by_tags', 'group_by_attribute_key', // Group results 'timeline', 'timeline_interval', 'timeline_attribute', // Timeline params 'has_location' //contains a location or not @@ -404,18 +402,19 @@ protected function setSearchConditions(SearchData $search) ; } + $raw_union = '(select post_geometry.post_id from post_geometry union select post_point.post_id from post_point)'; if($search->has_location === 'mapped') { - - $query - ->where("$table.id", 'IN', DB::select('post_id') - ->from('post_point')); + $query->where("$table.id", 'IN', + DB::query(Database::SELECT, $raw_union) + ); } else if($search->has_location === 'unmapped') { - $query - ->where("$table.id", 'NOT IN', DB::select('post_id') - ->from('post_point')); + $query->where("$table.id", 'NOT IN', + DB::query(Database::SELECT, $raw_union) + ); } // Filter by tag + // @todo add filter by specific tag attribute? if (!empty($search->tags)) { if (isset($search->tags['any'])) @@ -514,10 +513,32 @@ public function getSearchTotal() ->select([DB::expr('COUNT(DISTINCT posts.id)'), 'total']); // Fetch the result and... - $result = $query->execute($this->db); - + $results = $query->execute($this->db); // ... return the total. - return (int) $result->get('total', 0); + $total = 0; + + foreach ($results->as_array() as $result) { + $total += array_key_exists('total', $result) ? (int) $result['total'] : 0; + } + + return $total; + } + + public function getUnmappedTotal($total_posts) + { + + $mapped = 0; + $raw_sql = "select count(distinct post_id) as 'total' from (select post_geometry.post_id from post_geometry union select post_point.post_id from post_point) as sub;"; + if ($total_posts > 0) { + + $results = DB::query(Database::SELECT, $raw_sql)->execute($this->db); + + foreach($results->as_array() as $result) { + $mapped = array_key_exists('total', $result) ? (int) $result['total'] : 0; + } + } + + return $total_posts - $mapped; } // PostRepository @@ -584,6 +605,7 @@ public function getGroupedTotals(SearchData $search) 'time_label' ]) ->group_by('time_label'); + } // Group by attribute @@ -689,9 +711,13 @@ public function getGroupedTotals(SearchData $search) // Fetch the results and... $results = $this->search_query->execute($this->db); - + $results = $results->as_array(); + if ($search->include_unmapped) { + // Append unmapped totals to stats + $results['unmapped'] = $this->getUnmappedTotal($this->getSearchTotal()); + } // ... return them as an array - return $results->as_array(); + return $results; } // PostRepository @@ -774,10 +800,13 @@ private function getBoundingBoxSubquery(Util_BoundingBox $bounding_box) * @param int $id post id * @return array tag ids for post */ - private function getTagsForPost($id) + private function getTagsForPost($id, $form_id) { + list($attr_id, $attr_key) = $this->getFirstTagAttr($form_id); + $result = DB::select('tag_id')->from('posts_tags') ->where('post_id', '=', $id) + ->where('form_attribute_id', '=', $attr_id) ->execute($this->db); return $result->as_array(NULL, 'tag_id'); } @@ -847,16 +876,23 @@ public function create(Entity $entity) // Create the post $id = $this->executeInsert($this->removeNullValues($post)); + $values = $entity->values; + // Handle legacy post.tags attribute if ($entity->tags) { - // Update post-tags - $this->updatePostTags($id, $entity->tags); + // Find first tag attribute + list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); + + // If we don't have tags in the values, use the post.tags value + if ($attr_key && !isset($values[$attr_key])) { + $values[$attr_key] = $entity->tags; + } } if ($entity->values) { // Update post-values - $this->updatePostValues($id, $entity->values); + $this->updatePostValues($id, $values); } if ($entity->completed_stages) @@ -889,16 +925,23 @@ public function update(Entity $entity) $count = $this->executeUpdate(['id' => $entity->id], $post); + $values = $entity->values; + // Handle legacy post.tags attribute if ($entity->hasChanged('tags')) { - // Update post-tags - $this->updatePostTags($entity->id, $entity->tags); + // Find first tag attribute + list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); + + // If we don't have tags in the values, use the post.tags value + if ($attr_key && !isset($values[$attr_key])) { + $values[$attr_key] = $entity->tags; + } } if ($entity->hasChanged('values')) { // Update post-values - $this->updatePostValues($entity->id, $entity->values); + $this->updatePostValues($entity->id, $values); } if ($entity->hasChanged('completed_stages')) @@ -930,65 +973,18 @@ protected function updatePostValues($post_id, $attributes) } } - protected function updatePostTags($post_id, $tags) + public function getFirstTagAttr($form_id) { - // deletes all tags if $tags is empty - if (empty($tags)) - { - DB::delete('posts_tags') - ->where('post_id', '=', $post_id) - ->execute($this->db); - } - else - { - // Load existing tags - $existing = $this->getTagsForPost($post_id); - - $insert = DB::insert('posts_tags', ['post_id', 'tag_id']); - - $tag_ids = []; - $new_tags = FALSE; - - foreach ($tags as $tag) - { - if (is_array($tag)) { - $tag = $tag['id']; - } - - // Find the tag by id or name - // @todo this should happen before we even get here - $tag_entity = $this->tag_repo->getByTag($tag); - if (! $tag_entity->id) - { - $tag_entity = $this->tag_repo->get($tag); - } - - // Does the post already have this tag? - if (! in_array($tag_entity->id, $existing)) - { - // Add to insert query - $insert->values([$post_id, $tag_entity->id]); - $new_tags = TRUE; - } - - $tag_ids[] = $tag_entity->id; - } - - // Save - if ($new_tags) - { - $insert->execute($this->db); - } + $result = DB::select('form_attributes.id', 'form_attributes.key') + ->from('form_attributes') + ->join('form_stages', 'INNER')->on('form_stages.id', '=', 'form_attributes.form_stage_id') + ->where('form_stages.form_id', '=', $form_id) + ->where('form_attributes.type', '=', 'tags') + ->order_by('form_attributes.priority', 'ASC') + ->limit(1) + ->execute($this->db); - // Remove any other tags - if (! empty($tag_ids)) - { - DB::delete('posts_tags') - ->where('tag_id', 'NOT IN', $tag_ids) - ->and_where('post_id', '=', $post_id) - ->execute($this->db); - } - } + return [$result->get('id'), $result->get('key')]; } @@ -1044,4 +1040,4 @@ public function doesPostRequireApproval($formId) return true; } -} \ No newline at end of file +} diff --git a/application/classes/Ushahidi/Repository/Post/Tags.php b/application/classes/Ushahidi/Repository/Post/Tags.php new file mode 100644 index 0000000000..3b5e3f3c7e --- /dev/null +++ b/application/classes/Ushahidi/Repository/Post/Tags.php @@ -0,0 +1,96 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; + +class Ushahidi_Repository_Post_Tags extends Ushahidi_Repository_Post_Value +{ + protected $tag_repo; + + /** + * Construct + * @param Database $db + * @param TagRepo $tag_repo + */ + public function __construct( + Database $db, + UpdatePostTagRepository $tag_repo + ) + { + parent::__construct($db); + $this->tag_repo = $tag_repo; + } + + // Ushahidi_Repository + protected function getTable() + { + return 'posts_tags'; + } + + // Override selectQuery to fetch attribute 'key' too + protected function selectQuery(Array $where = []) + { + $query = parent::selectQuery($where); + + // Select 'tag_id' as value too + $query->select( + ['posts_tags.tag_id', 'value'] + ); + + return $query; + } + + // PostValueRepository + public function getValueQuery($form_attribute_id, $match) + { + return $this->selectQuery(compact('form_attribute_id')) + ->where('tag_id', 'LIKE', "%$match%"); + } + + // UpdatePostValueRepository + public function createValue($value, $form_attribute_id, $post_id) + { + $tag_id = $this->parseTag($value); + $input = compact('tag_id', 'form_attribute_id', 'post_id'); + $input['created'] = time(); + + return $this->executeInsert($input); + } + + // UpdatePostValueRepository + public function updateValue($id, $value) + { + $tag_id = $this->parseTag($value); + $update = compact($tag_id); + if ($id && $update) + { + $this->executeUpdate(compact('id'), $update); + } + } + + protected function parseTag($tag) + { + if (is_array($tag)) { + $tag = $tag['id']; + } + + // Find the tag by id or name + // @todo this should happen before we even get here + $tag_entity = $this->tag_repo->getByTag($tag); + if (! $tag_entity->id) + { + $tag_entity = $this->tag_repo->get($tag); + } + + return $tag_entity->id; + } + +} diff --git a/application/classes/Ushahidi/Repository/Tag.php b/application/classes/Ushahidi/Repository/Tag.php index 76421eb19e..3c8a4593aa 100644 --- a/application/classes/Ushahidi/Repository/Tag.php +++ b/application/classes/Ushahidi/Repository/Tag.php @@ -12,6 +12,7 @@ use Ushahidi\Core\Entity; use Ushahidi\Core\SearchData; use Ushahidi\Core\Entity\Tag; +use Ushahidi\Core\Entity\TagRepository; use Ushahidi\Core\Usecase\Tag\UpdateTagRepository; use Ushahidi\Core\Usecase\Tag\DeleteTagRepository; use Ushahidi\Core\Usecase\Post\UpdatePostTagRepository; @@ -19,7 +20,8 @@ class Ushahidi_Repository_Tag extends Ushahidi_Repository implements UpdateTagRepository, DeleteTagRepository, - UpdatePostTagRepository + UpdatePostTagRepository, + TagRepository { // Use the JSON transcoder to encode properties use Ushahidi_JsonTranscodeRepository; @@ -42,18 +44,17 @@ public function getEntity(Array $data = null) { if (!empty($data['id'])) { - $data['forms'] = $this->getFormsForTag($data['id']); - - if(empty($data['parent_id'])) { - - $data['children'] = - DB::select('id') - ->from('tags') - ->where('parent_id','=',$data['id']) - ->execute($this->db) - ->as_array(); - } - } + // If this is a top level category + if(empty($data['parent_id'])) { + // Load children + $data['children'] = DB::select('id') + ->from('tags') + ->where('parent_id','=',$data['id']) + ->execute($this->db) + ->as_array(null, 'id'); + } + } + return new Tag($data); } @@ -66,35 +67,32 @@ protected function getJsonProperties() // SearchRepository public function getSearchFields() { - return ['tag', 'type', 'parent_id', 'q', 'level', 'formId' /* LIKE tag */]; + return ['tag', 'type', 'parent_id', 'q', 'level' /* LIKE tag */]; } // Ushahidi_Repository - protected function setSearchConditions(SearchData $search) - { - $query = $this->search_query; - foreach (['tag', 'type', 'parent_id'] as $key) - { - if ($search->$key) { - $query->where($key, '=', $search->$key); - } - } - if ($search->q) { - // Tag text searching - $query->where('tag', 'LIKE', "%{$search->q}%"); - } - if($search->level) { - //searching for top-level-tags - if($search->level === 'parent') { - $query->where('parent_id', '=', null); - } - } - if($search->formId){ - $query->join('forms_tags') - ->on('tags.id', '=', 'forms_tags.tag_id') - ->where('form_id','=', $search->formId); - } - } + protected function setSearchConditions(SearchData $search) + { + $query = $this->search_query; + foreach (['tag', 'type', 'parent_id'] as $key) + { + if ($search->$key) { + $query->where($key, '=', $search->$key); + } + } + + if ($search->q) { + // Tag text searching + $query->where('tag', 'LIKE', "%{$search->q}%"); + } + + if($search->level) { + //searching for top-level-tags + if($search->level === 'parent') { + $query->where('parent_id', '=', null); + } + } + } // SearchRepository public function getSearchResults() @@ -110,29 +108,17 @@ public function create(Entity $entity) $record = $entity->asArray(); $record['created'] = time(); - unset($record['forms']); - $id = $this->executeInsert($this->removeNullValues($record)); - if($entity->forms) { - //updating forms_tags-table - $this->updateTagForms($id, $entity->forms); - } - return $id; } public function update(Entity $entity) { $tag = $entity->getChanged(); - unset($tag['forms']); - + // removing children before saving tag + unset($tag['children']); $count = $this->executeUpdate(['id' => $entity->id], $tag); - // updating forms_tags-table - if($entity->hasChanged('forms')) - { - $this->updateTagForms($entity->id, $entity->forms); - } return $count; } @@ -162,18 +148,23 @@ public function isSlugAvailable($slug) { return $this->selectCount(compact('slug')) === 0; } - public function delete(Entity $entity) - { - $this->updateFormAttributes($entity->id); - return $this->executeDelete([ - 'id' => $entity->id - ]); - } + + public function delete(Entity $entity) + { + // Remove tag from attribute options + $this->removeTagFromAttributeOptions($entity->id); + + return $this->executeDelete([ + 'id' => $entity->id + ]); + } // DeleteTagRepository public function deleteTag($id) { - $this->updateFormAttributes($entity->id); + // Remove tag from attribute options + $this->removeTagFromAttributeOptions($entity->id); + return $this->delete(compact('id')); } } diff --git a/application/classes/Ushahidi/Repository/User.php b/application/classes/Ushahidi/Repository/User.php index 2469b7896a..a8e77c2e10 100644 --- a/application/classes/Ushahidi/Repository/User.php +++ b/application/classes/Ushahidi/Repository/User.php @@ -19,6 +19,9 @@ use Ushahidi\Core\Usecase\User\RegisterRepository; use Ushahidi\Core\Usecase\User\ResetPasswordRepository; +use League\Event\ListenerInterface; +use Ushahidi\Core\Traits\Event; + class Ushahidi_Repository_User extends Ushahidi_Repository implements UserRepository, RegisterRepository, @@ -29,6 +32,9 @@ class Ushahidi_Repository_User extends Ushahidi_Repository implements */ protected $hasher; + // Use Event trait to trigger events + use Event; + /** * @param Hasher $hasher * @return $this @@ -58,7 +64,6 @@ public function create(Entity $entity) 'created' => time(), 'password' => $this->hasher->hash($entity->password), ]; - return parent::create($entity->setState($state)); } @@ -133,6 +138,9 @@ public function isUniqueEmail($email) // RegisterRepository public function register(Entity $entity) { + + $this->updateIntercomUserCount(1); + return $this->executeInsert([ 'realname' => $entity->realname, 'email' => $entity->email, @@ -202,4 +210,25 @@ public function getTotalCount(Array $where = []) { return $this->selectCount($where); } + + // DeleteRepository + public function delete(Entity $entity) { + $this->updateIntercomUserCount(-1); + return parent::delete($entity); + } + + /** + * Pass User count to Intercom + * takes a postive/negative offset by which to increase/decrease count for create/delete + * @param Integer $offset + * @return void + */ + protected function updateIntercomUserCount($offset) + { + $data = [ + 'total_users' => $this->getTotalCount() + $offset + ]; + $user = service('session.user'); + $this->emit($this->event, $user->email, $data); + } } diff --git a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php index 2cae01966c..b5bc82c750 100644 --- a/application/classes/Ushahidi/Validator/Form/Attribute/Update.php +++ b/application/classes/Ushahidi/Validator/Form/Attribute/Update.php @@ -29,6 +29,8 @@ public function __construct(FormAttributeRepository $repo, FormStageRepository $ protected function getRules() { + $type = $this->validation_engine->getFullData('type'); + return [ 'key' => [ ['max_length', [':value', 150]], @@ -76,7 +78,7 @@ protected function getRules() ]]], ], 'required' => [ - ['in_array', [':value', [true,false]]], + ['in_array', [':value', [true, false]]], ], 'priority' => [ ['digit'], @@ -92,10 +94,13 @@ protected function getRules() 'form_id' => [ ['digit'], ], + 'response_private' => [ + [[$this, 'canMakePrivate'], [':value', $type]] + ] ]; } - public function formStageBelongsToForm($value) + public function formStageBelongsToForm($value) { // don't check against nonexistant data if (!$value || !isset($this->valid['form_id'])) { @@ -105,4 +110,14 @@ public function formStageBelongsToForm($value) $group = $this->form_stage_repo->get($value); return ($group->form_id == $this->valid['form_id']); } + + public function canMakePrivate($value, $type) + { + // If input type is tags, then attribute cannot be private + if ($type === 'tags' && $value !== false) { + return false; + } + + return true; + } } diff --git a/application/classes/Ushahidi/Validator/Post/Create.php b/application/classes/Ushahidi/Validator/Post/Create.php index 0eafdf8b77..de33b2d766 100644 --- a/application/classes/Ushahidi/Validator/Post/Create.php +++ b/application/classes/Ushahidi/Validator/Post/Create.php @@ -199,9 +199,6 @@ public function checkApprovalRequired (Validation $validation, $status, $fullDat $requireApproval = $this->repo->doesPostRequireApproval($fullData['form_id']); - Kohana::$log->add(Log::ERROR, print_r($requireApproval, true)); - Kohana::$log->add(Log::ERROR, print_r($status, true)); - // Are we trying to change publish a post that requires approval? if ($requireApproval && $status !== 'draft') { $validation->error('status', 'postNeedsApprovalBeforePublishing'); diff --git a/application/classes/Ushahidi/Validator/Post/Markdown.php b/application/classes/Ushahidi/Validator/Post/Markdown.php index 20071cbbd8..68e91bbb00 100644 --- a/application/classes/Ushahidi/Validator/Post/Markdown.php +++ b/application/classes/Ushahidi/Validator/Post/Markdown.php @@ -16,8 +16,5 @@ protected function validate($value) if (!is_scalar($value)) { return 'scalar'; } - if (!Valid::max_length($value, 255)) { - return 'max_length'; - } } } diff --git a/application/classes/Ushahidi/Validator/Post/Tags.php b/application/classes/Ushahidi/Validator/Post/Tags.php new file mode 100644 index 0000000000..f83fc0ddbb --- /dev/null +++ b/application/classes/Ushahidi/Validator/Post/Tags.php @@ -0,0 +1,33 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +use Ushahidi\Core\Entity\TagRepository; + +class Ushahidi_Validator_Post_Tags extends Ushahidi_Validator_Post_ValueValidator +{ + protected $repo; + + public function __construct(TagRepository $tags_repo) + { + $this->repo = $tags_repo; + } + + protected function validate($value) + { + if (is_array($value)) { + $value = $value['id']; + } + + if (!$this->repo->doesTagExist($value)) { + return 'tagExists'; + } + } +} diff --git a/application/config/map.php b/application/config/map.php index aa04f40839..47b1a5f314 100644 --- a/application/config/map.php +++ b/application/config/map.php @@ -11,7 +11,7 @@ return array( // Enable marker clustering with leaflet.markercluster - 'clustering' => FALSE, + 'clustering' => TRUE, 'cluster_radius' => 50, // Map start location 'default_view' => array( diff --git a/application/config/site.php b/application/config/site.php index cd2e1cdfba..f4de51aa9a 100644 --- a/application/config/site.php +++ b/application/config/site.php @@ -1,4 +1,4 @@ -getHost()->toUnicode(); @@ -33,14 +36,15 @@ } return array( - 'name' => '', - 'description' => '', - 'email' => '', - 'timezone' => 'UTC', - 'language' => 'en-US', - 'date_format' => 'n/j/Y', - 'client_url' => $clientUrl ?: false, - 'first_login' => true, - 'tier' => 'free', - 'private' => false, + 'name' => '', + 'description' => '', + 'email' => '', + 'timezone' => 'UTC', + 'language' => 'en-US', + 'date_format' => 'n/j/Y', + 'client_url' => $clientUrl ?: false, + 'first_login' => true, + 'tier' => 'free', + 'private' => false, + 'intercomAppToken' => $intercomAppToken, ); diff --git a/application/messages/post.php b/application/messages/post.php index 88428126b5..8a649ebd21 100644 --- a/application/messages/post.php +++ b/application/messages/post.php @@ -2,7 +2,7 @@ return [ 'publishedPostsLimitReached' => 'limit::posts', - 'tagDoesNotExist' => 'tag :value does not exist', + 'tagDoesNotExist' => 'category :value does not exist', 'attributeDoesNotExist' => 'attribute ":param1" does not exist', 'tooManyValues' => 'Too many values for :param1 (max: :param2)', 'valueDoesNotExist' => 'value id :param2 for field :param1 does not exist', @@ -27,6 +27,7 @@ 'digit' => 'The field :param1 must be a digit, Given: :param2', 'email' => 'The field :param1 must be an email address, Given: :param2', 'exists' => 'The field :param1 must be a valid post id, Post id: :param2', + 'tagExists' => 'The field :param1 must be a valid category id or name, Category: :param2', 'max_length' => 'The field :param1 must not exceed :param2 characters long, Given: :param2', 'invalidForm' => 'The field :param1 has the wrong post type, Post id: :param2', 'numeric' => 'The field :param1 must be numeric, Given: :param2', diff --git a/behat.yml.dist b/behat.yml.dist index aea9ad7b4f..4c118246e2 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -9,12 +9,13 @@ default: paths: - %paths.base%/tests/integration contexts: - - FeatureContext - - RestContext: + - Tests\Integration\Bootstrap\KohanaContext + - Tests\Integration\Bootstrap\FeatureContext + - Tests\Integration\Bootstrap\RestContext: baseUrl: http://localhost:8000 # proxyUrl: localhost:8888 - - PHPUnitFixtureContext - - MinkExtendedContext + - Tests\Integration\Bootstrap\PHPUnitFixtureContext + - Tests\Integration\Bootstrap\MinkExtendedContext filters: tags: ~@dataproviders extensions: diff --git a/composer.json b/composer.json index 4928458de2..3e40bd4609 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "league/flysystem-rackspace": "~1.0", "league/flysystem": "~1.0", "ircmaxell/password-compat": "^1.0.4", + "intercom/intercom-php": "^v3.1.2", "abraham/twitteroauth": "^0.5.3", "kohana/core" : "3.3.3.1@dev", "kohana/cache" : "3.3.*@dev", @@ -53,14 +54,14 @@ "phpunit/phpunit": "^5.7", "phpunit/dbunit": "~1.4", "phpspec/phpspec": "~3.0", - "squizlabs/php_codesniffer": "1.5.*", "heroku/heroku-buildpack-php": "dev-master", "behat/behat": "^3.3", "behat/mink-extension": "^2.2", "behat/mink-goutte-driver": "^1.2", "satooshi/php-coveralls": "^2.0@dev", "leanphp/phpspec-code-coverage": "~3.1", - "laravel/homestead": "^5.2" + "laravel/homestead": "^5.2", + "squizlabs/php_codesniffer": "~3.0" }, "config": { "bin-dir": "bin/", @@ -77,9 +78,10 @@ } }, "autoload-dev": { - "classmap": [ - "tests/" - ] + "psr-4": { + "Tests\\Unit\\": "tests/unit", + "Tests\\Integration\\Bootstrap\\": "tests/integration/bootstrap" + } }, "minimum-stability": "dev", "prefer-stable": true, @@ -88,7 +90,7 @@ "@migrate" ], "lint" : [ - "phpcs --ignore=vendor/*,application/*,modules/*,plugins/*,httpdocs/*,tests/*,migrations/*,bin/* --standard=PSR2 --tab-width=4 ./", + "phpcs --ignore=vendor/*,application/*,modules/*,plugins/*,httpdocs/*,tests/spec/*,migrations/*,bin/* --standard=src/ruleset.xml --tab-width=4 ./", "phpcs --standard=tests/spec/ruleset.xml --tab-width=4 ./tests/spec/", "phpcs --standard=migrations/ruleset.xml --tab-width=4 ./migrations/" ], diff --git a/composer.lock b/composer.lock index f30f4cc48f..ddadf34031 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1986271af658ed65402813a01a5c1b2f", - "content-hash": "9a1bd95d142d72367d81fd19848ab737", + "hash": "930a9dfe59bde37d71c7443dfcdcb79e", + "content-hash": "75c4f2753a6b406fefe9b4bf17ba51ea", "packages": [ { "name": "abraham/twitteroauth", @@ -115,16 +115,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.25.0", + "version": "3.26.5", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "8fc5e41cd5d4b965c552f52ac0efa726838c6f89" + "reference": "5fd52d91aa168134f13a57df7fbf7d1f7b7a85ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8fc5e41cd5d4b965c552f52ac0efa726838c6f89", - "reference": "8fc5e41cd5d4b965c552f52ac0efa726838c6f89", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5fd52d91aa168134f13a57df7fbf7d1f7b7a85ca", + "reference": "5fd52d91aa168134f13a57df7fbf7d1f7b7a85ca", "shasum": "" }, "require": { @@ -146,7 +146,7 @@ "ext-simplexml": "*", "ext-spl": "*", "nette/neon": "^2.3", - "phpunit/phpunit": "~4.0|~5.0", + "phpunit/phpunit": "^4.8.35|^5.4.0", "psr/cache": "^1.0" }, "suggest": { @@ -191,7 +191,7 @@ "s3", "sdk" ], - "time": "2017-03-31 00:04:32" + "time": "2017-04-28 23:15:22" }, { "name": "beheh/flaps", @@ -289,16 +289,16 @@ }, { "name": "composer/installers", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/composer/installers.git", - "reference": "d78064c68299743e0161004f2de3a0204e33b804" + "reference": "79ad876c7498c0bbfe7eed065b8651c93bfd6045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/d78064c68299743e0161004f2de3a0204e33b804", - "reference": "d78064c68299743e0161004f2de3a0204e33b804", + "url": "https://api.github.com/repos/composer/installers/zipball/79ad876c7498c0bbfe7eed065b8651c93bfd6045", + "reference": "79ad876c7498c0bbfe7eed065b8651c93bfd6045", "shasum": "" }, "require": { @@ -340,12 +340,16 @@ "keywords": [ "Craft", "Dolibarr", + "Eliasis", "Hurad", "ImageCMS", + "Kanboard", "MODX Evo", "Mautic", + "Maya", "OXID", "Plentymarkets", + "Porto", "RadPHP", "SMF", "Thelia", @@ -368,9 +372,11 @@ "fuelphp", "grav", "installer", + "itop", "joomla", "kohana", "laravel", + "lavalite", "lithium", "magento", "mako", @@ -385,6 +391,7 @@ "roundcube", "shopware", "silverstripe", + "sydes", "symfony", "typo3", "wordpress", @@ -392,7 +399,7 @@ "zend", "zikula" ], - "time": "2016-08-13 20:53:52" + "time": "2017-04-24 06:37:16" }, { "name": "ddeboer/data-import", @@ -810,6 +817,54 @@ ], "time": "2017-03-20 17:10:46" }, + { + "name": "intercom/intercom-php", + "version": "v3.1.2", + "source": { + "type": "git", + "url": "https://github.com/intercom/intercom-php.git", + "reference": "9ebffdf46cf42e59cac03e8382e3420ba9df7953" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/intercom/intercom-php/zipball/9ebffdf46cf42e59cac03e8382e3420ba9df7953", + "reference": "9ebffdf46cf42e59cac03e8382e3420ba9df7953", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.0", + "php": ">= 5.6" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Intercom\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache Version 2" + ], + "authors": [ + { + "name": "Intercom Platform Team", + "homepage": "http://intercom.io" + } + ], + "description": "Intercom API client built on top of Guzzle 6", + "keywords": [ + "Guzzle", + "api", + "intercom", + "intercom.io" + ], + "time": "2017-04-04 13:33:25" + }, { "name": "ircmaxell/password-compat", "version": "v1.0.4", @@ -1193,16 +1248,16 @@ }, { "name": "league/flysystem", - "version": "1.0.37", + "version": "1.0.40", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd" + "reference": "3828f0b24e2c1918bb362d57a53205d6dc8fde61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", - "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3828f0b24e2c1918bb362d57a53205d6dc8fde61", + "reference": "3828f0b24e2c1918bb362d57a53205d6dc8fde61", "shasum": "" }, "require": { @@ -1224,12 +1279,12 @@ "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", "league/flysystem-copy": "Allows you to use Copy.com storage", - "league/flysystem-dropbox": "Allows you to use Dropbox storage", "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", "league/flysystem-webdav": "Allows you to use WebDAV storage", - "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", + "spatie/flysystem-dropbox": "Allows you to use Dropbox storage" }, "type": "library", "extra": { @@ -1272,25 +1327,25 @@ "sftp", "storage" ], - "time": "2017-03-22 15:43:14" + "time": "2017-04-28 10:15:08" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.13", + "version": "1.0.15", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c" + "reference": "c947f36f977b495a57e857ae1630df0da35ec456" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c", - "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c947f36f977b495a57e857ae1630df0da35ec456", + "reference": "c947f36f977b495a57e857ae1630df0da35ec456", "shasum": "" }, "require": { "aws/aws-sdk-php": "^3.0.0", - "league/flysystem": "~1.0", + "league/flysystem": "^1.0.40", "php": ">=5.5.0" }, "require-dev": { @@ -1319,7 +1374,7 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2016-06-21 21:34:35" + "time": "2017-04-28 10:21:54" }, { "name": "league/flysystem-rackspace", @@ -2097,16 +2152,16 @@ }, { "name": "symfony/config", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2" + "reference": "e5533fcc0b3dd377626153b2852707878f363728" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/741d6d4cd1414d67d48eb71aba6072b46ba740c2", - "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2", + "url": "https://api.github.com/repos/symfony/config/zipball/e5533fcc0b3dd377626153b2852707878f363728", + "reference": "e5533fcc0b3dd377626153b2852707878f363728", "shasum": "" }, "require": { @@ -2149,20 +2204,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-03-01 18:18:25" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/console", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "28fb243a2b5727774ca309ec2d92da240f1af0dd" + "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/28fb243a2b5727774ca309ec2d92da240f1af0dd", - "reference": "28fb243a2b5727774ca309ec2d92da240f1af0dd", + "url": "https://api.github.com/repos/symfony/console/zipball/a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", + "reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38", "shasum": "" }, "require": { @@ -2212,20 +2267,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-03-06 19:30:27" + "time": "2017-04-26 01:39:17" }, { "name": "symfony/debug", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "b90c9f91ad8ac37d9f114e369042d3226b34dc1a" + "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/b90c9f91ad8ac37d9f114e369042d3226b34dc1a", - "reference": "b90c9f91ad8ac37d9f114e369042d3226b34dc1a", + "url": "https://api.github.com/repos/symfony/debug/zipball/fd6eeee656a5a7b384d56f1072243fe1c0e81686", + "reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686", "shasum": "" }, "require": { @@ -2269,20 +2324,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-02-18 17:28:00" + "time": "2017-04-19 20:17:50" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.18", + "version": "v2.8.20", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0" + "reference": "7fc8e2b4118ff316550596357325dfd92a51f531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bb4ec47e8e109c1c1172145732d0aa468d967cd0", - "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7fc8e2b4118ff316550596357325dfd92a51f531", + "reference": "7fc8e2b4118ff316550596357325dfd92a51f531", "shasum": "" }, "require": { @@ -2329,20 +2384,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-02-21 08:33:48" + "time": "2017-04-26 16:56:54" }, { "name": "symfony/filesystem", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a" + "reference": "040651db13cf061827a460cc10f6e36a445c45b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bc0f17bed914df2cceb989972c3b996043c4da4a", - "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/040651db13cf061827a460cc10f6e36a445c45b4", + "reference": "040651db13cf061827a460cc10f6e36a445c45b4", "shasum": "" }, "require": { @@ -2378,7 +2433,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-03-06 19:30:27" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/polyfill-mbstring", @@ -2441,16 +2496,16 @@ }, { "name": "symfony/property-access", - "version": "v2.8.18", + "version": "v2.8.20", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "820b71d9384a66f92ef968f82af871dc76debedb" + "reference": "28a9b519a9cd1131b486362bfc6a00cdb9779a42" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/820b71d9384a66f92ef968f82af871dc76debedb", - "reference": "820b71d9384a66f92ef968f82af871dc76debedb", + "url": "https://api.github.com/repos/symfony/property-access/zipball/28a9b519a9cd1131b486362bfc6a00cdb9779a42", + "reference": "28a9b519a9cd1131b486362bfc6a00cdb9779a42", "shasum": "" }, "require": { @@ -2497,20 +2552,20 @@ "property path", "reflection" ], - "time": "2017-02-18 17:06:33" + "time": "2017-04-12 14:07:15" }, { "name": "symfony/yaml", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" + "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", - "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", + "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", "shasum": "" }, "require": { @@ -2552,7 +2607,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-03-07 16:47:02" + "time": "2017-05-01 14:55:58" }, { "name": "symm/gisconverter", @@ -3222,25 +3277,29 @@ }, { "name": "behat/transliterator", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/Behat/Transliterator.git", - "reference": "868e05be3a9f25ba6424c2dd4849567f50715003" + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Transliterator/zipball/868e05be3a9f25ba6424c2dd4849567f50715003", - "reference": "868e05be3a9f25ba6424c2dd4849567f50715003", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "chuyskywalker/rolling-curl": "^3.1", + "php-yaoi/php-yaoi": "^1.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -3258,7 +3317,7 @@ "slug", "transliterator" ], - "time": "2015-09-28 16:26:35" + "time": "2017-04-04 11:38:05" }, { "name": "container-interop/container-interop", @@ -3602,16 +3661,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", "shasum": "" }, "require": { @@ -3640,7 +3699,7 @@ "object", "object graph" ], - "time": "2017-01-26 22:05:40" + "time": "2017-04-12 18:52:22" }, { "name": "phpdocumentor/reflection-common", @@ -3828,16 +3887,16 @@ }, { "name": "phpspec/phpspec", - "version": "3.2.3", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/phpspec/phpspec.git", - "reference": "97246d90708cf98983d95d609bbe6f4b039b8600" + "reference": "1c77d11878c4bd475bc66f0eaa2686df0fcfa30f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/phpspec/zipball/97246d90708cf98983d95d609bbe6f4b039b8600", - "reference": "97246d90708cf98983d95d609bbe6f4b039b8600", + "url": "https://api.github.com/repos/phpspec/phpspec/zipball/1c77d11878c4bd475bc66f0eaa2686df0fcfa30f", + "reference": "1c77d11878c4bd475bc66f0eaa2686df0fcfa30f", "shasum": "" }, "require": { @@ -3846,7 +3905,7 @@ "php": "^5.6 || ^7.0", "phpspec/php-diff": "^1.0.0", "phpspec/prophecy": "^1.5", - "sebastian/exporter": "^1.0 || ^2.0", + "sebastian/exporter": "^1.0 || ^2.0 || ^3.0", "symfony/console": "^2.7 || ^3.0", "symfony/event-dispatcher": "^2.7 || ^3.0", "symfony/finder": "^2.7 || ^3.0", @@ -3854,9 +3913,9 @@ "symfony/yaml": "^2.7 || ^3.0" }, "require-dev": { - "behat/behat": "^3.1", + "behat/behat": "^3.3", "ciaranmcnulty/versionbasedtestskipper": "^0.2.1", - "phpunit/phpunit": "^5.4", + "phpunit/phpunit": "^5.5|^6.0", "symfony/filesystem": "^3.0" }, "suggest": { @@ -3906,7 +3965,7 @@ "testing", "tests" ], - "time": "2017-01-29 12:28:48" + "time": "2017-04-27 12:40:39" }, { "name": "phpspec/prophecy", @@ -4032,16 +4091,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "4.0.7", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", - "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", "shasum": "" }, "require": { @@ -4091,7 +4150,7 @@ "testing", "xunit" ], - "time": "2017-03-01 09:12:17" + "time": "2017-04-02 07:44:40" }, { "name": "phpunit/php-file-iterator", @@ -4281,16 +4340,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.7.17", + "version": "5.7.19", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf" + "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68752b665d3875f9a38a357e3ecb35c79f8673bf", - "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/69c4f49ff376af2692bad9cebd883d17ebaa98a1", + "reference": "69c4f49ff376af2692bad9cebd883d17ebaa98a1", "shasum": "" }, "require": { @@ -4359,7 +4418,7 @@ "testing", "xunit" ], - "time": "2017-03-19 16:52:12" + "time": "2017-04-03 02:22:27" }, { "name": "phpunit/phpunit-mock-objects", @@ -4475,12 +4534,12 @@ "source": { "type": "git", "url": "https://github.com/satooshi/php-coveralls.git", - "reference": "d5124af8bd6464144d550906cce46bd0df78f428" + "reference": "d7285decc88dff59c5ff02c4b1052ab424ba7fa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/d5124af8bd6464144d550906cce46bd0df78f428", - "reference": "d5124af8bd6464144d550906cce46bd0df78f428", + "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/d7285decc88dff59c5ff02c4b1052ab424ba7fa5", + "reference": "d7285decc88dff59c5ff02c4b1052ab424ba7fa5", "shasum": "" }, "require": { @@ -4530,7 +4589,7 @@ "github", "test" ], - "time": "2017-02-25 12:14:18" + "time": "2017-03-31 10:12:47" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5047,61 +5106,37 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "1.5.6", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", - "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b95ff2c3b122a3ee4b57d149a57d2afce65522c3", + "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3", "shasum": "" }, "require": { + "ext-simplexml": "*", "ext-tokenizer": "*", - "php": ">=5.1.2" + "ext-xmlwriter": "*", + "php": ">=5.4.0" }, - "suggest": { - "phpunit/php-timer": "dev-master" + "require-dev": { + "phpunit/phpunit": "~4.0" }, "bin": [ - "scripts/phpcs" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { - "dev-phpcs-fixer": "2.0.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/CommentParser/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -5112,26 +5147,26 @@ "role": "lead" } ], - "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "http://www.squizlabs.com/php-codesniffer", "keywords": [ "phpcs", "standards" ], - "time": "2014-12-04 22:32:15" + "time": "2017-05-04 00:33:04" }, { "name": "symfony/browser-kit", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8" + "reference": "9fab1ab6f77b77f3df5fc5250fc6956811699b57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2fe0caa60c1a1dfeefd0425741182687a9b382b8", - "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/9fab1ab6f77b77f3df5fc5250fc6956811699b57", + "reference": "9fab1ab6f77b77f3df5fc5250fc6956811699b57", "shasum": "" }, "require": { @@ -5175,20 +5210,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2017-02-21 09:12:04" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/class-loader", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9" + "reference": "fc4c04bfd17130a9dccfded9578353f311967da7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9", - "reference": "c29a5bc6ca14cfff1f5e3d7781ed74b6e898d2b9", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/fc4c04bfd17130a9dccfded9578353f311967da7", + "reference": "fc4c04bfd17130a9dccfded9578353f311967da7", "shasum": "" }, "require": { @@ -5231,20 +5266,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2017-02-18 17:28:00" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/css-selector", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c" + "reference": "02983c144038e697c959e6b06ef6666de759ccbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", - "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/02983c144038e697c959e6b06ef6666de759ccbc", + "reference": "02983c144038e697c959e6b06ef6666de759ccbc", "shasum": "" }, "require": { @@ -5284,20 +5319,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-02-21 09:12:04" + "time": "2017-05-01 14:55:58" }, { "name": "symfony/dependency-injection", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "74e0935e414ad33d5e82074212c0eedb4681a691" + "reference": "5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/74e0935e414ad33d5e82074212c0eedb4681a691", - "reference": "74e0935e414ad33d5e82074212c0eedb4681a691", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59", + "reference": "5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59", "shasum": "" }, "require": { @@ -5347,20 +5382,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-03-05 00:06:55" + "time": "2017-04-26 01:39:17" }, { "name": "symfony/dom-crawler", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee" + "reference": "f1ad34e8af09ed17570e027cf0c58a12eddec286" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/403944e294cf4ceb3b8447f54cbad88ea7b99cee", - "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f1ad34e8af09ed17570e027cf0c58a12eddec286", + "reference": "f1ad34e8af09ed17570e027cf0c58a12eddec286", "shasum": "" }, "require": { @@ -5403,20 +5438,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-02-21 09:12:04" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/finder", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10" + "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/92d7476d2df60cd851a3e13e078664b1deb8ce10", - "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10", + "url": "https://api.github.com/repos/symfony/finder/zipball/9cf076f8f492f4b1ffac40aae9c2d287b4ca6930", + "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930", "shasum": "" }, "require": { @@ -5452,20 +5487,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-02-21 09:12:04" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/process", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892" + "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/68bfa8c83f24c0ac04ea7193bcdcda4519f41892", - "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892", + "url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", + "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", "shasum": "" }, "require": { @@ -5501,20 +5536,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-03-04 12:23:14" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/stopwatch", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "c5ee0f8650c84b4d36a5f76b3b504233feaabf75" + "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/c5ee0f8650c84b4d36a5f76b3b504233feaabf75", - "reference": "c5ee0f8650c84b4d36a5f76b3b504233feaabf75", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a0105afb670dbd38f521105c444de1b8e10cfe3", + "reference": "5a0105afb670dbd38f521105c444de1b8e10cfe3", "shasum": "" }, "require": { @@ -5550,20 +5585,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-02-18 17:28:00" + "time": "2017-04-12 14:13:17" }, { "name": "symfony/translation", - "version": "v3.2.6", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690" + "reference": "f4a04d2df710f81515df576b2de06bdeee518b83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690", - "reference": "0e1b15ce8fbf3890f4ccdac430ed5e07fdfe0690", + "url": "https://api.github.com/repos/symfony/translation/zipball/f4a04d2df710f81515df576b2de06bdeee518b83", + "reference": "f4a04d2df710f81515df576b2de06bdeee518b83", "shasum": "" }, "require": { @@ -5614,7 +5649,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-03-04 12:23:14" + "time": "2017-04-12 14:13:17" }, { "name": "webmozart/assert", diff --git a/migrations/20141007125013_created_updated_indexes.php b/migrations/20141007125013_created_updated_indexes.php index e62fe4ef91..221e44b0fd 100644 --- a/migrations/20141007125013_created_updated_indexes.php +++ b/migrations/20141007125013_created_updated_indexes.php @@ -98,6 +98,5 @@ public function change() ->addIndex(['created']) ->addIndex(['updated']) ->update(); - } } diff --git a/migrations/20150323031520_rename_groups_to_stages.php b/migrations/20150323031520_rename_groups_to_stages.php index 5a98131192..3cead69605 100644 --- a/migrations/20150323031520_rename_groups_to_stages.php +++ b/migrations/20150323031520_rename_groups_to_stages.php @@ -20,7 +20,6 @@ public function up() 'delete' => 'CASCADE', ]) ->update(); - } public function down() diff --git a/migrations/20150326163454_add_published_to_column_to_posts.php b/migrations/20150326163454_add_published_to_column_to_posts.php index fec2c3cfec..d199c3adec 100644 --- a/migrations/20150326163454_add_published_to_column_to_posts.php +++ b/migrations/20150326163454_add_published_to_column_to_posts.php @@ -7,7 +7,7 @@ class AddPublishedToColumnToPosts extends AbstractMigration /** * Adding role-specific visibility functionality to posts * By default, all published posts are public, but post owners - * or administrators can specify which roles are able to view + * or administrators can specify which roles are able to view * a given post if desired. Admins still have access to all. */ @@ -20,6 +20,5 @@ public function change() 'null' => true ]) ->update(); - } } diff --git a/migrations/20150612014440_add_users_role_foreign_key.php b/migrations/20150612014440_add_users_role_foreign_key.php index fc56e49d15..5323e2d08d 100644 --- a/migrations/20150612014440_add_users_role_foreign_key.php +++ b/migrations/20150612014440_add_users_role_foreign_key.php @@ -28,7 +28,6 @@ public function up() ]) ->update() ; - } /** diff --git a/migrations/20150716003751_fix_unstructured_post_set_filter.php b/migrations/20150716003751_fix_unstructured_post_set_filter.php index ba43f34f94..ba71d86db0 100644 --- a/migrations/20150716003751_fix_unstructured_post_set_filter.php +++ b/migrations/20150716003751_fix_unstructured_post_set_filter.php @@ -23,6 +23,5 @@ public function up() */ public function down() { - } } diff --git a/migrations/20150829193514_add_notifications_oauth_scope.php b/migrations/20150829193514_add_notifications_oauth_scope.php index b457e86683..70382987e6 100644 --- a/migrations/20150829193514_add_notifications_oauth_scope.php +++ b/migrations/20150829193514_add_notifications_oauth_scope.php @@ -11,7 +11,6 @@ class AddNotificationsOauthScope extends AbstractMigration public function up() { $this->execute("INSERT INTO oauth_scopes (scope, name) VALUES ('notifications', 'notifications')"); - } /** diff --git a/migrations/20150904083146_add_contact_oauth_scope.php b/migrations/20150904083146_add_contact_oauth_scope.php index 1778f3bad4..8b6c7c9432 100644 --- a/migrations/20150904083146_add_contact_oauth_scope.php +++ b/migrations/20150904083146_add_contact_oauth_scope.php @@ -10,7 +10,6 @@ class AddContactOauthScope extends AbstractMigration public function up() { $this->execute("INSERT INTO oauth_scopes (scope, name) VALUES ('contacts', 'contacts')"); - } /** diff --git a/migrations/20151208024527_add_user_to_messages.php b/migrations/20151208024527_add_user_to_messages.php index a74b02d3b6..3517bdf6ef 100644 --- a/migrations/20151208024527_add_user_to_messages.php +++ b/migrations/20151208024527_add_user_to_messages.php @@ -21,7 +21,6 @@ public function up() 'update' => 'CASCADE', ]) ->update(); - } /** diff --git a/migrations/20151208172416_add_csv_oauth_scope.php b/migrations/20151208172416_add_csv_oauth_scope.php index 01b05e862d..63da2d4cb0 100644 --- a/migrations/20151208172416_add_csv_oauth_scope.php +++ b/migrations/20151208172416_add_csv_oauth_scope.php @@ -10,7 +10,6 @@ class AddCsvOauthScope extends AbstractMigration public function up() { $this->execute("INSERT INTO oauth_scopes (scope, name) VALUES ('csv', 'csv')"); - } /** diff --git a/migrations/20160202115439_add_permissions.php b/migrations/20160202115439_add_permissions.php index b1e80c990a..9e2f64a719 100644 --- a/migrations/20160202115439_add_permissions.php +++ b/migrations/20160202115439_add_permissions.php @@ -26,6 +26,5 @@ public function change() ('Manage Settings', 'Manage general settings'), ('Bulk Data Import', 'Import data from external sources') "); - } } diff --git a/migrations/20160215174906_add_role_id.php b/migrations/20160215174906_add_role_id.php index e93e011caa..caa2accce5 100644 --- a/migrations/20160215174906_add_role_id.php +++ b/migrations/20160215174906_add_role_id.php @@ -19,7 +19,6 @@ public function up() ->update(); $this->execute("ALTER TABLE roles DROP PRIMARY KEY;"); $this->execute("ALTER TABLE roles MODIFY id INT AUTO_INCREMENT PRIMARY KEY;"); - } /** diff --git a/migrations/20160503083146_add_migrate_oauth_scope.php b/migrations/20160503083146_add_migrate_oauth_scope.php index 85471628b4..13eb329003 100644 --- a/migrations/20160503083146_add_migrate_oauth_scope.php +++ b/migrations/20160503083146_add_migrate_oauth_scope.php @@ -10,7 +10,6 @@ class AddMigrateOauthScope extends AbstractMigration public function up() { $this->execute("INSERT INTO oauth_scopes (scope, name) VALUES ('migrate', 'migrate')"); - } /** diff --git a/migrations/20160509232531_add_message_location_attribute.php b/migrations/20160509232531_add_message_location_attribute.php index 79b97589dc..f25ba2604b 100644 --- a/migrations/20160509232531_add_message_location_attribute.php +++ b/migrations/20160509232531_add_message_location_attribute.php @@ -34,6 +34,5 @@ public function down() WHERE " . $adapter->quoteColumnName('key') . " = 'message_location' " )->execute(); - } } diff --git a/migrations/20160623184725_set_protected_roles.php b/migrations/20160623184725_set_protected_roles.php index 129c3d8f9d..7ed7a602c4 100644 --- a/migrations/20160623184725_set_protected_roles.php +++ b/migrations/20160623184725_set_protected_roles.php @@ -38,6 +38,5 @@ public function up() */ public function down() { - } } diff --git a/migrations/20161208162710_rename_visible_to_column.php b/migrations/20161208162710_rename_visible_to_column.php index 0e511a2dae..7292146b60 100644 --- a/migrations/20161208162710_rename_visible_to_column.php +++ b/migrations/20161208162710_rename_visible_to_column.php @@ -22,6 +22,5 @@ public function down() $this->table('sets') ->renameColumn('role', 'visible_to') ->update(); - } } diff --git a/migrations/20170311003829_create_webhook_table.php b/migrations/20170311003829_create_webhook_table.php index dbbe5247d3..503971fda1 100644 --- a/migrations/20170311003829_create_webhook_table.php +++ b/migrations/20170311003829_create_webhook_table.php @@ -23,7 +23,6 @@ public function up() 'update' => 'CASCADE', ]) ->create(); - } /** diff --git a/migrations/20170313194004_add_webhook_to_oauth_scope.php b/migrations/20170313194004_add_webhook_to_oauth_scope.php index bdfa0aea08..9f35b7c214 100644 --- a/migrations/20170313194004_add_webhook_to_oauth_scope.php +++ b/migrations/20170313194004_add_webhook_to_oauth_scope.php @@ -11,7 +11,6 @@ class AddWebhookToOauthScope extends AbstractMigration public function up() { $this->execute("INSERT INTO oauth_scopes (scope, name) VALUES ('webhooks', 'webhooks')"); - } /** diff --git a/migrations/20170328080656_add_forms_tags_table.php b/migrations/20170328080656_add_forms_tags_table.php index 97a3545934..dabffc554e 100644 --- a/migrations/20170328080656_add_forms_tags_table.php +++ b/migrations/20170328080656_add_forms_tags_table.php @@ -13,7 +13,8 @@ class AddFormsTagsTable extends AbstractMigration * Uncomment this method if you would like to use it. */ public function change() - { $this->table('forms_tags', [ + { + $this->table('forms_tags', [ 'id' => false, 'primary_key' => ['form_id', 'tag_id'], ]) @@ -28,25 +29,5 @@ public function change() 'update' => 'CASCADE' ]) ->create(); - - } - - /** - * Migrate Up. - */ - public function up() - { - - - } - - /** - * Migrate Down. - */ - public function down() - { - - - } } diff --git a/migrations/20170331210813_add_show_when_published_to_form_stage.php b/migrations/20170331210813_add_show_when_published_to_form_stage.php index 430c205f55..9e929d5b73 100644 --- a/migrations/20170331210813_add_show_when_published_to_form_stage.php +++ b/migrations/20170331210813_add_show_when_published_to_form_stage.php @@ -12,7 +12,7 @@ public function up() $this->table('form_stages') ->addColumn('show_when_published', 'boolean', [ 'null' => false, - 'default' => false + 'default' => true ]) ->update(); } diff --git a/migrations/20170412191954_convert_form_tags_to_form_attribute.php b/migrations/20170412191954_convert_form_tags_to_form_attribute.php index 7742b73197..76e0436091 100644 --- a/migrations/20170412191954_convert_form_tags_to_form_attribute.php +++ b/migrations/20170412191954_convert_form_tags_to_form_attribute.php @@ -6,7 +6,7 @@ class ConvertFormTagsToFormAttribute extends AbstractMigration { - + /** * Migrate Up. */ @@ -15,7 +15,8 @@ public function up() $pdo = $this->getAdapter()->getConnection(); $rows = $this->fetchAll( "SELECT id - FROM form_stages" + FROM form_stages + WHERE `type` = 'post'" ); $tag_rows = $this->fetchAll( "SELECT id @@ -53,7 +54,6 @@ public function up() */ public function down() { - $this->execute("DELETE from form_attributes where input = 'tags'"); - + $this->execute("DELETE from form_attributes where type = 'varchar' AND input = 'tags'"); } } diff --git a/migrations/20170417090621_move_post_tag_values_to_post_varchar.php b/migrations/20170417090621_move_post_tag_values_to_post_varchar.php index fed076d255..1c807b1474 100644 --- a/migrations/20170417090621_move_post_tag_values_to_post_varchar.php +++ b/migrations/20170417090621_move_post_tag_values_to_post_varchar.php @@ -9,42 +9,47 @@ class MovePostTagValuesToPostVarchar extends AbstractMigration */ public function up() { - $pdo = $this->getAdapter()->getConnection(); - // fetching posts with form_attribute_id - $posts = $this->fetchAll( - "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id - FROM posts - INNER JOIN form_stages - ON form_stages.form_id = posts.form_id - INNER JOIN form_attributes - ON form_attributes.form_stage_id = form_stages.id" - ); - $insert = $pdo->prepare( - "INSERT into - post_varchar - (`post_id`, `form_attribute_id`, `value`, `created`) - VALUES(:post_id, :form_attribute_id, :value, :created)" - ); - foreach ($posts as $post) { - $post_tags = $pdo->prepare( - "SELECT tag_id - FROM posts_tags - WHERE post_id = :post_id" - ); - $post_tags->execute([':post_id' => $post['id']]); - // inserting post_ids and tag_ids(value) in post_varchar - $tags = $post_tags->fetchAll(); - foreach ($tags as $tag) { - $insert->execute( - [ - ':post_id' => $post['id'], - ':form_attribute_id' => $post['form_attribute_id'], - ':value' => $tag['tag_id'], - ':created' => time() - ] - ); - } - } + // Don't do this if we haven't already! + // We have a better way. + + //$pdo = $this->getAdapter()->getConnection(); + // fetching posts with form_attribute_id + // $posts = $this->fetchAll( + // "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id + // FROM posts + // INNER JOIN form_stages + // ON form_stages.form_id = posts.form_id + // INNER JOIN form_attributes + // ON form_attributes.form_stage_id = form_stages.id + // AND form_attributes.input = 'tags' + // AND form_attributes.type = 'varchar'" + // ); + // $insert = $pdo->prepare( + // "INSERT into + // post_varchar + // (`post_id`, `form_attribute_id`, `value`, `created`) + // VALUES(:post_id, :form_attribute_id, :value, :created)" + // ); + // foreach ($posts as $post) { + // $post_tags = $pdo->prepare( + // "SELECT tag_id + // FROM posts_tags + // WHERE post_id = :post_id" + // ); + // $post_tags->execute([':post_id' => $post['id']]); + // // inserting post_ids and tag_ids(value) in post_varchar + // $tags = $post_tags->fetchAll(); + // foreach ($tags as $tag) { + // $insert->execute( + // [ + // ':post_id' => $post['id'], + // ':form_attribute_id' => $post['form_attribute_id'], + // ':value' => $tag['tag_id'], + // ':created' => time() + // ] + // ); + // } + // } } /** @@ -52,38 +57,10 @@ public function up() */ public function down() { - $pdo = $this->getAdapter()->getConnection(); - $posts = $this->fetchAll( - "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id - FROM posts - INNER JOIN form_stages - ON form_stages.form_id = posts.form_id - INNER JOIN form_attributes - ON form_attributes.form_stage_id = form_stages.id" - ); - $delete = $pdo->prepare( + $this->execute( "DELETE from post_varchar - WHERE post_id = :post_id AND form_attribute_id = :form_attribute_id AND value = :value" + WHERE form_attribute_id IN + (SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')" ); - - foreach ($posts as $post) { - $post_tags = $pdo->prepare( - "SELECT tag_id - FROM posts_tags - WHERE post_id = :post_id" - ); - $post_tags->execute([':post_id' => $post['id']]); - // inserting post_ids and tag_ids(value) in post_varchar - $tags = $post_tags->fetchAll(); - foreach ($tags as $tag) { - $delete->execute( - [ - ':post_id' => $post['id'], - ':form_attribute_id' => $post['form_attribute_id'], - ':value' => $tag['tag_id'] - ] - ); - } - } } } diff --git a/migrations/20170507060511_make_show_when_published_to_true.php b/migrations/20170507060511_make_show_when_published_to_true.php new file mode 100644 index 0000000000..6e39bb3c7f --- /dev/null +++ b/migrations/20170507060511_make_show_when_published_to_true.php @@ -0,0 +1,32 @@ +getAdapter()->getConnection(); + $rows = $this->fetchAll("SELECT show_when_published from form_stages"); + $insert = $pdo->prepare( + "UPDATE form_stages + SET show_when_published = true" + ); + foreach ($rows as $row) { + $insert->execute(); + } + } + + public function down() + { + $pdo = $this->getAdapter()->getConnection(); + $rows = $this->fetchAll("SELECT show_when_published from form_stages"); + $insert = $pdo->prepare( + "UPDATE form_stages + SET show_when_published = false" + ); + foreach ($rows as $row) { + $insert->execute(); + } + } +} diff --git a/migrations/20170508191840_change_task_visibility_default.php b/migrations/20170508191840_change_task_visibility_default.php new file mode 100644 index 0000000000..fd24cc6570 --- /dev/null +++ b/migrations/20170508191840_change_task_visibility_default.php @@ -0,0 +1,32 @@ +table('form_stages') + ->changeColumn('show_when_published', 'boolean', [ + 'null' => false, + 'default'=> true + ]) + ->update(); + } + + /** + * Migrate Down. + */ + public function down() + { + $this->table('form_stages') + ->changeColumn('show_when_published', 'boolean', [ + 'null' => true, + 'default'=> true + ]) + ->update(); + } +} diff --git a/migrations/20170519044934_remove_tags_from_tasks.php b/migrations/20170519044934_remove_tags_from_tasks.php new file mode 100644 index 0000000000..7401578506 --- /dev/null +++ b/migrations/20170519044934_remove_tags_from_tasks.php @@ -0,0 +1,20 @@ +execute(" + DELETE FROM `form_attributes` WHERE + `input` = 'tags' AND + `form_stage_id` IN (SELECT `id` FROM `form_stages` WHERE `type` = 'task') + "); + } + + public function down() + { + // No op, not reversible + } +} diff --git a/migrations/20170522004400_remove_tags_from_post_varchar.php b/migrations/20170522004400_remove_tags_from_post_varchar.php new file mode 100644 index 0000000000..1c2d8b1719 --- /dev/null +++ b/migrations/20170522004400_remove_tags_from_post_varchar.php @@ -0,0 +1,21 @@ +execute( + "DELETE from post_varchar + WHERE form_attribute_id IN + (SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')" + ); + } + + public function down() + { + // No op - not reversible + } +} diff --git a/migrations/20170522004409_join_posts_tags_table_to_attribute.php b/migrations/20170522004409_join_posts_tags_table_to_attribute.php new file mode 100644 index 0000000000..6cf847aaa3 --- /dev/null +++ b/migrations/20170522004409_join_posts_tags_table_to_attribute.php @@ -0,0 +1,86 @@ +getAdapter()->getConnection(); + + $this->table('posts_tags') + ->addColumn('id', 'integer', ['null' => false]) + ->addColumn('form_attribute_id', 'integer') + ->addColumn('created', 'integer', ['default' => 0]) + ->update(); + + // Manually fix up keys + $this->execute('ALTER TABLE posts_tags + DROP PRIMARY KEY, + ADD PRIMARY KEY (id), + ADD INDEX (post_id), + MODIFY COLUMN id INT AUTO_INCREMENT, + ADD UNIQUE INDEX unique_post_tag_attribute_ids (post_id, tag_id, form_attribute_id)'); + + // Make varchar/tags attributes into tags/tags attributes + $this->execute(" + UPDATE form_attributes + SET type = 'tags' + WHERE type = 'varchar' AND input = 'tags' + "); + + $attributes = $this->fetchAll(" + SELECT form_attributes.id, form_stages.form_id + FROM form_attributes + JOIN form_stages ON (form_attributes.form_stage_id = form_stages.id) + WHERE + form_attributes.type = 'tags' AND + form_stages.type = 'post' + "); + + // Set form_attribute_id for posts_tags entries + $insert = $pdo->prepare(' + UPDATE posts_tags JOIN posts ON (posts_tags.post_id = posts.id) + SET form_attribute_id = :attr_id WHERE posts.form_id = :form_id + '); + foreach ($attributes as $attribute) { + $insert->execute([ + ':attr_id' => $attribute['id'], + ':form_id' => $attribute['form_id'] + ]); + } + + // Add foreign key for form_attribute_id + $this->table('posts_tags') + ->addForeignKey('form_attribute_id', 'form_attributes', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE', + ]) + ->update(); + } + + public function down() + { + // Make tags/tags attributes into varchar/tags attributes + $this->execute(" + UPDATE form_attributes + SET type = 'varchar' + WHERE type = 'tags' AND input = 'tags' + "); + + // Restore keys/indexs + $this->execute('ALTER TABLE posts_tags + DROP PRIMARY KEY, + ADD PRIMARY KEY (post_id, tag_id), + MODIFY COLUMN id INT, + DROP INDEX unique_post_tag_attribute_ids'); + + // Remove columns + $this->table('posts_tags') + ->dropForeignKey('form_attribute_id') + ->removeColumn('id') + ->removeColumn('form_attribute_id') + ->removeColumn('created') + ->update(); + } +} diff --git a/migrations/20170525003110_drop_forms_tags_table.php b/migrations/20170525003110_drop_forms_tags_table.php new file mode 100644 index 0000000000..781ecba7da --- /dev/null +++ b/migrations/20170525003110_drop_forms_tags_table.php @@ -0,0 +1,51 @@ +dropTable('forms_tags'); + } + + public function down() + { + $this->table('forms_tags', [ + 'id' => false, + 'primary_key' => ['form_id', 'tag_id'], + ]) + ->addColumn('form_id', 'integer') + ->addForeignKey('form_id', 'forms', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE' + ]) + ->addColumn('tag_id', 'integer') + ->addForeignKey('tag_id', 'tags', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE' + ]) + ->create(); + } +} diff --git a/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php b/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php new file mode 100644 index 0000000000..bd10ac164c --- /dev/null +++ b/migrations/20170526014209_make_tags_top_level_when_parent_deleted.php @@ -0,0 +1,40 @@ +table('tags') + ->dropForeignKey('parent_id') + ->update(); + + $this->table('tags') + ->addForeignKey('parent_id', 'tags', 'id', [ + 'delete' => 'SET_NULL', + 'update' => 'CASCADE', + ]) + ->update(); + } + + /** + * Migrate Down. + */ + public function down() + { + $this->table('tags') + ->dropForeignKey('parent_id') + ->update(); + + $this->table('tags') + ->addForeignKey('parent_id', 'tags', 'id', [ + 'delete' => 'CASCADE', + 'update' => 'CASCADE', + ]) + ->update(); + } +} diff --git a/migrations/ruleset.xml b/migrations/ruleset.xml index 402af32586..27363ab4c6 100644 --- a/migrations/ruleset.xml +++ b/migrations/ruleset.xml @@ -5,5 +5,6 @@ + - \ No newline at end of file + diff --git a/src/Console/Application.php b/src/Console/Application.php index 122bb7dafe..dae7d3adbc 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -23,7 +23,7 @@ class Application extends ConsoleApplication * @param Array $commands * @return void */ - public function injectCommands(Array $commands) + public function injectCommands(array $commands) { foreach ($commands as $command) { $this->add($command()); diff --git a/src/Console/Command/Import.php b/src/Console/Command/Import.php index d518994ab8..b4d461283d 100644 --- a/src/Console/Command/Import.php +++ b/src/Console/Command/Import.php @@ -38,7 +38,7 @@ class Import extends Command * Set Data Importers * @param [Ushahidi\DataImport\Importer, ..] $importers */ - public function setImporters(Array $importers) + public function setImporters(array $importers) { $this->importers = $importers; } diff --git a/src/Core/Data.php b/src/Core/Data.php index aff606a7b7..b556ab9230 100644 --- a/src/Core/Data.php +++ b/src/Core/Data.php @@ -33,7 +33,7 @@ abstract class Data * @param Array $data raw input * @return void */ - public function __construct(Array $data) + public function __construct(array $data) { // Get the (empty) array that currently exists, this tells us what // properties are allowed in this object. @@ -88,7 +88,7 @@ public function asArray() * @param Array $compare existing data * @return Data */ - public function getDifferent(Array $compare) + public function getDifferent(array $compare) { // Get the difference of current data and comparison. // This will allow null values in $compare to be overridden, diff --git a/src/Core/Entity.php b/src/Core/Entity.php index 3eded5c5c7..c8ae7c59f7 100644 --- a/src/Core/Entity.php +++ b/src/Core/Entity.php @@ -41,7 +41,7 @@ public function asArray(); * @param Array $data * @return $this */ - public function setState(Array $data); + public function setState(array $data); /** * Get all values that have been changed since initial state was defined. diff --git a/src/Core/Entity/Form.php b/src/Core/Entity/Form.php index d623457fd2..90ce73bd29 100644 --- a/src/Core/Entity/Form.php +++ b/src/Core/Entity/Form.php @@ -28,7 +28,7 @@ class Form extends StaticEntity protected $require_approval; protected $everyone_can_create; protected $can_create; - public $tags; + protected $tags; // DataTransformer protected function getDefinition() @@ -61,4 +61,11 @@ public function getResource() { return 'forms'; } + + // StatefulData + protected function getImmutable() + { + // Hack: Add computed properties to immutable list + return array_merge(parent::getImmutable(), ['tags', 'can_create']); + } } diff --git a/src/Core/Entity/FormRoleRepository.php b/src/Core/Entity/FormRoleRepository.php index 936c4918cf..9a908841de 100644 --- a/src/Core/Entity/FormRoleRepository.php +++ b/src/Core/Entity/FormRoleRepository.php @@ -36,5 +36,5 @@ public function existsInFormRole($role_id, $form_id); * @param [Ushahidi\Core\Entity\FormRole, ...] $entities * @return [Ushahidi\Core\Entity\FormRole, ...] */ - public function updateCollection(Array $entities); + public function updateCollection(array $entities); } diff --git a/src/Core/Entity/RoleRepository.php b/src/Core/Entity/RoleRepository.php index 5f30c8ef2f..4482d92d7b 100644 --- a/src/Core/Entity/RoleRepository.php +++ b/src/Core/Entity/RoleRepository.php @@ -22,7 +22,7 @@ interface RoleRepository extends * @param Array $roles * @return Boolean */ - public function doRolesExist(Array $roles = null); + public function doRolesExist(array $roles = null); /** * @param String $name diff --git a/src/Core/Entity/Tag.php b/src/Core/Entity/Tag.php index 50fc758853..45bf47096b 100644 --- a/src/Core/Entity/Tag.php +++ b/src/Core/Entity/Tag.php @@ -26,7 +26,6 @@ class Tag extends StaticEntity protected $priority; protected $created; protected $role; - protected $forms; protected $children; // StatefulData @@ -57,8 +56,7 @@ protected function getDefinition() 'priority' => 'int', 'created' => 'int', 'role' => '*json', - 'forms' => 'array', - 'children' =>'array', + 'children' => 'array', ]; } @@ -67,4 +65,9 @@ public function getResource() { return 'tags'; } + protected function getImmutable() + { + // Hack: Add computed properties to immutable list + return array_merge(parent::getImmutable(), ['children']); + } } diff --git a/src/Core/Entity/TagRepository.php b/src/Core/Entity/TagRepository.php new file mode 100644 index 0000000000..d1e11434d5 --- /dev/null +++ b/src/Core/Entity/TagRepository.php @@ -0,0 +1,21 @@ + + * @package Ushahidi\Application + * @copyright 2014 Ushahidi + * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) + */ + +namespace Ushahidi\Core\Entity; + +use Ushahidi\Core\Entity\Repository\EntityGet; +use Ushahidi\Core\Entity\Repository\EntityExists; + +interface TagRepository extends + EntityGet, + EntityExists +{ +} diff --git a/src/Core/Exception/ValidatorException.php b/src/Core/Exception/ValidatorException.php index 551bcc383c..f3c97e2dc9 100644 --- a/src/Core/Exception/ValidatorException.php +++ b/src/Core/Exception/ValidatorException.php @@ -18,7 +18,7 @@ class ValidatorException extends \InvalidArgumentException { private $errors; - public function __construct($message, Array $errors, Exception $previous = null) + public function __construct($message, array $errors, Exception $previous = null) { $flatErrors = iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($errors)), false); @@ -28,7 +28,7 @@ public function __construct($message, Array $errors, Exception $previous = null) $this->setErrors($errors); } - public function setErrors(Array $errors) + public function setErrors(array $errors) { $this->errors = $errors; } diff --git a/src/Core/SearchData.php b/src/Core/SearchData.php index ca744acf2c..d9ad75c302 100644 --- a/src/Core/SearchData.php +++ b/src/Core/SearchData.php @@ -34,7 +34,7 @@ class SearchData * * @param Array $filters */ - public function __construct(Array $filters = null) + public function __construct(array $filters = null) { if ($filters) { $this->setFilters($filters); @@ -81,7 +81,7 @@ public function __isset($key) * @param Array $sorting * @return $this */ - public function setSortingKeys(Array $sorting) + public function setSortingKeys(array $sorting) { $this->sorting = $sorting; return $this; diff --git a/src/Core/Tool/Authorizer/ContactAuthorizer.php b/src/Core/Tool/Authorizer/ContactAuthorizer.php index 4d7c464036..6b571b8b70 100644 --- a/src/Core/Tool/Authorizer/ContactAuthorizer.php +++ b/src/Core/Tool/Authorizer/ContactAuthorizer.php @@ -56,7 +56,6 @@ public function isAllowed(Entity $entity, $privilege) // Contacts should not be deleted. if ($this->isUserOwner($entity, $user) and in_array($privilege, ['create', 'read', 'update'])) { - return true; } diff --git a/src/Core/Tool/Authorizer/NotificationAuthorizer.php b/src/Core/Tool/Authorizer/NotificationAuthorizer.php index dddc6d7a6f..fd5c7aa402 100644 --- a/src/Core/Tool/Authorizer/NotificationAuthorizer.php +++ b/src/Core/Tool/Authorizer/NotificationAuthorizer.php @@ -56,7 +56,6 @@ public function isAllowed(Entity $entity, $privilege) // Allow create, read, update and delete if owner. if ($this->isUserOwner($entity, $user) and in_array($privilege, ['create', 'read', 'update', 'delete'])) { - return true; } diff --git a/src/Core/Tool/Date.php b/src/Core/Tool/Date.php index e7ab3766b4..5117f1c207 100644 --- a/src/Core/Tool/Date.php +++ b/src/Core/Tool/Date.php @@ -68,7 +68,7 @@ public function getTimestampFromString($time, $format = null) * @param String $format non-default format * @return Array */ - public function addTimestampToResults(Array $results, $key = 'date', $add = 'ts', $format = null) + public function addTimestampToResults(array $results, $key = 'date', $add = 'ts', $format = null) { if (!$format) { $format = $this->getDateFormat(); diff --git a/src/Core/Tool/Mailer.php b/src/Core/Tool/Mailer.php index b38493e132..c9ccbceeca 100644 --- a/src/Core/Tool/Mailer.php +++ b/src/Core/Tool/Mailer.php @@ -23,5 +23,5 @@ interface Mailer * @param Array|null $params Params for populating the template * @return void */ - public function send($to, $type, Array $params = null); + public function send($to, $type, array $params = null); } diff --git a/src/Core/Tool/MappingTransformer.php b/src/Core/Tool/MappingTransformer.php index aefea4aef8..e57543a78a 100644 --- a/src/Core/Tool/MappingTransformer.php +++ b/src/Core/Tool/MappingTransformer.php @@ -17,6 +17,6 @@ interface MappingTransformer extends Transformer { - public function setMap(Array $map); - public function setFixedValues(Array $fixedValues); + public function setMap(array $map); + public function setFixedValues(array $fixedValues); } diff --git a/src/Core/Tool/Transformer.php b/src/Core/Tool/Transformer.php index 33e2d1ae52..0a23c271d7 100644 --- a/src/Core/Tool/Transformer.php +++ b/src/Core/Tool/Transformer.php @@ -15,5 +15,5 @@ interface Transformer { - public function interact(Array $data); + public function interact(array $data); } diff --git a/src/Core/Tool/ValidationEngine.php b/src/Core/Tool/ValidationEngine.php index 01675ab762..7b31e1039c 100644 --- a/src/Core/Tool/ValidationEngine.php +++ b/src/Core/Tool/ValidationEngine.php @@ -19,7 +19,7 @@ interface ValidationEngine * * @param Array $data array of data in $key => $value format */ - public function setData(Array $data); + public function setData(array $data); /** * Get data by its array key @@ -33,7 +33,7 @@ public function getData($key = null); * * @param Array $data array of data in $key => $value format */ - public function setFullData(Array $data); + public function setFullData(array $data); /** * Get full data by its array key @@ -47,7 +47,7 @@ public function getFullData($key = null); * * @return null */ - public function rules($field, Array $rules); + public function rules($field, array $rules); /** * Check the data against the previously set rules diff --git a/src/Core/Tool/Validator.php b/src/Core/Tool/Validator.php index 681476b659..ee2c016f18 100644 --- a/src/Core/Tool/Validator.php +++ b/src/Core/Tool/Validator.php @@ -40,7 +40,7 @@ abstract protected function getRules(); * @param Array $fullData an array of full entity data for reference during validation * @return bool */ - public function check(Array $data, Array $fullData = []) + public function check(array $data, array $fullData = []) { // If no full data is passed, fallback to changed values if (!$fullData) { diff --git a/src/Core/Traits/CollectionLoader.php b/src/Core/Traits/CollectionLoader.php index 52d46bbf1d..388c3600b4 100644 --- a/src/Core/Traits/CollectionLoader.php +++ b/src/Core/Traits/CollectionLoader.php @@ -22,7 +22,7 @@ trait CollectionLoader * @param Array $data * @return Ushahidi\Core\Entity */ - abstract public function getEntity(Array $data = null); + abstract public function getEntity(array $data = null); /** * Converts an array of results into an array of entities, @@ -30,7 +30,7 @@ abstract public function getEntity(Array $data = null); * @param Array $results * @return Array */ - protected function getCollection(Array $results) + protected function getCollection(array $results) { $collection = []; foreach ($results as $row) { diff --git a/src/Core/Traits/DataTransformer.php b/src/Core/Traits/DataTransformer.php index 1727e8e99e..05c7c7dc2d 100644 --- a/src/Core/Traits/DataTransformer.php +++ b/src/Core/Traits/DataTransformer.php @@ -171,7 +171,7 @@ protected function getCustomTransformer($type) * @param Array $data * @return Array */ - protected function transform(Array $data) + protected function transform(array $data) { $definition = $this->getDefinition(); diff --git a/src/Core/Traits/FilterRecords.php b/src/Core/Traits/FilterRecords.php index ce0b72d0f9..74f92fdb6e 100644 --- a/src/Core/Traits/FilterRecords.php +++ b/src/Core/Traits/FilterRecords.php @@ -37,7 +37,7 @@ trait FilterRecords * @param Array $filters * @return $this */ - public function setFilters(Array $filters) + public function setFilters(array $filters) { $this->filters = $filters; return $this; @@ -71,7 +71,7 @@ public function setFilter($name, $value) * @param Array $force force all parameters to be defined * @return Array */ - public function getFilters(Array $allowed, $force = false) + public function getFilters(array $allowed, $force = false) { $filters = array_intersect_key($this->filters, array_flip($allowed)); if ($force) { diff --git a/src/Core/Traits/IdentifyRecords.php b/src/Core/Traits/IdentifyRecords.php index ca167ab287..e8da2a355f 100644 --- a/src/Core/Traits/IdentifyRecords.php +++ b/src/Core/Traits/IdentifyRecords.php @@ -35,7 +35,7 @@ trait IdentifyRecords * @param Array $identifiers * @return $this */ - public function setIdentifiers(Array $identifiers) + public function setIdentifiers(array $identifiers) { $this->identifiers = array_replace($this->identifiers, $identifiers); return $this; diff --git a/src/Core/Traits/ModifyRecords.php b/src/Core/Traits/ModifyRecords.php index 3d757a8952..2add3b79ad 100644 --- a/src/Core/Traits/ModifyRecords.php +++ b/src/Core/Traits/ModifyRecords.php @@ -37,7 +37,7 @@ trait ModifyRecords * @param Array $payload * @return $this */ - public function setPayload(Array $payload) + public function setPayload(array $payload) { $this->payload = $payload; return $this; diff --git a/src/Core/Traits/PostValueRestrictions.php b/src/Core/Traits/PostValueRestrictions.php index a4d71bdcb2..8d392a466a 100644 --- a/src/Core/Traits/PostValueRestrictions.php +++ b/src/Core/Traits/PostValueRestrictions.php @@ -25,7 +25,6 @@ public function canUserSeeAuthor(Post $post, FormRepository $form_repo, $user) { if ($post->form_id) { - if ($this->canUserEditForm($post->form_id, $user)) { return true; } diff --git a/src/Core/Traits/StatefulData.php b/src/Core/Traits/StatefulData.php index d3ae1cd51d..7b30691605 100644 --- a/src/Core/Traits/StatefulData.php +++ b/src/Core/Traits/StatefulData.php @@ -30,7 +30,7 @@ trait StatefulData * * @param Array $data */ - public function __construct(Array $data = null) + public function __construct(array $data = null) { // Initialize change tracking. static::$changed[$this->getObjectId()] = []; @@ -123,7 +123,7 @@ final protected function getObjectId() * @param Array $data * @return $this */ - public function setState(Array $data) + public function setState(array $data) { // Allow for data to be filled in by deriving from other values. foreach ($this->getDerived() as $key => $possible) { diff --git a/src/Core/Usecase/CreateRepository.php b/src/Core/Usecase/CreateRepository.php index 052accc5b4..76f9fa5cb2 100644 --- a/src/Core/Usecase/CreateRepository.php +++ b/src/Core/Usecase/CreateRepository.php @@ -28,5 +28,5 @@ public function create(Entity $entity); * @param Array $data * @return Entity */ - public function getEntity(Array $data = null); + public function getEntity(array $data = null); } diff --git a/src/Core/Usecase/ImportUsecase.php b/src/Core/Usecase/ImportUsecase.php index cf8801f926..205e6e226f 100644 --- a/src/Core/Usecase/ImportUsecase.php +++ b/src/Core/Usecase/ImportUsecase.php @@ -109,7 +109,6 @@ public function interact() $created_entities = array(); // Fetch a record foreach ($this->payload as $index => $record) { - // ... transform record $entity = $this->transform($record); diff --git a/src/Core/Usecase/Message/CreateMessage.php b/src/Core/Usecase/Message/CreateMessage.php index cbcdc034b4..1ae8d2b11c 100644 --- a/src/Core/Usecase/Message/CreateMessage.php +++ b/src/Core/Usecase/Message/CreateMessage.php @@ -30,8 +30,7 @@ protected function getEntity() } // If no user information is provided, default to the current session user. - if ( - empty($entity->user_id) && + if (empty($entity->user_id) && $this->auth->getUserId() ) { $entity->setState(['user_id' => $this->auth->getUserId()]); diff --git a/src/Core/Usecase/Post/CreatePost.php b/src/Core/Usecase/Post/CreatePost.php index 6712e9a4bf..103e0c0ad5 100644 --- a/src/Core/Usecase/Post/CreatePost.php +++ b/src/Core/Usecase/Post/CreatePost.php @@ -24,8 +24,7 @@ protected function getEntity() $entity = parent::getEntity(); // If no user information is provided, default to the current session user. - if ( - empty($entity->user_id) && + if (empty($entity->user_id) && empty($entity->author_email) && empty($entity->author_realname) && $this->auth->getUserId() diff --git a/src/Core/Usecase/Post/UpdatePostValueRepository.php b/src/Core/Usecase/Post/UpdatePostValueRepository.php index 8b874a0d9b..032e7e3d1d 100644 --- a/src/Core/Usecase/Post/UpdatePostValueRepository.php +++ b/src/Core/Usecase/Post/UpdatePostValueRepository.php @@ -35,5 +35,5 @@ public function updateValue($id, $value); * @param Integer $post_id * @param Array $ids */ - public function deleteNotIn($post_id, Array $ids); + public function deleteNotIn($post_id, array $ids); } diff --git a/src/Core/Usecase/Post/ValuesForPostRepository.php b/src/Core/Usecase/Post/ValuesForPostRepository.php index d0f7153634..c2b4aa08ea 100644 --- a/src/Core/Usecase/Post/ValuesForPostRepository.php +++ b/src/Core/Usecase/Post/ValuesForPostRepository.php @@ -21,8 +21,8 @@ interface ValuesForPostRepository */ public function getAllForPost( $post_id, - Array $include_attributes = [], - Array $exclude_stages = [], + array $include_attributes = [], + array $exclude_stages = [], $restricted = false ); diff --git a/src/Core/Usecase/ReadRepository.php b/src/Core/Usecase/ReadRepository.php index 37df1bed91..f30923bf3e 100644 --- a/src/Core/Usecase/ReadRepository.php +++ b/src/Core/Usecase/ReadRepository.php @@ -20,5 +20,5 @@ interface ReadRepository extends EntityGet * @param Array $data * @return Entity */ - public function getEntity(Array $data = null); + public function getEntity(array $data = null); } diff --git a/src/Core/Usecase/SearchRepository.php b/src/Core/Usecase/SearchRepository.php index 8049acb6a7..13addab271 100644 --- a/src/Core/Usecase/SearchRepository.php +++ b/src/Core/Usecase/SearchRepository.php @@ -20,7 +20,7 @@ interface SearchRepository * @param Array $data * @return Entity */ - public function getEntity(Array $data = null); + public function getEntity(array $data = null); /** * Get fields that can be used for searches. diff --git a/src/Core/Usecase/Set/VerifySetExists.php b/src/Core/Usecase/Set/VerifySetExists.php index 206e9fae25..fc7ef4d010 100644 --- a/src/Core/Usecase/Set/VerifySetExists.php +++ b/src/Core/Usecase/Set/VerifySetExists.php @@ -13,7 +13,7 @@ use Ushahidi\Core\Entity; -trait verifySetExists +trait VerifySetExists { /** diff --git a/src/Factory/AuthorizerFactory.php b/src/Factory/AuthorizerFactory.php index bd56d292a7..4e7a585492 100644 --- a/src/Factory/AuthorizerFactory.php +++ b/src/Factory/AuthorizerFactory.php @@ -26,7 +26,7 @@ class AuthorizerFactory /** * @param Array $map */ - public function __construct(Array $map) + public function __construct(array $map) { $this->map = $map; } diff --git a/src/Factory/DataFactory.php b/src/Factory/DataFactory.php index 400e8e9763..33b0efff66 100644 --- a/src/Factory/DataFactory.php +++ b/src/Factory/DataFactory.php @@ -28,7 +28,7 @@ class DataFactory /** * @param Array $actions */ - public function __construct(Array $actions) + public function __construct(array $actions) { $this->actions = $actions; } @@ -42,7 +42,7 @@ public function __construct(Array $actions) * @param Array $params * @return Ushahidi\Core\Data */ - public function get($action, Array $params = null) + public function get($action, array $params = null) { if (empty($this->actions[$action])) { throw new \InvalidArgumentException(sprintf( diff --git a/src/Factory/FormatterFactory.php b/src/Factory/FormatterFactory.php index 0653929472..05121f0969 100644 --- a/src/Factory/FormatterFactory.php +++ b/src/Factory/FormatterFactory.php @@ -40,8 +40,8 @@ class FormatterFactory * @param Closure $factory */ public function __construct( - Array $map, - Array $collections, + array $map, + array $collections, $factory ) { $this->map = $map; diff --git a/src/Factory/RepositoryFactory.php b/src/Factory/RepositoryFactory.php index 8119e06628..f0100b7900 100644 --- a/src/Factory/RepositoryFactory.php +++ b/src/Factory/RepositoryFactory.php @@ -26,7 +26,7 @@ class RepositoryFactory /** * @param Array $map */ - public function __construct(Array $map) + public function __construct(array $map) { $this->map = $map; } diff --git a/src/Factory/UsecaseFactory.php b/src/Factory/UsecaseFactory.php index cb659540d7..b820fc2539 100644 --- a/src/Factory/UsecaseFactory.php +++ b/src/Factory/UsecaseFactory.php @@ -68,8 +68,8 @@ public function __construct( FormatterFactory $formatters, RepositoryFactory $repositories, ValidatorFactory $validators, - Array $actions, - Array $map + array $actions, + array $map ) { $this->authorizers = $authorizers; $this->data = $data; diff --git a/src/Factory/ValidatorFactory.php b/src/Factory/ValidatorFactory.php index 55adbc7331..70fcb507cc 100644 --- a/src/Factory/ValidatorFactory.php +++ b/src/Factory/ValidatorFactory.php @@ -27,7 +27,7 @@ class ValidatorFactory /** * @param Array $map */ - public function __construct(Array $map) + public function __construct(array $map) { $this->map = $map; } diff --git a/src/ruleset.xml b/src/ruleset.xml new file mode 100644 index 0000000000..5310434f9c --- /dev/null +++ b/src/ruleset.xml @@ -0,0 +1,9 @@ + + + Ushahidi uses PSR2 with tabs instead of spaces + + + + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 711a59a8ca..8ac9cf8120 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,5 @@ 0) - { + if ($ob_len > 0) { ob_end_flush(); - } - else - { + } else { ob_end_clean(); } } diff --git a/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml index e72e69a85f..5edd3f86cf 100644 --- a/tests/datasets/ushahidi/Base.yml +++ b/tests/datasets/ushahidi/Base.yml @@ -110,36 +110,43 @@ form_stages: form_id: 1 label: "Main" show_when_published: 1 + type: "post" - id: 2 form_id: 1 label: "2nd step" show_when_published: 1 + type: "task" - id: 3 form_id: 1 label: "3rd step" show_when_published: 1 + type: "task" - id: 4 form_id: 2 label: "Main" show_when_published: 1 + type: "post" - id: 5 form_id: 3 label: "Post" show_when_published: 1 + type: "post" - id: 6 form_id: 4 label: "restricted" show_when_published: 0 + type: "task" - id: 7 form_id: 4 label: "Post" show_when_published: 1 + type: "post" form_attributes: - id: 1 @@ -441,6 +448,54 @@ form_attributes: options: "" cardinality: 1 form_stage_id: 1 + - + id: 26 + label: "Categories" + key: "tags1" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: '["1","2","3","4","5","6","7"]' + cardinality: 0 + form_stage_id: 1 + - + id: 27 + label: "Categories" + key: "tags2" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: '["1","2","3","5"]' + cardinality: 0 + form_stage_id: 4 + - + id: 28 + label: "Categories" + key: "tags3" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: '["1","2","3","5","6","7"]' + cardinality: 0 + form_stage_id: 5 + - + id: 29 + label: "Categories" + key: "tags4" + type: "tags" + input: "tags" + response_private: 0 + required: 0 + priority: 3 + options: '["1","2","3","4","5","6","7"]' + cardinality: 0 + form_stage_id: 7 posts: - id: 1 @@ -950,12 +1005,15 @@ posts_tags: - post_id: 1 tag_id: 4 + form_attribute_id: 26 - post_id: 1 tag_id: 3 + form_attribute_id: 26 - post_id: 99 tag_id: 3 + form_attribute_id: 26 form_stages_posts: - form_stage_id: 1 diff --git a/tests/integration/acl.feature b/tests/integration/acl.feature index 24cdb97dbe..3717044930 100644 --- a/tests/integration/acl.feature +++ b/tests/integration/acl.feature @@ -168,7 +168,7 @@ Feature: API Access Control Layer Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "7" + And the "count" property equals "8" Then the guzzle status code should be 200 Scenario: Listing All Attributes for a form with hidden stages with edit permission @@ -178,7 +178,7 @@ Feature: API Access Control Layer Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "7" + And the "count" property equals "8" Then the guzzle status code should be 200 Scenario: User can see hidden tasks of posts published when survey restricted to their role diff --git a/tests/integration/bootstrap/FeatureContext.php b/tests/integration/bootstrap/FeatureContext.php index ed454e395f..ed2edc7999 100644 --- a/tests/integration/bootstrap/FeatureContext.php +++ b/tests/integration/bootstrap/FeatureContext.php @@ -9,8 +9,7 @@ * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) */ -// Load bootstrap to hook into Kohana -require_once __DIR__.'/../../bootstrap.php'; +namespace Tests\Integration\Bootstrap; use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; @@ -23,63 +22,62 @@ class FeatureContext implements SnippetAcceptingContext /** @BeforeScenario @private */ public function makePrivate() { - $config = Kohana::$config->load('site'); + $config = \Kohana::$config->load('site'); $config->set('private', true); - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('private.enabled', true); } /** @AfterScenario @private */ public function makePublic() { - $config = Kohana::$config->load('site'); + $config = \Kohana::$config->load('site'); $config->set('private', false); - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('private.enabled', false); } /** @BeforeScenario @rolesEnabled */ public function enableRoles() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('roles.enabled', true); } /** @AfterScenario @rolesEnabled */ public function disableRoles() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('roles.enabled', false); } /** @BeforeScenario @webhooksEnabled */ public function enableWebhooks() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('webhooks.enabled', true); } /** @AfterScenario @webhooksEnabled */ public function disableWebhooks() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('webhooks.enabled', false); } /** @BeforeScenario @dataImportEnabled */ public function enableDataImport() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('data-import.enabled', true); } /** @AfterScenario @dataImportEnabled */ public function disableDataImport() { - $config = Kohana::$config->load('features'); + $config = \Kohana::$config->load('features'); $config->set('data-import.enabled', false); } - } diff --git a/tests/integration/bootstrap/KohanaContext.php b/tests/integration/bootstrap/KohanaContext.php new file mode 100644 index 0000000000..d7cbbc4456 --- /dev/null +++ b/tests/integration/bootstrap/KohanaContext.php @@ -0,0 +1,16 @@ +getSession()->getCurrentUrl(); - if (!preg_match($pattern, $actual)) - { + if (!preg_match($pattern, $actual)) { $message = sprintf('Current page "%s" does not match the regex "%s".', $actual, $pattern); throw new Exception($message); } @@ -33,13 +35,13 @@ public function assertFullUrlRegExp($pattern) public function canIntercept() { $driver = $this->getSession()->getDriver(); - if (!$driver instanceof GoutteDriver) - { + if (!$driver instanceof GoutteDriver) { throw new UnsupportedDriverActionException( 'You need to tag the scenario with ' . '"@mink:goutte" or "@mink:symfony". ' . 'Intercepting the redirections is not ' . - 'supported by %s', $driver + 'supported by %s', + $driver ); } } @@ -89,8 +91,7 @@ public function redirectLocationShouldMatch($pattern) $pattern = $this->fixStepArgument($pattern); - if (!preg_match($pattern, $actual)) - { + if (!preg_match($pattern, $actual)) { $message = sprintf('Redirect location "%s" does not match the regex "%s".', $actual, $pattern); throw new Exception($message); } @@ -103,5 +104,4 @@ public function iShouldHaveCookie($cookie) { $this->assertSession()->cookieExists($cookie); } - } diff --git a/tests/integration/bootstrap/PHPUnitFixtureContext.php b/tests/integration/bootstrap/PHPUnitFixtureContext.php index 4ff84132f2..9ac234faef 100644 --- a/tests/integration/bootstrap/PHPUnitFixtureContext.php +++ b/tests/integration/bootstrap/PHPUnitFixtureContext.php @@ -1,22 +1,25 @@ setUpDBTester('ushahidi/Base'); @@ -24,7 +27,7 @@ public static function featureSetup(Behat\Behat\Hook\Scope\BeforeFeatureScope $s } /** @AfterFeature */ - public static function featureTearDown(Behat\Behat\Hook\Scope\AfterFeatureScope $scope) + public static function featureTearDown(\Behat\Behat\Hook\Scope\AfterFeatureScope $scope) { $fixtureContext = new static(); $fixtureContext->tearDownDBTester('ushahidi/Base'); @@ -71,10 +74,9 @@ protected function insertGeometryFixtures() public function getConnection() { // Get the unittesting db connection - $config = Kohana::$config->load('database.'.$this->_database_connection); + $config = \Kohana::$config->load('database.'.$this->database_connection); - if($config['type'] !== 'pdo') - { + if ($config['type'] !== 'pdo') { // Replace MySQLi with MySQL since MySQLi isn't valid for a DSN $type = $config['type'] === 'MySQLi' ? 'MySQL' : $config['type']; @@ -83,7 +85,7 @@ public function getConnection() 'dbname='.$config['connection']['database']; } - $pdo = new PDO( + $pdo = new \PDO( $config['connection']['dsn'], $config['connection']['username'], $config['connection']['password'] @@ -100,7 +102,7 @@ public function getConnection() */ protected function getDataSet($dataset) { - return new PHPUnit_Extensions_Database_DataSet_YamlDataSet( + return new \PHPUnit_Extensions_Database_DataSet_YamlDataSet( __DIR__ . '/../../datasets/' . $dataset . '.yml' ); } @@ -110,7 +112,7 @@ protected function getDataSet($dataset) /** Call this in a BeforeScenario hook */ public function setUpDBTester($dataset) { - $this->_databaseTester = NULL; + $this->databaseTester = null; $this->getDatabaseTester()->setSetUpOperation($this->getSetUpOperation()); $this->getDatabaseTester()->setDataSet($this->getDataSet($dataset)); @@ -128,7 +130,7 @@ public function tearDownDBTester($dataset) * Destroy the tester after the test is run to keep DB connections * from piling up. */ - $this->_databaseTester = NULL; + $this->databaseTester = null; } /** @@ -140,11 +142,10 @@ public function tearDownDBTester($dataset) */ protected function getDatabaseTester() { - if (empty($this->_databaseTester)) - { - $this->_databaseTester = $this->newDatabaseTester(); + if (empty($this->databaseTester)) { + $this->databaseTester = $this->newDatabaseTester(); } - return $this->_databaseTester; + return $this->databaseTester; } /** @@ -154,7 +155,7 @@ protected function getDatabaseTester() */ protected function newDatabaseTester() { - return new PHPUnit_Extensions_Database_DefaultTester($this->getConnection()); + return new \PHPUnit_Extensions_Database_DefaultTester($this->getConnection()); } /** @@ -166,10 +167,10 @@ protected function newDatabaseTester() protected function getSetUpOperation() { //return PHPUnit_Extensions_Database_Operation_Factory::CLEAN_INSERT(); - $cascadeTruncates = TRUE; - return new PHPUnit_Extensions_Database_Operation_Composite(array( - new Unittest_Database_Operation_MySQL55Truncate($cascadeTruncates), - PHPUnit_Extensions_Database_Operation_Factory::INSERT() + $cascadeTruncates = true; + return new \PHPUnit_Extensions_Database_Operation_Composite(array( + new \Unittest_Database_Operation_MySQL55Truncate($cascadeTruncates), + \PHPUnit_Extensions_Database_Operation_Factory::INSERT() )); } @@ -180,7 +181,7 @@ protected function getSetUpOperation() */ protected function getTearDownOperation() { - return PHPUnit_Extensions_Database_Operation_Factory::NONE(); + return \PHPUnit_Extensions_Database_Operation_Factory::NONE(); } /** @@ -191,9 +192,8 @@ protected function getTearDownOperation() * @param string $schema * @return PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection */ - protected function createDefaultDBConnection(PDO $connection, $schema = '') + protected function createDefaultDBConnection(\PDO $connection, $schema = '') { - return new PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection($connection, $schema); + return new \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection($connection, $schema); } - } diff --git a/tests/integration/bootstrap/RestContext.php b/tests/integration/bootstrap/RestContext.php index 18a3be7cd5..d1d3e6b6d0 100644 --- a/tests/integration/bootstrap/RestContext.php +++ b/tests/integration/bootstrap/RestContext.php @@ -1,5 +1,7 @@ _restObject = new stdClass(); + $this->restObject = new stdClass(); $options = array(); - if($proxyUrl) - { + if ($proxyUrl) { $options['curl.options'] = array(CURLOPT_PROXY => $proxyUrl); } - $this->_client = new Guzzle\Service\Client($baseUrl, $options); + $this->client = new \Guzzle\Service\Client($baseUrl, $options); } /** @@ -62,11 +64,11 @@ public function setDefaultBearerAuth() */ public function thatIWantToMakeANew($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'post'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'post'; } /** @@ -74,11 +76,11 @@ public function thatIWantToMakeANew($objectType) */ public function thatIWantToImportA($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'post'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'post'; } @@ -87,11 +89,11 @@ public function thatIWantToImportA($objectType) */ public function thatIWantToSubmitANew($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'post'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'post'; } /** @@ -100,11 +102,11 @@ public function thatIWantToSubmitANew($objectType) */ public function thatIWantToUpdateA($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'put'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'put'; } /** @@ -113,11 +115,11 @@ public function thatIWantToUpdateA($objectType) */ public function thatIWantToFindA($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'get'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'get'; } /** @@ -125,11 +127,11 @@ public function thatIWantToFindA($objectType) */ public function thatIWantToGetAll($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'get'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'get'; } /** @@ -138,11 +140,11 @@ public function thatIWantToGetAll($objectType) */ public function thatIWantToDeleteA($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'delete'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'delete'; } /** @@ -152,7 +154,7 @@ public function thatIWantToDeleteA($objectType) */ public function thatTheRequestPropertyIs($propertyName, $propertyValue) { - $this->_restObject->$propertyName = $propertyValue; + $this->restObject->$propertyName = $propertyValue; } /** @@ -161,7 +163,7 @@ public function thatTheRequestPropertyIs($propertyName, $propertyValue) */ public function thatTheRequestHeaderIs($headerName, $headerValue) { - $this->_headers[$headerName] = $headerValue; + $this->headers[$headerName] = $headerValue; } /** @@ -169,7 +171,7 @@ public function thatTheRequestHeaderIs($headerName, $headerValue) */ public function thatTheResponseHeaderIs($headerName, $headerValue) { - $this->_headers[$headerName] = $headerValue; + $this->headers[$headerName] = $headerValue; } /** @@ -178,7 +180,7 @@ public function thatTheResponseHeaderIs($headerName, $headerValue) */ public function thatThePostFieldIs($fieldName, $fieldValue) { - $this->_postFields[$fieldName] = $fieldValue; + $this->postFields[$fieldName] = $fieldValue; } /** @@ -187,7 +189,7 @@ public function thatThePostFieldIs($fieldName, $fieldValue) */ public function thatThePostFileIs($fieldName, $fieldValue) { - $this->_postFiles[$fieldName] = $fieldValue; + $this->postFiles[$fieldName] = $fieldValue; } /** @@ -195,71 +197,66 @@ public function thatThePostFileIs($fieldName, $fieldValue) */ public function iRequest($pageUrl) { - $this->_requestUrl = $this->_apiUrl.$pageUrl; + $this->requestUrl = $this->apiUrl.$pageUrl; - switch (strtoupper($this->_restObjectMethod)) { + switch (strtoupper($this->restObjectMethod)) { case 'GET': - $request = (array)$this->_restObject; + $request = (array)$this->restObject; $id = ( isset($request['id']) ) ? $request['id'] : ''; - $http_request = $this->_client - ->get($this->_requestUrl.'/'.$id); + $http_request = $this->client + ->get($this->requestUrl.'/'.$id); - if (isset($request['query string'])) - { - $url = $http_request->getUrl(TRUE); + if (isset($request['query string'])) { + $url = $http_request->getUrl(true); $url->setQuery((string) trim($request['query string'])); $http_request->setUrl($url); } break; case 'POST': - $request = (array)$this->_restObject; + $request = (array)$this->restObject; // If post fields or files are set assume this is a 'normal' POST request - if ($this->_postFields OR $this->_postFiles) - { - $http_request = $this->_client - ->post($this->_requestUrl) - ->addPostFields($this->_postFields) - ->addPostFiles($this->_preparePostFileData($this->_postFiles)); - } - // Otherwise assume we have JSON - else - { - $http_request = $this->_client - ->post($this->_requestUrl) + if ($this->postFields or $this->postFiles) { + $http_request = $this->client + ->post($this->requestUrl) + ->addPostFields($this->postFields) + ->addPostFiles($this->preparePostFileData($this->postFiles)); + } // Otherwise assume we have JSON + else { + $http_request = $this->client + ->post($this->requestUrl) ->setBody($request['data']); } break; case 'PUT': - $request = (array)$this->_restObject; + $request = (array)$this->restObject; $id = ( isset($request['id']) ) ? $request['id'] : ''; - $http_request = $this->_client - ->put($this->_requestUrl.'/'.$id) + $http_request = $this->client + ->put($this->requestUrl.'/'.$id) ->setBody($request['data']); break; case 'DELETE': - $request = (array)$this->_restObject; + $request = (array)$this->restObject; $id = ( isset($request['id']) ) ? $request['id'] : ''; - $http_request = $this->_client - ->delete($this->_requestUrl.'/'.$id); + $http_request = $this->client + ->delete($this->requestUrl.'/'.$id); break; } try { $http_request - ->addHeaders($this->_headers) + ->addHeaders($this->headers) ->send(); - } catch (Guzzle\Http\Exception\BadResponseException $e) { + } catch (\Guzzle\Http\Exception\BadResponseException $e) { // Don't care. // 4xx and 5xx statuses are valid error responses } // Get response object - $this->_response = $http_request->getResponse(); + $this->response = $http_request->getResponse(); // Create fake response object if Guzzle doesn't give us one - if (! $this->_response instanceof Guzzle\Http\Message\Response) - { - $this->_response = new Guzzle\Http\Message\Response(null, null, null); + if (! $this->response instanceof \Guzzle\Http\Message\Response) { + $this->response = new \Guzzle\Http\Message\Response(null, null, null); } } @@ -268,37 +265,38 @@ public function iRequest($pageUrl) */ public function theResponseIsJson() { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); // Check for NULL not empty - since [] and {} will be empty but valid - if ($data === NULL) { - + if ($data === null) { // Get further error info switch (json_last_error()) { case JSON_ERROR_NONE: $error = 'No errors'; - break; + break; case JSON_ERROR_DEPTH: $error = 'Maximum stack depth exceeded'; - break; + break; case JSON_ERROR_STATE_MISMATCH: $error = 'Underflow or the modes mismatch'; - break; + break; case JSON_ERROR_CTRL_CHAR: $error = 'Unexpected control character found'; - break; + break; case JSON_ERROR_SYNTAX: $error = 'Syntax error, malformed JSON'; - break; + break; case JSON_ERROR_UTF8: $error = 'Malformed UTF-8 characters, possibly incorrectly encoded'; - break; + break; default: $error = 'Unknown error'; - break; + break; } - throw new Exception("Response was not JSON\nBody:" . $this->_response->getBody(TRUE) . "\nError: " . $error ); + throw new \Exception( + "Response was not JSON\nBody:" . $this->response->getBody(true) . "\nError: " . $error + ); } } @@ -307,43 +305,44 @@ public function theResponseIsJson() */ public function theResponseIsJsonp() { - $result = preg_match('/^.+\(({.+})\)$/', $this->_response->getBody(TRUE), $matches); + $result = preg_match('/^.+\(({.+})\)$/', $this->response->getBody(true), $matches); - if ($result != 1 OR empty($matches[1])) - { - throw new Exception("Response was not JSONP\nBody:" . $this->_response->getBody(TRUE)); + if ($result != 1 or empty($matches[1])) { + throw new \Exception("Response was not JSONP\nBody:" . $this->response->getBody(true)); } $data = json_decode($matches[1]); // Check for NULL not empty - since [] and {} will be empty but valid - if ($data === NULL) { + if ($data === null) { // Get further error info switch (json_last_error()) { case JSON_ERROR_NONE: $error = 'No errors'; - break; + break; case JSON_ERROR_DEPTH: $error = 'Maximum stack depth exceeded'; - break; + break; case JSON_ERROR_STATE_MISMATCH: $error = 'Underflow or the modes mismatch'; - break; + break; case JSON_ERROR_CTRL_CHAR: $error = 'Unexpected control character found'; - break; + break; case JSON_ERROR_SYNTAX: $error = 'Syntax error, malformed JSON'; - break; + break; case JSON_ERROR_UTF8: $error = 'Malformed UTF-8 characters, possibly incorrectly encoded'; - break; + break; default: $error = 'Unknown error'; - break; + break; } - throw new Exception("Response was not JSONP\nBody:" . $this->_response->getBody(TRUE) . "\nError: " . $error ); + throw new \Exception( + "Response was not JSONP\nBody:" . $this->response->getBody(true) . "\nError: " . $error + ); } } @@ -353,12 +352,12 @@ public function theResponseIsJsonp() */ public function theResponseHasAProperty($propertyName) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - if (Arr::path($data, $propertyName) === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if (\Arr::path($data, $propertyName) === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } } @@ -368,12 +367,12 @@ public function theResponseHasAProperty($propertyName) */ public function theResponseDoesNotHaveAProperty($propertyName) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - if (Arr::path($data, $propertyName) !== NULL) { - throw new Exception("Property '".$propertyName."' is set but should not be!\n"); + if (\Arr::path($data, $propertyName) !== null) { + throw new \Exception("Property '".$propertyName."' is set but should not be!\n"); } } @@ -382,18 +381,22 @@ public function theResponseDoesNotHaveAProperty($propertyName) */ public function thePropertyEquals($propertyName, $propertyValue) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if ($actualPropertyValue === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } - // Check the value - note this has to use != since $propertValue is always a string so strict comparison would fail. + // Check the value - note this has to use != since $propertValue + // is always a string so strict comparison would fail. if ($actualPropertyValue != $propertyValue) { - throw new \Exception('Property value mismatch on \''.$propertyName.'\'! (given: '.$propertyValue.', match: '.$actualPropertyValue.')'); + throw new \Exception( + "Property value mismatch on '" . $propertyName . "'! ". + "(given: " . $propertyValue . ", match: " . $actualPropertyValue . ")" + ); } } @@ -402,16 +405,16 @@ public function thePropertyEquals($propertyName, $propertyValue) */ public function thePropertyIsTrue($propertyName) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if ($actualPropertyValue === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } - if ($actualPropertyValue !== TRUE) { + if ($actualPropertyValue !== true) { throw new \Exception('Property \''.$propertyName.'\' is not true! (match: '.$actualPropertyValue.')'); } } @@ -421,16 +424,16 @@ public function thePropertyIsTrue($propertyName) */ public function thePropertyIsFalse($propertyName) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if ($actualPropertyValue === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } - if ($actualPropertyValue !== FALSE) { + if ($actualPropertyValue !== false) { throw new \Exception('Property \''.$propertyName.'\' is not false! (match: '.$actualPropertyValue.')'); } } @@ -441,26 +444,63 @@ public function thePropertyIsFalse($propertyName) public function thePropertyContains($propertyName, $propertyContainsValue) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { + if ($actualPropertyValue === null) { throw new Exception("Property '".$propertyName."' is not set!\n"); } - if (is_array($actualPropertyValue) AND ! in_array($propertyContainsValue, $actualPropertyValue)) { - throw new \Exception('Property \''.$propertyName.'\' does not contain value! (given: '.$propertyContainsValue.', match: '.json_encode($actualPropertyValue).')'); + if (is_array($actualPropertyValue) and ! in_array($propertyContainsValue, $actualPropertyValue)) { + throw new \Exception( + 'Property \''.$propertyName.'\' does not contain value!' . + '(given: '.$propertyContainsValue.', match: '.json_encode($actualPropertyValue).')' + ); + } elseif (is_string($actualPropertyValue) and strpos($actualPropertyValue, $propertyContainsValue) === false) { + throw new \Exception( + 'Property \''.$propertyName.'\' does not contain value!' . + '(given: '.$propertyContainsValue.', match: '.$actualPropertyValue.')' + ); + } elseif (!is_array($actualPropertyValue) and !is_string($actualPropertyValue)) { + throw new \Exception( + "Property '".$propertyName."' could not be compared. Must be string or array.\n" + ); } - elseif (is_string($actualPropertyValue) AND strpos($actualPropertyValue, $propertyContainsValue) === FALSE) - { - throw new \Exception('Property \''.$propertyName.'\' does not contain value! (given: '.$propertyContainsValue.', match: '.$actualPropertyValue.')'); + } + + /** + * @Given /^the "([^"]*)" property does not contain "([^"]*)"$/ + */ + public function thePropertyDoesNotContains($propertyName, $propertyContainsValue) + { + + $data = json_decode($this->response->getBody(true), true); + + $this->theResponseIsJson(); + + $actualPropertyValue = \Arr::path($data, $propertyName); + + if ($actualPropertyValue === null) { + throw new Exception("Property '".$propertyName."' is not set!\n"); } - elseif (!is_array($actualPropertyValue) AND !is_string($actualPropertyValue)) - { - throw new \Exception("Property '".$propertyName."' could not be compared. Must be string or array.\n"); + + if (is_array($actualPropertyValue) and in_array($propertyContainsValue, $actualPropertyValue)) { + throw new \Exception( + 'Property \''.$propertyName.'\' contains value!' . + '(given: '.$propertyContainsValue.', match: '.json_encode($actualPropertyValue).')' + ); + } elseif (is_string($actualPropertyValue) and strpos($actualPropertyValue, $propertyContainsValue) !== false) { + throw new \Exception( + 'Property \''.$propertyName.'\' does not contain value!' . + '(given: '.$propertyContainsValue.', match: '.$actualPropertyValue.')' + ); + } elseif (!is_array($actualPropertyValue) and !is_string($actualPropertyValue)) { + throw new \Exception( + "Property '".$propertyName."' could not be compared. Must be string or array.\n" + ); } } @@ -470,21 +510,22 @@ public function thePropertyContains($propertyName, $propertyContainsValue) public function thePropertyCountIs($propertyName, $propertyCountValue) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if ($actualPropertyValue === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } - if (is_array($actualPropertyValue) AND count($actualPropertyValue) != $propertyCountValue) { - throw new \Exception('Property \''.$propertyName.'\' count does not match! (given: '.$propertyCountValue.', match: '.count($actualPropertyValue).')'); - } - elseif (!is_array($actualPropertyValue)) - { + if (is_array($actualPropertyValue) and count($actualPropertyValue) != $propertyCountValue) { + throw new \Exception( + 'Property \''.$propertyName.'\' count does not match!' . + '(given: '.$propertyCountValue.', match: '.count($actualPropertyValue).')' + ); + } elseif (!is_array($actualPropertyValue)) { throw new \Exception("Property '".$propertyName."' could not be compared. Must be an array.\n"); } } @@ -494,20 +535,20 @@ public function thePropertyCountIs($propertyName, $propertyCountValue) */ public function theTypeOfThePropertyIs($propertyName, $typeString) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); - if ($actualPropertyValue === NULL) { - throw new Exception("Property '".$propertyName."' is not set!\n"); + if ($actualPropertyValue === null) { + throw new \Exception("Property '".$propertyName."' is not set!\n"); } // check our type switch (strtolower($typeString)) { case 'numeric': if (!is_numeric($actualPropertyValue)) { - throw new Exception("Property '".$propertyName."' is not of the correct type: ".$typeString."!\n"); + throw new \Exception("Property '".$propertyName."' is not of the correct type: ".$typeString."!\n"); } break; } @@ -518,14 +559,14 @@ public function theTypeOfThePropertyIs($propertyName, $typeString) */ public function thePropertyIsEmpty($propertyName) { - $data = json_decode($this->_response->getBody(TRUE), TRUE); + $data = json_decode($this->response->getBody(true), true); $this->theResponseIsJson(); - $actualPropertyValue = Arr::path($data, $propertyName); + $actualPropertyValue = \Arr::path($data, $propertyName); if (!empty($actualPropertyValue)) { - throw new Exception("Property '{$propertyName}' is not empty!\n"); + throw new \Exception("Property '{$propertyName}' is not empty!\n"); } } @@ -534,9 +575,9 @@ public function thePropertyIsEmpty($propertyName) */ public function theRestResponseStatusCodeShouldBe($httpStatus) { - if ((string)$this->_response->getStatusCode() !== $httpStatus) { + if ((string)$this->response->getStatusCode() !== $httpStatus) { throw new \Exception('HTTP code does not match '.$httpStatus. - ' (actual: '.$this->_response->getStatusCode().')'); + ' (actual: '.$this->response->getStatusCode().')'); } } @@ -545,8 +586,8 @@ public function theRestResponseStatusCodeShouldBe($httpStatus) */ public function theRestHeaderShouldExist($header) { - if (!$this->_response->hasHeader($header)) { - throw new \Exception('HTTP header does not exist '.$header ); + if (!$this->response->hasHeader($header)) { + throw new \Exception('HTTP header does not exist '.$header); } } @@ -555,9 +596,9 @@ public function theRestHeaderShouldExist($header) */ public function theRestHeaderShouldExistBe($header, $contents) { - if ((string)$this->_response->getHeader($header) !== $contents) { + if ((string)$this->response->getHeader($header) !== $contents) { throw new \Exception('HTTP header ' . $header . ' does not match '.$contents. - ' (actual: '.$this->_response->getHeader($header).')'); + ' (actual: '.$this->response->getHeader($header).')'); } } @@ -568,8 +609,8 @@ public function theRestHeaderShouldExistBe($header, $contents) public function echoLastResponse() { var_dump( - $this->_requestUrl."\n\n". - $this->_response + $this->requestUrl."\n\n". + $this->response ); } @@ -578,27 +619,25 @@ public function echoLastResponse() */ public function thatTheApiUrlIs($api_url) { - $this->_apiUrl = $api_url; + $this->apiUrl = $api_url; } /** * @AfterScenario */ - public function afterScenarioCheckError(Behat\Behat\Hook\Scope\AfterScenarioScope $scope) + public function afterScenarioCheckError(\Behat\Behat\Hook\Scope\AfterScenarioScope $scope) { // If scenario failed, dump response - if (!$scope->getTestResult()->isPassed() AND $this->_response) - { + if (!$scope->getTestResult()->isPassed() and $this->response) { $this->echoLastResponse(); } } - private function _preparePostFileData($postFiles) + private function preparePostFileData($postFiles) { //Check if post files is not empty - if ( count($postFiles) > 0) - { - array_walk_recursive($postFiles, array($this, '_prefix_app_path')); + if (count($postFiles) > 0) { + array_walk_recursive($postFiles, array($this, 'prefixAppPath')); return $postFiles; } return $postFiles; @@ -610,7 +649,7 @@ private function _preparePostFileData($postFiles) * @param string $item the path to the file to be uploaded * @return string path to application folder */ - private function _prefix_app_path(&$item) + private function prefixAppPath(&$item) { $item = DOCROOT.$item; } @@ -620,11 +659,10 @@ private function _prefix_app_path(&$item) */ public function thatIWantToCountAll($objectType) { - // Reset _restObject - $this->_restObject = new stdClass(); + // Reset restObject + $this->restObject = new stdClass(); - $this->_restObjectType = ucwords(strtolower($objectType)); - $this->_restObjectMethod = 'get'; + $this->restObjectType = ucwords(strtolower($objectType)); + $this->restObjectMethod = 'get'; } - } diff --git a/tests/integration/forms.feature b/tests/integration/forms.feature index dee814ba00..e2285a3003 100644 --- a/tests/integration/forms.feature +++ b/tests/integration/forms.feature @@ -35,7 +35,8 @@ Feature: Testing the Forms API "description":"This is a test form updated by BDD testing", "disabled":true, "require_approval":false, - "everyone_can_create":false + "everyone_can_create":false, + "tags": [1,2,3,"junk"] } """ And that its "id" is "1" @@ -142,6 +143,15 @@ Feature: Testing the Forms API Then the guzzle status code should be 200 Scenario: Finding a Form after roles have been set. + Given that I want to update a "FormRole" + And that the request "data" is: + """ + { + "roles": [1,2] + } + """ + When I request "/forms/1/roles" + Then the response is JSON Given that I want to find a "Form" And that its "id" is "1" When I request "/forms" diff --git a/tests/integration/forms/attributes.feature b/tests/integration/forms/attributes.feature index a1ed03473c..b9d656875c 100644 --- a/tests/integration/forms/attributes.feature +++ b/tests/integration/forms/attributes.feature @@ -169,22 +169,24 @@ Feature: Testing the Form Attributes API And the response has a "errors" property Then the guzzle status code should be 404 + @resetFixture Scenario: Listing All Attributes for a form Given that I want to get all "Attributes" When I request "/forms/1/attributes" Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "19" + And the "count" property equals "18" Then the guzzle status code should be 200 - Scenario: Listing All Attributes + @resetFixture + Scenario: Listing All Attributes Given that I want to get all "Attributes" When I request "/forms/attributes" Then the response is JSON And the response has a "count" property And the type of the "count" property is "numeric" - And the "count" property equals "27" + And the "count" property equals "29" Then the guzzle status code should be 200 Scenario: Search for point attributes diff --git a/tests/integration/posts.feature b/tests/integration/posts.feature index 8229bd876b..3f4458127d 100644 --- a/tests/integration/posts.feature +++ b/tests/integration/posts.feature @@ -31,9 +31,9 @@ Feature: Testing the Posts API "links":[ "http://google.com", "http://facebook.com" - ] + ], + "tags1": [1] }, - "tags":["explosion"], "completed_stages":[1] } """ @@ -80,9 +80,9 @@ Feature: Testing the Posts API "links":[ "http://google.com", "http://facebook.com" - ] + ], + "tags1": ["explosion"] }, - "tags":["explosion"], "completed_stages":[1] } """ @@ -512,6 +512,79 @@ Feature: Testing the Posts API And the "values.last_location_point.0.lon" property equals "-85.39" Then the guzzle status code should be 200 + @update + Scenario: Updating a post and remove some values + Given that I want to update a "Post" + And that the request "data" is: + """ + { + "form":1, + "title":"Update 1", + "type":"report", + "status":"published", + "locale":"en_US", + "values": + { + "full_name":["David Kobia"], + "description":["Skinny, homeless Kenyan last seen in the vicinity of the greyhound station"], + "date_of_birth":[], + "missing_date":["2012/09/25"], + "last_location":["atlanta"], + "last_location_point":[ + { + "lat": 33.755, + "lon": -85.39 + } + ], + "missing_status":["believed_missing"], + "links":[ + "abc123", + "def456" + ] + } + } + """ + And that its "id" is "1" + When I request "/posts" + Then the response is JSON + And the response has a "id" property + # Update 2 + Given that I want to update a "Post" + And that the request "data" is: + """ + { + "form":1, + "title":"Update 2", + "type":"report", + "status":"published", + "locale":"en_US", + "values": + { + "full_name":["David Kobia"], + "description":["Skinny, homeless Kenyan last seen in the vicinity of the greyhound station"], + "date_of_birth":[], + "missing_date":["2012/09/25"], + "last_location":["atlanta"], + "last_location_point":[ + { + "lat": 33.755, + "lon": -85.39 + } + ], + "missing_status":["believed_missing"], + "links":[ + "def456" + ] + } + } + """ + And that its "id" is "1" + When I request "/posts" + Then the response is JSON + And the response has a "id" property + And the "values.links" property count is "1" + Then the guzzle status code should be 200 + @update Scenario: Updating a Post to update tags Given that I want to update a "Post" diff --git a/tests/integration/tags.feature b/tests/integration/tags.feature index 3926f56c60..eefcd23fa9 100644 --- a/tests/integration/tags.feature +++ b/tests/integration/tags.feature @@ -267,6 +267,20 @@ Feature: Testing the Tags API When I request "/tags" Then the guzzle status code should be 200 + @resetFixture + Scenario: Deleting a tag removes it from attribute options + Given that I want to delete a "Tag" + And that its "id" is "1" + When I request "/tags" + Then the guzzle status code should be 200 + Given that I want to find a "Attribute" + And that its "id" is "26" + When I request "/forms/1/attributes" + Then the response is JSON + And the response has an "options" property + And the "options" property does not contain "1" + Then the guzzle status code should be 200 + Scenario: Deleting a non-existent Tag Given that I want to delete a "Tag" And that its "id" is "35" diff --git a/tests/spec/ruleset.xml b/tests/spec/ruleset.xml index b63e9a9a20..2d4aeedff0 100644 --- a/tests/spec/ruleset.xml +++ b/tests/spec/ruleset.xml @@ -6,5 +6,6 @@ + - \ No newline at end of file + diff --git a/tests/unit/Core/Traits/DataTranformerTest.php b/tests/unit/Core/Traits/DataTransformerTest.php similarity index 67% rename from tests/unit/Core/Traits/DataTranformerTest.php rename to tests/unit/Core/Traits/DataTransformerTest.php index e5a538206d..833afdc4b8 100644 --- a/tests/unit/Core/Traits/DataTranformerTest.php +++ b/tests/unit/Core/Traits/DataTransformerTest.php @@ -1,4 +1,4 @@ - '*date' - ]; - } - - public function pTransform($data) { - return $this->transform($data); - } -} +namespace Tests\Unit\Core\Traits; /** * @backupGlobals disabled * @preserveGlobalState disabled */ -class DataTransformerTest extends PHPUnit\Framework\TestCase { +class DataTransformerTest extends \PHPUnit\Framework\TestCase +{ /** * Test get method */ - public function test_transformDate() + public function testTransformDate() { - $mock = new mockDataTransformer(); + $mock = new MockDataTransformer(); - $original_date = new DateTime('2014-12-01 11:00', new DateTimeZone('UTC')); + $original_date = new \DateTime('2014-12-01 11:00', new \DateTimeZone('UTC')); $date1 = $mock->pTransform(['date' => $original_date])['date']; $this->assertInstanceOf('DateTimeInterface', $date1); $this->assertNotSame($original_date, $date1); @@ -50,7 +38,6 @@ public function test_transformDate() $date3 = $mock->pTransform(['date' => '2016-10-15T12:18:27+13:00'])['date']; $this->assertInstanceOf('DateTimeInterface', $date3); $this->assertEquals('2016-10-14 23:18:27', $date3->format('Y-m-d H:i:s')); - $this->assertEquals('2016-10-14T23:18:27+00:00', $date3->format(DateTime::W3C)); + $this->assertEquals('2016-10-14T23:18:27+00:00', $date3->format(\DateTime::W3C)); } - } diff --git a/tests/unit/Core/Traits/MockDataTransformer.php b/tests/unit/Core/Traits/MockDataTransformer.php new file mode 100644 index 0000000000..821eafc38c --- /dev/null +++ b/tests/unit/Core/Traits/MockDataTransformer.php @@ -0,0 +1,20 @@ + '*date' + ]; + } + + public function pTransform($data) + { + return $this->transform($data); + } +} diff --git a/tests/unit/Ushahidi/PostValueTest.php b/tests/unit/Ushahidi/PostValueRepositoryTest.php similarity index 85% rename from tests/unit/Ushahidi/PostValueTest.php rename to tests/unit/Ushahidi/PostValueRepositoryTest.php index fb0304f91a..df70ea80a8 100644 --- a/tests/unit/Ushahidi/PostValueTest.php +++ b/tests/unit/Ushahidi/PostValueRepositoryTest.php @@ -1,4 +1,4 @@ -repository = $this->getMockBuilder(Ushahidi_Repository_Post_Value::class) + $this->repository = $this->getMockBuilder(\Ushahidi_Repository_Post_Value::class) ->setMethods(['selectOne', 'selectQuery', 'getTable']) ->disableOriginalConstructor() ->getMock(); - $this->postvalue = $this->createMock(Ushahidi\Core\Entity\PostValue::class); + $this->postvalue = $this->createMock(\Ushahidi\Core\Entity\PostValue::class); } /** * Test get method */ - public function test_get() + public function testGet() { $this->repository->expects($this->any()) ->method('selectOne') @@ -53,7 +56,7 @@ public function test_get() /** * Test get method */ - public function test_getAllForPost() + public function testGetAllForPost() { // Create mocks $mockQueryBuilder = $this->getMockBuilder('Database_Query_Builder_Select') @@ -97,5 +100,4 @@ public function test_getAllForPost() $this->assertCount(3, $values); $this->assertInstanceOf('Ushahidi\Core\Entity\PostValue', current($values)); } - } diff --git a/tests/unit/Util/BoundingBoxTest.php b/tests/unit/Util/BoundingBoxTest.php index 4382b64862..89357c78c0 100644 --- a/tests/unit/Util/BoundingBoxTest.php +++ b/tests/unit/Util/BoundingBoxTest.php @@ -1,4 +1,4 @@ -assertEquals('POLYGON((-180 -90,180 -90,180 90,-180 90,-180 -90))', $bb->toWKT()); @@ -34,7 +39,7 @@ public function test_toWKT() * * @return void */ - public function test_as_array() + public function testAsArray() { $bb = new Util_BoundingBox(-180, -90, 180, 90); $this->assertEquals(array(-180, -90, 180, 90), $bb->as_array()); @@ -48,7 +53,7 @@ public function test_as_array() * * @return void */ - public function test_toGeometry() + public function testToGeometry() { $bb = new Util_BoundingBox(-180, -90, 180, 90); $geom = $bb->toGeometry(); diff --git a/tests/unit/Util/TileTest.php b/tests/unit/Util/TileTest.php index db1b32e731..cd4047a139 100644 --- a/tests/unit/Util/TileTest.php +++ b/tests/unit/Util/TileTest.php @@ -1,4 +1,4 @@ -assertEquals(1, Util_Tile::numTiles(0)); $this->assertEquals(2, Util_Tile::numTiles(1)); @@ -33,7 +38,7 @@ public function test_numTiles() * * @return void */ - public function test_tileToBoundingBox() + public function testTileToBoundingBox() { $bb = Util_Tile::tileToBoundingBox(0, 0, 0); $this->assertAttributeEquals(85.051100, 'north', $bb, '', 0.0002); @@ -65,7 +70,7 @@ public function test_tileToBoundingBox() * * @return void */ - public function test_tileToLon() + public function testTileToLon() { $this->assertEquals(-180, Util_Tile::tileToLon(0, 0), '', 0.0002); $this->assertEquals(0, Util_Tile::tileToLon(1, 1), '', 0.0002); @@ -78,7 +83,7 @@ public function test_tileToLon() * * @return void */ - public function test_tileToLat() + public function testTileToLat() { $this->assertEquals(85.05112, Util_Tile::tileToLat(0, 0), '', 0.0002); $this->assertEquals(0, Util_Tile::tileToLat(1, 1), '', 0.0002);