THRIFT-4423: migrate to psr-4
Client: php

This closes #1445
diff --git a/.gitignore b/.gitignore
index ee6ab9e..fe9be57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -291,6 +291,8 @@
 /ltmain.sh
 /missing
 /node_modules/
+/vendor/
+/composer.lock
 /stamp-h1
 /test/features/results.json
 /test/results.json
diff --git a/build/docker/ubuntu-artful/Dockerfile b/build/docker/ubuntu-artful/Dockerfile
index 831e347..59bbfa9 100644
--- a/build/docker/ubuntu-artful/Dockerfile
+++ b/build/docker/ubuntu-artful/Dockerfile
@@ -24,8 +24,8 @@
 MAINTAINER Apache Thrift <dev@thrift.apache.org>
 ENV DEBIAN_FRONTEND noninteractive
 
-RUN apt-get update && \ 
-    apt-get dist-upgrade -y && \ 
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
     apt-get install -y --no-install-recommends \
       apt \
       apt-transport-https \
@@ -188,7 +188,7 @@
       php-dev \
       php-pear \
       re2c \
-      phpunit
+      composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
diff --git a/build/docker/ubuntu-trusty/Dockerfile b/build/docker/ubuntu-trusty/Dockerfile
index db2041a..394e84f 100644
--- a/build/docker/ubuntu-trusty/Dockerfile
+++ b/build/docker/ubuntu-trusty/Dockerfile
@@ -25,8 +25,8 @@
 MAINTAINER Apache Thrift <dev@thrift.apache.org>
 ENV DEBIAN_FRONTEND noninteractive
 
-RUN apt-get update && \ 
-    apt-get dist-upgrade -y && \ 
+RUN apt-get update && \
+    apt-get dist-upgrade -y && \
     apt-get install -y --no-install-recommends \
       apt \
       apt-transport-https \
@@ -166,8 +166,8 @@
       php5-cli \
       php5-dev \
       php-pear \
-      re2c \
-      phpunit
+      re2c && \
+      wget https://getcomposer.org/installer -O - -q | php -- --quiet --install-dir=/usr/local/bin/ --filename=composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
@@ -189,7 +189,7 @@
       python3-wheel \
       python3-zope.interface && \
     pip install -U ipaddress backports.ssl_match_hostname tornado && \
-    pip3 install -U backports.ssl_match_hostname tornado 
+    pip3 install -U backports.ssl_match_hostname tornado
 # installing tornado by pip/pip3 instead of debian package
 # if we install the debian package, the build fails in py2
 
diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile
index c640bd9..02b5ac2 100644
--- a/build/docker/ubuntu-xenial/Dockerfile
+++ b/build/docker/ubuntu-xenial/Dockerfile
@@ -197,7 +197,7 @@
       php7.0-dev \
       php-pear \
       re2c \
-      phpunit
+      composer
 
 RUN apt-get install -y --no-install-recommends \
 `# Python dependencies` \
diff --git a/composer.json b/composer.json
index ad71f91..c14dd99 100644
--- a/composer.json
+++ b/composer.json
@@ -16,10 +16,16 @@
         "issues": "https://issues.apache.org/jira/browse/THRIFT"
     },
     "require": {
-        "php": ">=5.3.0"
+        "php": ">=5.3.3"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "~4.8.36"
     },
     "autoload": {
-        "psr-0": {"Thrift": "lib/php/lib/"}
+        "psr-4": {"Thrift\\": "lib/php/lib/Thrift/"}
+    },
+    "autoload-dev": {
+        "psr-4": {"Test\\Thrift\\": "lib/php/test/Test/Thrift/"}
     },
     "minimum-stability": "dev",
     "extra": {
diff --git a/configure.ac b/configure.ac
index 073ad8d..bbf53d3 100755
--- a/configure.ac
+++ b/configure.ac
@@ -353,9 +353,6 @@
 fi
 AM_CONDITIONAL(WITH_PHP_EXTENSION, [test "$have_php_extension" = "yes"])
 
-AC_PATH_PROG([PHPUNIT], [phpunit])
-AM_CONDITIONAL(HAVE_PHPUNIT, [test "x$PHPUNIT" != "x"])
-
 AX_THRIFT_LIB(dart, [DART], yes)
 if test "$with_dart" = "yes"; then
   AC_PATH_PROG([DART], [dart])
diff --git a/lib/php/lib/Thrift/StoredMessageProtocol.php b/lib/php/lib/Thrift/StoredMessageProtocol.php
new file mode 100644
index 0000000..476d9a6
--- /dev/null
+++ b/lib/php/lib/Thrift/StoredMessageProtocol.php
@@ -0,0 +1,51 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * @package thrift.processor
+ */
+
+namespace Thrift;
+
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TProtocolDecorator;
+
+/**
+ *  Our goal was to work with any protocol. In order to do that, we needed
+ *  to allow them to call readMessageBegin() and get the Message in exactly
+ *  the standard format, without the service name prepended to the Message name.
+ */
+class StoredMessageProtocol extends TProtocolDecorator
+{
+    private $fname_, $mtype_, $rseqid_;
+
+    public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid)
+    {
+        parent::__construct($protocol);
+        $this->fname_  = $fname;
+        $this->mtype_  = $mtype;
+        $this->rseqid_ = $rseqid;
+    }
+
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        $name  = $this->fname_;
+        $type  = $this->mtype_;
+        $seqid = $this->rseqid_;
+    }
+}
diff --git a/lib/php/lib/Thrift/TMultiplexedProcessor.php b/lib/php/lib/Thrift/TMultiplexedProcessor.php
index 138f95b..0c2094d 100644
--- a/lib/php/lib/Thrift/TMultiplexedProcessor.php
+++ b/lib/php/lib/Thrift/TMultiplexedProcessor.php
@@ -25,7 +25,6 @@
 use Thrift\Exception\TException;
 use Thrift\Protocol\TProtocol;
 use Thrift\Protocol\TMultiplexedProtocol;
-use Thrift\Protocol\TProtocolDecorator;
 use Thrift\Type\TMessageType;
 
 /**
@@ -116,28 +115,3 @@
         );
     }
 }
-
-/**
- *  Our goal was to work with any protocol. In order to do that, we needed
- *  to allow them to call readMessageBegin() and get the Message in exactly
- *  the standard format, without the service name prepended to the Message name.
- */
-class StoredMessageProtocol extends TProtocolDecorator
-{
-    private $fname_, $mtype_, $rseqid_;
-
-    public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid)
-    {
-        parent::__construct($protocol);
-        $this->fname_  = $fname;
-        $this->mtype_  = $mtype;
-        $this->rseqid_ = $rseqid;
-    }
-
-    public function readMessageBegin(&$name, &$type, &$seqid)
-    {
-        $name  = $this->fname_;
-        $type  = $this->mtype_;
-        $seqid = $this->rseqid_;
-    }
-}
diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am
index c872b1a..c4dcde3 100755
--- a/lib/php/test/Makefile.am
+++ b/lib/php/test/Makefile.am
@@ -17,6 +17,8 @@
 # under the License.
 #
 
+PHPUNIT=php $(top_srcdir)/vendor/bin/phpunit
+
 stubs: ../../../test/ThriftTest.thrift  TestValidators.thrift
 	mkdir -p ./packages
 	$(THRIFT) --gen php -r --out ./packages ../../../test/ThriftTest.thrift
@@ -27,23 +29,24 @@
 	$(THRIFT) --gen php:validate,oop -r --out ./packages/phpvo  TestValidators.thrift
 	$(THRIFT) --gen php:json         -r --out ./packages/phpjs  TestValidators.thrift
 
-check-json-serializer: stubs
-if HAVE_PHPUNIT
-	$(PHPUNIT) --log-junit=TEST-json-serializer.xml Test/Thrift/JsonSerialize/
-endif
+deps: $(top_srcdir)/composer.json
+	composer install --working-dir=$(top_srcdir)
 
-check-validator: stubs
+all-local: deps
+
+check-json-serializer: deps stubs
+	$(PHPUNIT) --log-junit=TEST-json-serializer.xml Test/Thrift/JsonSerialize/
+
+check-validator: deps stubs
 	php Test/Thrift/TestValidators.php
 	php Test/Thrift/TestValidators.php -oop
 
-check-protocol:	stubs
-if HAVE_PHPUNIT
+check-protocol:	deps stubs
 	$(PHPUNIT) --log-junit=TEST-log-json-protocol.xml Test/Thrift/Protocol/TestTJSONProtocol.php
 	$(PHPUNIT) --log-junit=TEST-binary-serializer.xml Test/Thrift/Protocol/TestBinarySerializer.php
 	$(PHPUNIT) --log-junit=TEST-log-simple-json-protocol.xml Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
-endif
 
-check: stubs \
+check: deps stubs \
   check-protocol \
   check-validator \
   check-json-serializer
@@ -55,5 +58,3 @@
 EXTRA_DIST = \
 	Test \
 	TestValidators.thrift
-
-
diff --git a/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php b/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php
index 2471b52..a6b0e7b 100644
--- a/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php
+++ b/lib/php/test/Test/Thrift/JsonSerialize/JsonSerializeTest.php
@@ -23,11 +23,9 @@
 use stdClass;
 use Thrift\ClassLoader\ThriftClassLoader;
 
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../../../../../vendor/autoload.php';
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
 $loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages/phpjs');
 $loader->register();
 
diff --git a/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php b/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php
index a983216..b30cf3d 100644
--- a/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php
+++ b/lib/php/test/Test/Thrift/Protocol/TestBinarySerializer.php
@@ -26,11 +26,9 @@
 use Thrift\ClassLoader\ThriftClassLoader;
 use Thrift\Serializer\TBinarySerializer;
 
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../../../../../vendor/autoload.php';
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
 $loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
 $loader->register();
 
diff --git a/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php b/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php
old mode 100755
new mode 100644
index a4ca9d5..a41b081
--- a/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php
+++ b/lib/php/test/Test/Thrift/Protocol/TestTJSONProtocol.php
@@ -30,11 +30,9 @@
 
 define( 'BUFSIZ', 8192 ); //big enough to read biggest serialized Fixture arg.
 
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../../../../../vendor/autoload.php';
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
 $loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
 $loader->register();
 
diff --git a/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php b/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
old mode 100755
new mode 100644
index 973f55c..5a8e9e6
--- a/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
+++ b/lib/php/test/Test/Thrift/Protocol/TestTSimpleJSONProtocol.php
@@ -30,11 +30,9 @@
 
 define( 'BUFSIZ', 8192 ); //big enough to read biggest serialized Fixture arg.
 
-require_once __DIR__.'/../../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../../../../../vendor/autoload.php';
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../../lib');
-$loader->registerNamespace('Test', __DIR__ . '/../../..');
 $loader->registerDefinition('ThriftTest', __DIR__ . '/../../../packages');
 $loader->register();
 
diff --git a/lib/php/test/Test/Thrift/TestValidators.php b/lib/php/test/Test/Thrift/TestValidators.php
index 36cf000..a6c13c5 100644
--- a/lib/php/test/Test/Thrift/TestValidators.php
+++ b/lib/php/test/Test/Thrift/TestValidators.php
@@ -18,9 +18,9 @@
  * under the License.
  */
 
-namespace test\php;
+namespace Test\Thrift;
 
-require_once __DIR__.'/../../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../../../../vendor/autoload.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 use Thrift\Exception\TProtocolException;
@@ -31,7 +31,6 @@
 $GEN_DIR = $oop_mode ? 'phpvo' : 'phpv';
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../../lib');
 $loader->registerDefinition('ThriftTest', __DIR__ . '/../../packages/' . $GEN_DIR);
 $loader->registerDefinition('TestValidators', __DIR__ . '/../../packages/' . $GEN_DIR);
 $loader->register();
diff --git a/test/php/TestClient.php b/test/php/TestClient.php
index 1591027..aa42e09 100755
--- a/test/php/TestClient.php
+++ b/test/php/TestClient.php
@@ -2,7 +2,7 @@
 
 namespace test\php;
 
-require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
+require_once __DIR__.'/../../vendor/autoload.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
@@ -14,7 +14,6 @@
 }
 
 $loader = new ThriftClassLoader();
-$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');
 if ($GEN_DIR === 'gen-php-psr4') {
   $loader->registerNamespace('ThriftTest', $GEN_DIR);
 } else {